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, 2021-2022 -- leonerd@leonerd.org.uk |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package XS::Parse::Infix 0.28; |
7
|
|
|
|
|
|
|
|
8
|
2
|
|
|
2
|
|
2590
|
use v5.14; |
|
2
|
|
|
|
|
9
|
|
9
|
2
|
|
|
2
|
|
10
|
use warnings; |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
1304
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# No actual .xs file; the code is implemented in XS::Parse::Keyword |
12
|
|
|
|
|
|
|
require XS::Parse::Keyword; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
C - XS functions to assist in parsing infix operators |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 DESCRIPTION |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
This module provides some XS functions to assist in writing syntax modules |
21
|
|
|
|
|
|
|
that provide new infix operators as perl syntax, primarily for authors of |
22
|
|
|
|
|
|
|
syntax plugins. It is unlikely to be of much use to anyone else; and highly |
23
|
|
|
|
|
|
|
unlikely to be of any use when writing perl code using these. Unless you are |
24
|
|
|
|
|
|
|
writing a syntax plugin using XS, this module is not for you. |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
This module is also currently experimental, and the design is still evolving |
27
|
|
|
|
|
|
|
and subject to change. Later versions may break ABI compatibility, requiring |
28
|
|
|
|
|
|
|
changes or at least a rebuild of any module that depends on it. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
In addition, the places this functionality can be used are relatively small. |
31
|
|
|
|
|
|
|
No current release of perl actually supports custom infix operators, though I |
32
|
|
|
|
|
|
|
have a branch where I am currently experimenting with such support: |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
L |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
In addition, the various C token types of L |
37
|
|
|
|
|
|
|
support querying on this module, so some syntax provided by other modules may |
38
|
|
|
|
|
|
|
be able to make use of these new infix operators. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=cut |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head1 CONSTANTS |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head2 HAVE_PL_INFIX_PLUGIN |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
if( XS::Parse::Infix::HAVE_PL_INFIX_PLUGIN ) { ... } |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
This constant is true if built on a perl that supports the C |
49
|
|
|
|
|
|
|
extension mechanism, meaning that custom infix operators registered with this |
50
|
|
|
|
|
|
|
module will actually be recognised by the perl parser. |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
No actual production or development releases of perl yet support this feature, |
53
|
|
|
|
|
|
|
but see above for details of a branch which does. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=cut |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head1 XS FUNCTIONS |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head2 boot_xs_parse_infix |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
void boot_xs_parse_infix(double ver); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
Call this function from your C section in order to initialise the module |
64
|
|
|
|
|
|
|
and parsing hooks. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
I should either be 0 or a decimal number for the module version |
67
|
|
|
|
|
|
|
requirement; e.g. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
boot_xs_parse_infix(0.14); |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head2 parse_infix |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
bool parse_infix(enum XSParseInfixSelection select, struct XSParseInfixInfo **infop); |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
I |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
This function attempts to parse syntax for an infix operator from the current |
78
|
|
|
|
|
|
|
parser position. If it is successful, it fills in the variable pointed to by |
79
|
|
|
|
|
|
|
I with a pointer to the actual information structure and returns |
80
|
|
|
|
|
|
|
C. If no suitable operator is found, returns C. |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
=head2 xs_parse_infix_new_op |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
OP *xs_parse_infix_new_op(const struct XSParseInfixInfo *info, U32 flags, |
85
|
|
|
|
|
|
|
OP *lhs, OP *rhs); |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
This function constructs a new optree fragment to represent invoking the infix |
88
|
|
|
|
|
|
|
operator with the given operands. It should be used much the same as core |
89
|
|
|
|
|
|
|
perl's C function. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
The C structure pointer would be obtained from the C field of the |
92
|
|
|
|
|
|
|
result of invoking the various C token types from |
93
|
|
|
|
|
|
|
C, or by calling L directly. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head2 register_xs_parse_infix |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
void register_xs_parse_infix(const char *opname, |
98
|
|
|
|
|
|
|
const struct XSParseInfixHooks *hooks, void *hookdata); |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
This function installs a set of parsing hooks to be associated with the given |
101
|
|
|
|
|
|
|
operator name. This new operator will then be available via |
102
|
|
|
|
|
|
|
L by the various C token types, |
103
|
|
|
|
|
|
|
L, or to core perl's C if available. |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
These tokens will all yield an info structure, with the following fields: |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
struct XSParseInfixInfo { |
108
|
|
|
|
|
|
|
const char *opname; |
109
|
|
|
|
|
|
|
OPCODE opcode; /* for built-in operators, or OP_CUSTOM for |
110
|
|
|
|
|
|
|
custom-registered ones */ |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
struct XSParseInfixHooks *hooks; |
113
|
|
|
|
|
|
|
void *hookdata; |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
enum XSParseInfixClassification cls; /* since version 0.28 */ |
116
|
|
|
|
|
|
|
}; |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
If the operator name contains any non-ASCII characters they are presumed to be |
119
|
|
|
|
|
|
|
in UTF-8 encoding. This will matter for deparse purposes. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=cut |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head1 PARSE HOOKS |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
The C structure provides the following fields which are |
126
|
|
|
|
|
|
|
used at various stages of parsing. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
struct XSParseInfixHooks { |
129
|
|
|
|
|
|
|
U16 flags; /* currently ignored */ |
130
|
|
|
|
|
|
|
U8 lhs_flags; |
131
|
|
|
|
|
|
|
U8 rhs_flags; |
132
|
|
|
|
|
|
|
enum XSParseInfixClassification cls; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
const char *wrapper_func_name; |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
const char *permit_hintkey; |
137
|
|
|
|
|
|
|
bool (*permit)(pTHX_ void *hookdata); |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
OP *(*new_op)(pTHX_ U32 flags, OP *lhs, OP *rhs, ANY *parsedata, void *hookdata); |
140
|
|
|
|
|
|
|
OP *(*ppaddr)(pTHX); |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
/* optional */ |
143
|
|
|
|
|
|
|
void (*parse)(pTHX_ U32 flags, ANY *parsedata, void *hookdata); |
144
|
|
|
|
|
|
|
}; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 Flags |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
The C field is currently ignored. It is defined simply to reserve the |
149
|
|
|
|
|
|
|
space in case used in a later version. It should be set to zero. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
The C and C fields give details on how to handle the |
152
|
|
|
|
|
|
|
left- and right-hand side operands, respectively. |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
It should be set to one of the following constants, or left as zero: |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
=over 4 |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=item XPI_OPERAND_TERM_LIST |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
The operand will be foced into list context, preserving the C at |
161
|
|
|
|
|
|
|
the beginning. This means that the ppfunc for this infix operator will have to |
162
|
|
|
|
|
|
|
C to find that. |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
=item XPI_OPERAND_LIST |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
The same as above. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=back |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Older versions used to provide constants named C and |
171
|
|
|
|
|
|
|
C but they related to an older version of the core perl |
172
|
|
|
|
|
|
|
branch. These names are now aliases for zero, and can be removed from new |
173
|
|
|
|
|
|
|
code. |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
In addition the following extra bitflags are defined: |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=over 4 |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=item XPI_OPERAND_ONLY_LOOK |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
If set, the operator function promises that it will not mutate any of its |
182
|
|
|
|
|
|
|
passed values, nor allow leaking of direct alias pointers to them via return |
183
|
|
|
|
|
|
|
value or other locations. |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
This flag is optional; omitting it when applicable will not change any |
186
|
|
|
|
|
|
|
observed behaviour. Setting it may enable certain optimisations to be |
187
|
|
|
|
|
|
|
performed. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
Currently, this flag simply enables an optimisation in the call-checker for |
190
|
|
|
|
|
|
|
infix operator wrapper functions that take list-shaped operands. This |
191
|
|
|
|
|
|
|
optimisation discards an C operation which would create a |
192
|
|
|
|
|
|
|
temporary anonymous array reference for its operand values, allowing a slight |
193
|
|
|
|
|
|
|
saving of memory use and CPU time. This optimisation is only safe to perform |
194
|
|
|
|
|
|
|
if the operator does not mutate or retain aliases of any of the arguments, as |
195
|
|
|
|
|
|
|
otherwise the caller might see unexpected modifications or value references to |
196
|
|
|
|
|
|
|
the values passed. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=back |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=head2 The Selection Stage |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
The C field gives a "classification" of the operator, suggesting what |
203
|
|
|
|
|
|
|
sort of operation it provides. This is used as a filter by the various |
204
|
|
|
|
|
|
|
C selection macros. |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
The classification should be one of the C constants found and |
207
|
|
|
|
|
|
|
described further in the main F file. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=head2 The C Stage |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
As a shortcut for the common case, the C may point to a string |
212
|
|
|
|
|
|
|
to look up from the hints hash. If the given key name is not found in the |
213
|
|
|
|
|
|
|
hints hash then the keyword is not permitted. If the key is present then the |
214
|
|
|
|
|
|
|
C function is invoked as normal. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
If not rejected by a hint key that was not found in the hints hash, the |
217
|
|
|
|
|
|
|
function part of the stage is called next and should inspect whether the |
218
|
|
|
|
|
|
|
keyword is permitted at this time perhaps by inspecting other lexical clues, |
219
|
|
|
|
|
|
|
and return true only if the keyword is permitted. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Both the string and the function are optional. Either or both may be present. |
222
|
|
|
|
|
|
|
If neither is present then the keyword is always permitted - which is likely |
223
|
|
|
|
|
|
|
not what you wanted to do. |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=head2 The C Stage |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
If the optional C hook function is present, it is called immediately |
228
|
|
|
|
|
|
|
after the parser has recognised the presence of the named operator itself but |
229
|
|
|
|
|
|
|
before it attempts to consume the right-hand side term. This hook function can |
230
|
|
|
|
|
|
|
attempt further parsing, in order to implement more complex syntax such as |
231
|
|
|
|
|
|
|
hyper-operators. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
When invoked, it is passed a pointer to an C-typed storage variable. It |
234
|
|
|
|
|
|
|
is free to use whichever field of this variable it desires to store a result, |
235
|
|
|
|
|
|
|
which will then later be made available to the C function. |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=head2 The Op Generation Stage |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
If the infix operator is going to be used, then one of the C or the |
240
|
|
|
|
|
|
|
C fields explain how to create a new optree fragment. |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
If C is defined then it will be used, and is expected to return an |
243
|
|
|
|
|
|
|
optree fragment that consumes the LHS and RHS arguments to implement the |
244
|
|
|
|
|
|
|
semantics of the operator. If the optional C stage had been present |
245
|
|
|
|
|
|
|
earlier, the C pointer passed here will point to the same storage that |
246
|
|
|
|
|
|
|
C had previously had access to, so it can retrieve the results. |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
If C is not present, then the C will be used instead to |
249
|
|
|
|
|
|
|
construct a new BINOP of the C type. If an earlier C stage |
250
|
|
|
|
|
|
|
had stored additional results into the C variable these will be lost |
251
|
|
|
|
|
|
|
here. |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
=head2 The Wrapper Function |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
Additionally, if the C field is set to a string, this gives |
256
|
|
|
|
|
|
|
the (fully-qualified) name for a function to be generated as part of |
257
|
|
|
|
|
|
|
registering the operator. This newly-generated function will act as a wrapper |
258
|
|
|
|
|
|
|
for the operator. |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
For operators whose RHS is a scalar, the wrapper function is assumed to take |
261
|
|
|
|
|
|
|
two simple scalar arguments. The result of invoking the function on those |
262
|
|
|
|
|
|
|
arguments will be determined by using the operator code. |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
$result = $lhs OP $rhs; |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
$result = WRAPPERFUNC( $lhs, $rhs ); |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
For operators whose RHS is a list, the wrapper function takes at least one |
269
|
|
|
|
|
|
|
argument, possibly more. The first argument is the scalar on the LHS, and the |
270
|
|
|
|
|
|
|
remaining arguments, however many there are, form the RHS: |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
$result = $lhs OP @rhs; |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
$result = WRAPPERFUNC( $lhs, @rhs ); |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
For operators whose LHS and RHS is a list, the wrapper function takes two |
277
|
|
|
|
|
|
|
arguments which must be array references containing the lists. |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
$result = @lhs OP @rhs; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
$result = WRAPPERFUNC( \@lhs, \@rhs ); |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
This creates a convenience for accessing the operator from perls that do not |
284
|
|
|
|
|
|
|
support C. |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
In the case of scalar infix operators, the wrapper function also includes a |
287
|
|
|
|
|
|
|
call-checker which attempts to inline the operator directly into the callsite. |
288
|
|
|
|
|
|
|
Thus, in simple cases where the function is called directly on exactly two |
289
|
|
|
|
|
|
|
scalar arguments (such as in the following), no C overhead will be |
290
|
|
|
|
|
|
|
incurred and the generated optree will be identical to that which would have |
291
|
|
|
|
|
|
|
been generated by using infix operator syntax directly: |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
WRAPPERFUNC( $lhs, $rhs ); |
294
|
|
|
|
|
|
|
WRAPPERFUNC( $lhs, CONSTANT ); |
295
|
|
|
|
|
|
|
WRAPPERFUNC( $args[0], $args[1] ); |
296
|
|
|
|
|
|
|
WRAPPERFUNC( $lhs, scalar otherfunc() ); |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
The checker is very pessimistic and will only rewrite callsites where it |
299
|
|
|
|
|
|
|
determines this can be done safely. It will not rewrite any of the following |
300
|
|
|
|
|
|
|
forms: |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
WRAPPERFUNC( $onearg ); # not enough args |
303
|
|
|
|
|
|
|
WRAPPERFUNC( $x, $y, $z ); # too many args |
304
|
|
|
|
|
|
|
WRAPPERFUNC( @args[0,1] ); # not a scalar |
305
|
|
|
|
|
|
|
WRAPPERFUNC( $lhs, otherfunc() ); # not a scalar |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
The wrapper function for infix operators which take lists on both sides also |
308
|
|
|
|
|
|
|
has a call-checker which will attempt to inline the operator in similar |
309
|
|
|
|
|
|
|
circumstances. In addition to the optimisations described above for scalar |
310
|
|
|
|
|
|
|
operators, this checker will also inline an array-reference operator and omit |
311
|
|
|
|
|
|
|
the resulting dereference behaviour. Thus, the two following lines emit the |
312
|
|
|
|
|
|
|
same optree, without an C or C: |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
@lhs OP @rhs; |
315
|
|
|
|
|
|
|
WRAPPERFUNC( \@lhs, \@rhs ); |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
B that technically, this optimisation isn't strictly transparent in the |
318
|
|
|
|
|
|
|
odd cornercase that one of the referenced arrays is also the backing store for |
319
|
|
|
|
|
|
|
a blessed object reference, and that object class has a C<@{}> overload. |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
my @arr; |
322
|
|
|
|
|
|
|
package SomeClass { |
323
|
|
|
|
|
|
|
use overload '@{}' => sub { return ["values", "go", "here"]; }; |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
bless \@arr, "SomeClass"; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# this will not actually invoke the overload operator |
328
|
|
|
|
|
|
|
WRAPPERFUNC( \@arr, [4, 5, 6] ); |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
As this cornercase relates to taking duplicate references to the same blessed |
331
|
|
|
|
|
|
|
object's backing store variable, it should not matter to any real code; |
332
|
|
|
|
|
|
|
regular objects that are passed by reference into the wrapper function will |
333
|
|
|
|
|
|
|
run their overload methods as normal. |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
The callchecker for list operands can optionally also discard an op of the |
336
|
|
|
|
|
|
|
C type, which is used by anonymous array-ref construction: |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
($u, $v, $w) OP ($x, $y, $z); |
339
|
|
|
|
|
|
|
WRAPPERFUNC( [$u, $v, $w], [$x, $y, $z] ); |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
This optimisation is only performed if the operator declared it safe to do so, |
342
|
|
|
|
|
|
|
via the C flag. |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
If a function of the given name already exists at registration time it will be |
345
|
|
|
|
|
|
|
left undisturbed and no new wrapper will be created. This permits the same |
346
|
|
|
|
|
|
|
infix operator to have multiple spellings of its name; for example to allow |
347
|
|
|
|
|
|
|
both a real Unicode and a fallback ASCII transliteration of the same operator. |
348
|
|
|
|
|
|
|
The first registration will create the wrapper function; the subsequent one |
349
|
|
|
|
|
|
|
will skip it because it would otherwise be identical. |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
Note that when generating an optree for a wrapper function call, the C |
352
|
|
|
|
|
|
|
hook function will be invoked with a C pointer for the C-typed |
353
|
|
|
|
|
|
|
parse data storage, as there won't be an opporunity for the C hook to |
354
|
|
|
|
|
|
|
run in this case. |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
=cut |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=head1 DEPARSE |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
This module operates with L in order to automatically provide |
361
|
|
|
|
|
|
|
deparse support for infix operators. Every infix operator that is implemented |
362
|
|
|
|
|
|
|
as a custom op (and thus has the C hook field set) will have deparse |
363
|
|
|
|
|
|
|
logic added. This will allow it to deparse to either the named wrapper |
364
|
|
|
|
|
|
|
function, or to the infix operator syntax if on a C-enabled |
365
|
|
|
|
|
|
|
perl and the appropriate lexical hint is enabled at the callsite. |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
In order for this to work, it is important that your custom operator is I |
368
|
|
|
|
|
|
|
registered as a custom op using the C function. |
369
|
|
|
|
|
|
|
This registration will be performed by C itself at the time |
370
|
|
|
|
|
|
|
the infix operator is registered. |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
=cut |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
sub B::Deparse::_deparse_infix_wrapperfunc_scalarscalar |
375
|
|
|
|
|
|
|
{ |
376
|
1
|
|
|
1
|
|
14572
|
my ( $self, $wrapper_func_name, $op, $ctx ) = @_; |
377
|
|
|
|
|
|
|
|
378
|
1
|
|
|
|
|
5
|
my $lhs = $op->first; |
379
|
1
|
|
|
|
|
6
|
my $rhs = $op->last; |
380
|
|
|
|
|
|
|
|
381
|
1
|
|
|
|
|
374
|
$_ = $self->deparse( $_, 6 ) for $lhs, $rhs; |
382
|
|
|
|
|
|
|
|
383
|
1
|
|
|
|
|
141
|
return "$wrapper_func_name($lhs, $rhs)"; |
384
|
|
|
|
|
|
|
} |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub B::Deparse::_deparse_infix_wrapperfunc_listlist |
387
|
|
|
|
|
|
|
{ |
388
|
4
|
|
|
4
|
|
5080
|
my ( $self, $wrapper_func_name, $op, $ctx ) = @_; |
389
|
|
|
|
|
|
|
|
390
|
4
|
|
|
|
|
17
|
my $lhs = $op->first; |
391
|
4
|
|
|
|
|
16
|
my $rhs = $op->last; |
392
|
|
|
|
|
|
|
|
393
|
4
|
|
|
|
|
14
|
foreach my $var ( \$lhs, \$rhs ) { |
394
|
8
|
|
|
|
|
14
|
my $argop = $$var; |
395
|
8
|
|
|
|
|
14
|
my $kid; |
396
|
|
|
|
|
|
|
|
397
|
8
|
100
|
33
|
|
|
174
|
if( $argop->name eq "null" and |
|
|
|
33
|
|
|
|
|
|
|
|
66
|
|
|
|
|
398
|
|
|
|
|
|
|
$argop->first->name eq "pushmark" and |
399
|
|
|
|
|
|
|
($kid = $argop->first->sibling) and |
400
|
|
|
|
|
|
|
B::Deparse::null($kid->sibling) ) { |
401
|
7
|
|
|
|
|
30
|
my $add_refgen; |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
# A list of a single item |
404
|
7
|
100
|
100
|
|
|
68
|
if( $kid->name eq "rv2av" and $kid->first->name ne "gv" ) { |
|
|
50
|
66
|
|
|
|
|
405
|
3
|
|
|
|
|
11
|
$argop = $kid->first; |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
elsif( $kid->name eq "padav" or $kid->name eq "rv2av" ) { |
408
|
4
|
|
|
|
|
10
|
$add_refgen++; |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
else { |
411
|
0
|
|
|
|
|
0
|
print STDERR "Maybe UNWRAP list ${\ $kid->name }\n"; |
|
0
|
|
|
|
|
0
|
|
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
|
414
|
7
|
|
|
|
|
847
|
$$var = $self->deparse( $argop, 6 ); |
415
|
|
|
|
|
|
|
|
416
|
7
|
100
|
|
|
|
56
|
$$var = "\\$$var" if $add_refgen; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
else { |
419
|
|
|
|
|
|
|
# Pretend the entire list was anonlist |
420
|
1
|
|
|
|
|
12
|
my @args; |
421
|
1
|
|
|
|
|
11
|
$argop = $argop->first->sibling; # skip pushmark |
422
|
1
|
|
|
|
|
11
|
while( not B::Deparse::null($argop) ) { |
423
|
2
|
|
|
|
|
40
|
push @args, $self->deparse( $argop, 6 ); |
424
|
2
|
|
|
|
|
17
|
$argop = $argop->sibling; |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
1
|
|
|
|
|
7
|
$$var = "[" . join( ", ", @args ) . "]"; |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
4
|
|
|
|
|
334
|
return "$wrapper_func_name($lhs, $rhs)"; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
sub B::Deparse::_deparse_infix_named |
435
|
|
|
|
|
|
|
{ |
436
|
0
|
|
|
0
|
|
|
my ( $self, $opname, $op, $ctx ) = @_; |
437
|
|
|
|
|
|
|
|
438
|
0
|
|
|
|
|
|
my $lhs = $op->first; |
439
|
0
|
|
|
|
|
|
my $rhs = $op->last; |
440
|
|
|
|
|
|
|
|
441
|
0
|
|
|
|
|
|
return join " ", |
442
|
|
|
|
|
|
|
$self->deparse_binop_left( $op, $lhs, 14 ), |
443
|
|
|
|
|
|
|
$opname, |
444
|
|
|
|
|
|
|
$self->deparse_binop_right( $op, $rhs, 14 ); |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=head1 TODO |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=over 4 |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
=item * |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
Have the entersub checker for list/list operators unwrap arrayref or |
454
|
|
|
|
|
|
|
anon-array argument forms (C or |
455
|
|
|
|
|
|
|
C). |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
=item * |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
Further thoughts about how infix operators with C hooks will work with |
460
|
|
|
|
|
|
|
automatic deparse, and also how to integrate them with L's |
461
|
|
|
|
|
|
|
grammar piece. |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=back |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=cut |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
=head1 AUTHOR |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
Paul Evans |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
=cut |
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
0x55AA; |