File Coverage

lib/B/DeparseTree/PP_OPtable.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             # Copyright (c) 2018 Rocky Bernstein
2              
3             # A table-driven mapping from Perl PP ops e.g pp_accept, pp_aeach,
4             # ... to a compact list of function names with arguments that
5             # implements them.
6              
7             package B::DeparseTree::PP_OPtable;
8              
9 3     3   19 use warnings; use strict;
  3     3   8  
  3         83  
  3         16  
  3         5  
  3         174  
10             our($VERSION, @EXPORT, @ISA);
11             $VERSION = '3.2.0';
12             @ISA = qw(Exporter);
13              
14 3     3   25 use vars qw(%PP_MAPFNS);
  3         20  
  3         146  
15              
16 3     3   16 use constant ASSIGN => 2; # operation OP has a =OP variant
  3         4  
  3         2266  
17              
18              
19             # In the HASH below, the key is the operation name with the leading pp_ stripped.
20             # so "die" refers to function "pp_die". The value can be several things.
21             #
22             # If the table value is a string, then that function is called with a standard
23             # set of parameters. For example, consider:
24             # 'die' => 'listop'.
25             #
26             # The above indicates that for the pp_die operation we should call listop
27             # with standard parameters $self, $op, and the key value, e.g
28             # "die". This replaces B::Deparse equivalent:
29             # sub pp_die { $self->listop($op, $cx, "die"); }
30             #
31             # If the table value is not a string, it will be an array reference, and here
32             # the entries may be subject to interpretation based on the function name.
33             #
34             # For the most part, when there are two entries, it is similar to the string case,
35             # but instead of passing the key name as a parameter, the string second parameter
36             # is used. For example:
37             # 'ghostent' => ['baseop', "gethostent"],
38             # replaces the B::Deparse equivalent:
39             # sub pp_ghostent { $self->listop($op, $cx, "gethostent"); }
40              
41             # Precedences in binop are given by the following table
42              
43             # Precedences:
44             # 26 [TODO] inside interpolation context ("")
45             # 25 left terms and list operators (leftward)
46             # 24 left ->
47             # 23 nonassoc ++ --
48             # 22 right **
49             # 21 right ! ~ \ and unary + and -
50             # 20 left =~ !~
51             # 19 left * / % x
52             # 18 left + - .
53             # 17 left << >>
54             # 16 nonassoc named unary operators
55             # 15 nonassoc < > <= >= lt gt le ge
56             # 14 nonassoc == != <=> eq ne cmp
57             # 13 left &
58             # 12 left | ^
59             # 11 left &&
60             # 10 left ||
61             # 9 nonassoc .. ...
62             # 8 right ?:
63             # 7 right = += -= *= etc.
64             # 6 left , =>
65             # 5 nonassoc list operators (rightward)
66             # 4 right not
67             # 3 left and
68             # 2 left or xor
69             # 1 statement modifiers
70             # 0.5 statements, but still print scopes as do { ... }
71             # 0 statement level
72             # -1 format body
73              
74              
75             %PP_MAPFNS = (
76             # 'avalues' => ['unop', 'value'],
77             # 'values' => 'unop', # FIXME
78             # 'sselect' => 'listop', FIXME: is used in PPfns
79             # 'sockpair' => 'listop', ""
80              
81             'accept' => 'listop',
82             'add' => ['maybe_targmy', 'binop', '+', 18, ASSIGN],
83             'aeach' => ['unop', 'each'],
84             'akeys' => ['unop', 'keys'],
85             'alarm' => 'unop',
86             'andassign' => ['logassignop', '&&='],
87             'atan2' => ['maybe_targmy', 'listop'],
88              
89             'bind' => 'listop',
90             'binmode' => 'listop',
91             'bit_and' => ['maybe_targmy', 'binop', "&", 13, ASSIGN],
92             'bit_or' => ['maybe_targmy', 'binop', "|", 12, ASSIGN],
93             'bit_xor' => ['maybe_targmy', 'binop', "^", 12, ASSIGN],
94             'bless' => 'listop',
95             'break' => 'unop',
96              
97             'caller' => 'unop',
98             'chdir' => ['maybe_targmy', 'unop'], # modified below
99             'chr' => ['maybe_targmy', 'unop'],
100             'chroot' => ['maybe_targmy', 'unop'],
101             'close' => 'unop',
102             'closedir' => 'unop',
103             'connect' => 'listop',
104             'concat' => ['maybe_targmy', 'concat'],
105             'continue' => 'unop',
106              
107             'db_open' => 'listop',
108             'dbmclose' => 'unop',
109             'dbmopen' => 'listop',
110             'dbstate' => 'cops',
111             'defined' => 'unop',
112             'die' => 'listop',
113             'divide' => ['maybe_targmy', 'binop', "/", 19, ASSIGN],
114             'dorassign' => ['logassignop', '//='],
115             'dump' => ['loopex', "CORE::dump"],
116              
117             'each' => 'unop',
118             'egrent' => ['baseop', 'endgrent'],
119             'ehostent' => ['baseop', "endhostent"],
120             'enetent' => ['baseop', "endnetent"],
121             'eof' => 'unop',
122             'eprotoent' => ['baseop', "endprotoent"],
123             'epwent' => ['baseop', "endpwent"],
124             'eservent' => ['baseop', "endservent"],
125             'exit' => 'unop',
126              
127             'fc' => 'unop',
128             'fcntl' => 'listop',
129             'fileno' => 'unop',
130             'fork' => 'baseop',
131             'formline' => 'listop', # see also deparse_format
132             'ftatime' => ['filetest', "-A"],
133             'ftbinary' => ['filetest', "-B"],
134             'ftblk' => ['filetest', "-b"],
135             'ftchr' => ['filetest', "-c"],
136             'ftctime' => ['filetest', "-C"],
137             'ftdir' => ['filetest', "-d"],
138             'fteexec' => ['filetest', "-x"],
139             'fteowned' => ['filetest', "-O"],
140             'fteread' => ['filetest', "-r"],
141             'ftewrite' => ['filetest', "-w"],
142             'ftfile' => ['filetest', "-f"],
143             'ftis' => ['filetest', "-e"],
144             'ftlink' => ['filetest', "-l"],
145             'ftmtime' => ['filetest', "-M"],
146             'ftpipe' => ['filetest', "-p"],
147             'ftrexec' => ['filetest', "-X"],
148             'ftrowned' => ['filetest', "-o"],
149             'ftrread' => ['filetest', '-R'],
150             'ftrwrite' => ['filetest', "-W"],
151             'ftsgid' => ['filetest', "-g"],
152             'ftsize' => ['filetest', "-s"],
153             'ftsock' => ['filetest', "-S"],
154             'ftsuid' => ['filetest', "-u"],
155             'ftsvtx' => ['filetest', "-k"],
156             'fttext' => ['filetest', "-T"],
157             'fttty' => ['filetest', "-t"],
158             'ftzero' => ['filetest', "-z"],
159              
160             'getc' => 'unop',
161             'getlogin' => 'baseop',
162             'getpeername' => 'unop',
163             'getpgrp' => ['maybe_targmy', 'unop'],
164             'getsockname' => 'unop',
165             'ggrent' => ['baseop', "getgrent"],
166             'ggrgid' => ['unop', "getgrgid"],
167             'ggrnam' => ['unop', "getgrnam"],
168             'ghbyaddr' => ['listop', 'gethostbyaddr'],
169             'ghbyname' => ['unop', "gethostbyname"],
170             'ghostent' => ['baseop', "gethostent"],
171             'gmtime' => 'unop',
172             'gnbyaddr' => ['listop', "getnetbyaddr"],
173             'gnbyname' => ['unop', "getnetbyname"],
174             'gnetent' => ['baseop', "getnetent"],
175             'goto' => ['loopex', "goto"],
176             'gpbyname' => ['unop', "getprotobyname"],
177             'gpbynumber' => ['listop', 'getprotobynumber'],
178             'gprotoent' => ['baseop', "getprotoent"],
179             'gpwent' => ['baseop', "getpwent"],
180             'gpwnam' => ['unop', "getpwnam"],
181             'gpwuid' => ['unop', "getpwuid"],
182             'grepstart' => ['baseop', "grep"],
183             'gsbyname' => ['listop', 'getservbyname'],
184             'gsbyport' => ['listop', 'getservbyport'],
185             'gservent' => ['baseop', "getservent"],
186             'gsockopt' => ['listop', 'getsockopt'],
187              
188             'i_add' => ['maybe_targmy', 'binop', "+", 18, ASSIGN],
189             'i_divide' => ['maybe_targmy', 'binop', "/", 19, ASSIGN],
190             'i_modulo' => ['maybe_targmy', 'binop', "%", 19, ASSIGN],
191             'i_multiply' => ['maybe_targmy', 'binop', "*", 19, ASSIGN],
192             'i_subtract' => ['maybe_targmy', 'binop', "-", 18, ASSIGN],
193             'ioctl' => 'listop',
194             'keys' => 'unop',
195              
196             'last' => 'loopex',
197             'lc' => 'dq_unop',
198             'lcfirst' => 'dq_unop',
199             'left_shift' => ['maybe_targmy', 'binop', "<<", 17, ASSIGN],
200             'length' => ['maybe_targmy', 'unop'],
201             'listen' => 'listop',
202             'localtime' => 'unop',
203             'lock' => 'unop',
204             'lstat' => 'filetest',
205              
206             'modulo' => ['maybe_targmy', 'binop', "%", 19, ASSIGN],
207             'msgctl' => 'listop',
208             'msgget' => 'listop',
209             'msgrcv' => 'listop',
210             'msgsnd' => 'listop',
211             'multiply' => ['maybe_targmy', 'binop', '*', 19, ASSIGN],
212              
213             'nbit_and' => ['maybe_targmy', 'binop', "&", 13, ASSIGN],
214             'nbit_or' => ['maybe_targmy', 'binop', "|", 12, ASSIGN],
215             'nbit_xor' => ['maybe_targmy', 'binop', "^", 12, ASSIGN],
216             'next' => 'loopex',
217             'nextstate' => 'cops',
218              
219             'ord' => ['maybe_targmy', 'unop'],
220             'open' => 'listop',
221             'orassign' => ['logassignop', '||='],
222              
223             'padav' => 'pp_padsv',
224             'padhv' => 'pp_padsv',
225             'pack' => 'listop',
226             'pipe_op' => ['listop', 'pipe'],
227             'pop' => 'unop',
228             'pow' => ['maybe_targmy', 'binop', "**", 22, ASSIGN],
229             'prototype' => 'unop',
230              
231             'quotemeta' => ['maybe_targmy', 'dq_unop'],
232              
233             'read' => 'listop',
234             'readdir' => 'unop',
235             'readlink' => 'unop',
236             'recv' => 'listop',
237             'redo' => 'loopex',
238             'ref' => 'unop',
239             'repeat' => ['maybe_targmy', 'repeat'], # modified below
240             'reset' => 'unop',
241             'reverse' => 'listop',
242             'rewinddir' => 'unop',
243             'right_shift' => ['maybe_targmy', 'binop', ">>", 17, ASSIGN],
244             'rmdir' => ['maybe_targmy', 'unop'],
245             'runcv' => ['unop', '__SUB__'],
246              
247             'say' => 'indirop',
248             'seek' => 'listop',
249             'seekdir' => 'listop',
250             'select' => 'listop',
251             'semctl' => 'listop',
252             'semget' => 'listop',
253             'semop' => 'listop',
254             'send' => 'listop',
255             'setstate' => 'nextstate',
256             'sgrent' => ['baseop', "setgrent"],
257             'shift' => 'unop',
258             'shmctl' => 'listop',
259             'shmget' => 'listop',
260             'shmread' => 'listop',
261             'shmwrite' => 'listop',
262             'shostent' => ['unop', "sethostent"],
263             'shutdown' => 'listop',
264             'sleep' => ['maybe_targmy', 'unop'],
265             'snetent' => ['unop', "setnetent"],
266             'socket' => 'listop',
267             'sort' => "indirop",
268             'splice' => 'listop',
269             'sprotoent' => ['unop', "setprotoent"],
270             'spwent' => ['baseop', "setpwent"],
271             'srand' => 'unop',
272             'sselect' => ['listop', "select"],
273             'sservent' => ['unop', "setservent"],
274             'ssockopt' => ['listop', "setsockopt"],
275             'stat' => 'filetest',
276             'study' => 'unop',
277             'subtract' => ['maybe_targmy', 'binop', "-", 18, ASSIGN],
278             'syscall' => 'listop',
279             'sysopen' => 'listop',
280             'sysread' => 'listop',
281             'sysseek' => 'listop',
282             'syswrite' => 'listop',
283              
284             'tell' => 'unop',
285             'telldir' => 'unop',
286             'tie' => 'listop',
287             'tied' => 'unop',
288             'tms' => ['baseop', 'times'],
289              
290             'uc' => 'dq_unop',
291             'ucfirst' => 'dq_unop',
292             'umask' => 'unop',
293             'undef' => 'unop',
294             'unpack' => 'listop',
295             'untie' => 'unop',
296              
297             'warn' => 'listop',
298             );
299              
300              
301             # Version specific modification are next...
302 3     3   22 use Config;
  3         6  
  3         485  
303             my $is_cperl = $Config::Config{usecperl};
304              
305             if ($] >= 5.015000) {
306             # FIXME is it starting in cperl 5.26+ which add this?
307             $PP_MAPFNS{'srefgen'} = 'pp_refgen';
308             }
309             if ($is_cperl) {
310             # FIXME reconcile differences in cperl. Maybe cperl is right?
311             delete $PP_MAPFNS{'chdir'};
312             }
313              
314             if ($] < 5.012000) {
315             # Earlier than 5.12 doesn't use "targmy"?
316             $PP_MAPFNS{'repeat'} = 'repeat';
317             }
318              
319             @EXPORT = qw(%PP_MAPFNS);
320              
321             1;