This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
2ed797ac7e1ace76a2c8adf8b6e5a03bb5f56bd8
[perl5.git] / lib / B / Deparse-core.t
1 #!./perl
2
3 # Test the core keywords.
4 #
5 # Initially this test file just checked that CORE::foo got correctly
6 # deparsed as CORE::foo, hence the name. It's since been expanded
7 # to fully test both CORE:: versus none, plus that any arguments
8 # are correctly deparsed. It also cross-checks against regen/keywords.pl
9 # to make sure we've tested all keywords, and with the correct strength.
10 #
11 # A keyword can be either weak or strong. Strong keywords can never be
12 # overridden, while weak ones can. So deparsing of weak keywords depends
13 # on whether a sub of that name has been created:
14 #
15 # for both:         keyword(..) deparsed as keyword(..)
16 # for weak:   CORE::keyword(..) deparsed as CORE::keyword(..)
17 # for strong: CORE::keyword(..) deparsed as keyword(..)
18 #
19 # Three permutations of lex/nonlex args are checked for:
20 #
21 #   foo($a,$b,$c,...)
22 #   foo(my $a,$b,$c,...)
23 #   my ($a,$b,$c,...); foo($a,$b,$c,...)
24 #
25 # Note that tests for prefixing feature.pm-enabled keywords with CORE:: when
26 # feature.pm is not enabled are in deparse.t, as they fit that format better.
27
28
29 BEGIN {
30     require Config;
31     if (($Config::Config{extensions} !~ /\bB\b/) ){
32         print "1..0 # Skip -- Perl configured without B module\n";
33         exit 0;
34     }
35 }
36
37 use strict;
38 use Test::More;
39 plan tests => 3886;
40
41 use feature (sprintf(":%vd", $^V)); # to avoid relying on the feature
42                                     # logic to add CORE::
43 use B::Deparse;
44 my $deparse = new B::Deparse;
45
46 my %SEEN;
47 my %SEEN_STRENGH;
48
49 # for a given keyword, create a sub of that name, then
50 # deparse "() = $expr", and see if it matches $expected_expr
51
52 sub testit {
53     my ($keyword, $expr, $expected_expr, $lexsub) = @_;
54
55     $expected_expr //= $expr;
56     $SEEN{$keyword} = 1;
57
58
59     # lex=0:   () = foo($a,$b,$c)
60     # lex=1:   my ($a,$b); () = foo($a,$b,$c)
61     # lex=2:   () = foo(my $a,$b,$c)
62     for my $lex (0, 1, 2) {
63         if ($lex) {
64             next if $keyword =~ /local|our|state|my/;
65         }
66         my $vars = $lex == 1 ? 'my($a, $b, $c, $d, $e);' . "\n    " : "";
67
68         if ($lex == 2) {
69             my $repl = 'my $a';
70             if ($expr =~ 'CORE::do') {
71                 # do foo() is a syntax error, so B::Deparse emits
72                 # do (foo()), but does not distinguish between foo and my,
73                 # because it is too complicated.
74                 $repl = '(my $a)';
75             }
76             s/\$a/$repl/ for $expr, $expected_expr;
77         }
78
79         my $desc = "$keyword: lex=$lex $expr => $expected_expr";
80         $desc .= " (lex sub)" if $lexsub;
81
82
83         my $code_ref;
84         if ($lexsub) {
85             package lexsubtest;
86             no warnings 'experimental::lexical_subs';
87             use feature 'lexical_subs';
88             no strict 'vars';
89             $code_ref =
90                 eval "sub { state sub $keyword; ${vars}() = $expr }"
91                             || die "$@ in $expr";
92         }
93         else {
94             package test;
95             use subs ();
96             import subs $keyword;
97             $code_ref = eval "no strict 'vars'; sub { ${vars}() = $expr }"
98                             or die "$@ in $expr";
99         }
100
101         my $got_text = $deparse->coderef2text($code_ref);
102
103         unless ($got_text =~ /
104     package (?:lexsub)?test;
105 (?:    BEGIN \{\$\{\^WARNING_BITS\} = "[^"]+"\}
106 )?    use strict 'refs', 'subs';
107     use feature [^\n]+
108 (?:    (?:CORE::)?state sub \w+;
109 )?    \Q$vars\E\(\) = (.*)
110 \}/s) {
111             ::fail($desc);
112             ::diag("couldn't extract line from boilerplate\n");
113             ::diag($got_text);
114             return;
115         }
116
117         my $got_expr = $1;
118         is $got_expr, $expected_expr, $desc;
119     }
120 }
121
122
123 # Deparse can't distinguish 'and' from '&&' etc
124 my %infix_map = qw(and && or ||);
125
126
127 # test a keyword that is a binary infix operator, like 'cmp'.
128 # $parens - "$a op $b" is deparsed as "($a op $b)"
129 # $strong - keyword is strong
130
131 sub do_infix_keyword {
132     my ($keyword, $parens, $strong) = @_;
133     $SEEN_STRENGH{$keyword} = $strong;
134     my $expr = "(\$a $keyword \$b)";
135     my $nkey = $infix_map{$keyword} // $keyword;
136     my $expr = "(\$a $keyword \$b)";
137     my $exp = "\$a $nkey \$b";
138     $exp = "($exp)" if $parens;
139     $exp .= ";";
140     # with infix notation, a keyword is always interpreted as core,
141     # so no need for Deparse to disambiguate with CORE::
142     testit $keyword, "(\$a CORE::$keyword \$b)", $exp;
143     testit $keyword, "(\$a $keyword \$b)", $exp;
144     testit $keyword, "(\$a CORE::$keyword \$b)", $exp, 1;
145     testit $keyword, "(\$a $keyword \$b)", $exp, 1;
146     if (!$strong) {
147         # B::Deparse fully qualifies any sub whose name is a keyword,
148         # imported or not, since the importedness may not be reproduced by
149         # the deparsed code.  x is special.
150         my $pre = "test::" x ($keyword ne 'x');
151         testit $keyword, "$keyword(\$a, \$b)", "$pre$keyword(\$a, \$b);";
152     }
153     testit $keyword, "$keyword(\$a, \$b)", "$keyword(\$a, \$b);", 1;
154 }
155
156 # test a keyword that is as tandard op/function, like 'index(...)'.
157 # narg    - how many args to test it with
158 # $parens - "foo $a, $b" is deparsed as "foo($a, $b)"
159 # $dollar - an extra '$_' arg will appear in the deparsed output
160 # $strong - keyword is strong
161
162
163 sub do_std_keyword {
164     my ($keyword, $narg, $parens, $dollar, $strong) = @_;
165
166     $SEEN_STRENGH{$keyword} = $strong;
167
168     for my $core (0,1) { # if true, add CORE:: to keyword being deparsed
169       for my $lexsub (0,1) { # if true, define lex sub
170         my @code;
171         for my $do_exp(0, 1) { # first create expr, then expected-expr
172             my @args = map "\$$_", (undef,"a".."z")[1..$narg];
173             push @args, '$_'
174                 if $dollar && $do_exp && ($strong && !$lexsub or $core);
175             my $args = join(', ', @args);
176              # XXX $lex_parens is temporary, until lex subs are
177              #     deparsed properly.
178             my $lex_parens =
179                 !$core && $do_exp && $lexsub && $keyword ne 'map';
180             $args = ((!$core && !$strong) || $parens || $lex_parens)
181                         ? "($args)"
182                         :  @args ? " $args" : "";
183             push @code, (($core && !($do_exp && $strong))
184                          ? "CORE::"
185                          : $lexsub && $do_exp
186                            ? "CORE::" x $core
187                            : $do_exp && !$core && !$strong ? "test::" : "")
188                                                         . "$keyword$args;";
189         }
190         # code[0]: to run; code[1]: expected
191         testit $keyword, @code, $lexsub;
192       }
193     }
194 }
195
196
197 while (<DATA>) {
198     chomp;
199     s/#.*//;
200     next unless /\S/;
201
202     my @fields = split;
203     die "not 3 fields" unless @fields == 3;
204     my ($keyword, $args, $flags) = @fields;
205
206     $args = '012' if $args eq '@';
207
208     my $parens  = $flags =~ s/p//;
209     my $invert1 = $flags =~ s/1//;
210     my $dollar  = $flags =~ s/\$//;
211     my $strong  = $flags =~ s/\+//;
212     die "unrecognised flag(s): '$flags'" unless $flags =~ /^-?$/;
213
214     if ($args eq 'B') { # binary infix
215         die "$keyword: binary (B) op can't have '\$' flag\\n" if $dollar;
216         die "$keyword: binary (B) op can't have '1' flag\\n" if $invert1;
217         do_infix_keyword($keyword, $parens, $strong);
218     }
219     else {
220         my @narg = split //, $args;
221         for my $n (0..$#narg) {
222             my $narg = $narg[$n];
223             my $p = $parens;
224             $p = !$p if ($n == 0 && $invert1);
225             do_std_keyword($keyword, $narg, $p, (!$n && $dollar), $strong);
226         }
227     }
228 }
229
230
231 # Special cases
232
233 testit dbmopen  => 'CORE::dbmopen(%foo, $bar, $baz);';
234 testit dbmclose => 'CORE::dbmclose %foo;';
235
236 testit delete   => 'CORE::delete $h{\'foo\'};', 'delete $h{\'foo\'};';
237 testit delete   => 'CORE::delete $h{\'foo\'};', undef, 1;
238 testit delete   => 'CORE::delete @h{\'foo\'};', undef, 1;
239 testit delete   => 'CORE::delete $h[0];', undef, 1;
240 testit delete   => 'CORE::delete @h[0];', undef, 1;
241 testit delete   => 'delete $h{\'foo\'};',       'delete $h{\'foo\'};';
242
243 # do is listed as strong, but only do { block } is strong;
244 # do $file is weak,  so test it separately here
245 testit do       => 'CORE::do $a;';
246 testit do       => 'do $a;',                    'test::do($a);';
247 testit do       => 'CORE::do { 1 }',
248                    "do {\n        1\n    };";
249 testit do       => 'CORE::do { 1 }',
250                    "CORE::do {\n        1\n    };", 1;
251 testit do       => 'do { 1 };',
252                    "do {\n        1\n    };";
253
254 testit each     => 'CORE::each %bar;';
255 testit each     => 'CORE::each @foo;';
256
257 testit eof      => 'CORE::eof();';
258
259 testit exists   => 'CORE::exists $h{\'foo\'};', 'exists $h{\'foo\'};';
260 testit exists   => 'CORE::exists $h{\'foo\'};', undef, 1;
261 testit exists   => 'CORE::exists &foo;', undef, 1;
262 testit exists   => 'CORE::exists $h[0];', undef, 1;
263 testit exists   => 'exists $h{\'foo\'};',       'exists $h{\'foo\'};';
264
265 testit exec     => 'CORE::exec($foo $bar);';
266
267 testit glob     => 'glob;',                       'glob($_);';
268 testit glob     => 'CORE::glob;',                 'CORE::glob($_);';
269 testit glob     => 'glob $a;',                    'glob($a);';
270 testit glob     => 'CORE::glob $a;',              'CORE::glob($a);';
271
272 testit grep     => 'CORE::grep { $a } $b, $c',    'grep({$a;} $b, $c);';
273
274 testit keys     => 'CORE::keys %bar;';
275 testit keys     => 'CORE::keys @bar;';
276
277 testit map      => 'CORE::map { $a } $b, $c',    'map({$a;} $b, $c);';
278
279 testit not      => '3 unless CORE::not $a && $b;';
280
281 testit pop      => 'CORE::pop @foo;';
282
283 testit push     => 'CORE::push @foo;',           'CORE::push(@foo);';
284 testit push     => 'CORE::push @foo, 1;',        'CORE::push(@foo, 1);';
285 testit push     => 'CORE::push @foo, 1, 2;',     'CORE::push(@foo, 1, 2);';
286
287 testit readline => 'CORE::readline $a . $b;';
288
289 testit readpipe => 'CORE::readpipe $a + $b;';
290
291 testit reverse  => 'CORE::reverse sort(@foo);';
292
293 testit shift    => 'CORE::shift @foo;';
294
295 testit splice   => q{CORE::splice @foo;},                 q{CORE::splice(@foo);};
296 testit splice   => q{CORE::splice @foo, 0;},              q{CORE::splice(@foo, 0);};
297 testit splice   => q{CORE::splice @foo, 0, 1;},           q{CORE::splice(@foo, 0, 1);};
298 testit splice   => q{CORE::splice @foo, 0, 1, 'a';},      q{CORE::splice(@foo, 0, 1, 'a');};
299 testit splice   => q{CORE::splice @foo, 0, 1, 'a', 'b';}, q{CORE::splice(@foo, 0, 1, 'a', 'b');};
300
301 # note that the test does '() = split...' which is why the
302 # limit is optimised to 1
303 testit split    => 'split;',                     q{split(' ', $_, 1);};
304 testit split    => 'CORE::split;',               q{split(' ', $_, 1);};
305 testit split    => 'split $a;',                  q{split(/$a/u, $_, 1);};
306 testit split    => 'CORE::split $a;',            q{split(/$a/u, $_, 1);};
307 testit split    => 'split $a, $b;',              q{split(/$a/u, $b, 1);};
308 testit split    => 'CORE::split $a, $b;',        q{split(/$a/u, $b, 1);};
309 testit split    => 'split $a, $b, $c;',          q{split(/$a/u, $b, $c);};
310 testit split    => 'CORE::split $a, $b, $c;',    q{split(/$a/u, $b, $c);};
311
312 testit sub      => 'CORE::sub { $a, $b }',
313                         "sub {\n        \$a, \$b;\n    }\n    ;";
314
315 testit system   => 'CORE::system($foo $bar);';
316
317 testit unshift  => 'CORE::unshift @foo;',        'CORE::unshift(@foo);';
318 testit unshift  => 'CORE::unshift @foo, 1;',     'CORE::unshift(@foo, 1);';
319 testit unshift  => 'CORE::unshift @foo, 1, 2;',  'CORE::unshift(@foo, 1, 2);';
320
321 testit values   => 'CORE::values %bar;';
322 testit values   => 'CORE::values @foo;';
323
324
325 # XXX These are deparsed wrapped in parens.
326 # whether they should be, I don't know!
327
328 testit dump     => '(CORE::dump);';
329 testit dump     => '(CORE::dump FOO);';
330 testit goto     => '(CORE::goto);',     '(goto);';
331 testit goto     => '(CORE::goto FOO);', '(goto FOO);';
332 testit last     => '(CORE::last);',     '(last);';
333 testit last     => '(CORE::last FOO);', '(last FOO);';
334 testit next     => '(CORE::next);',     '(next);';
335 testit next     => '(CORE::next FOO);', '(next FOO);';
336 testit redo     => '(CORE::redo);',     '(redo);';
337 testit redo     => '(CORE::redo FOO);', '(redo FOO);';
338 testit redo     => '(CORE::redo);',     '(redo);';
339 testit redo     => '(CORE::redo FOO);', '(redo FOO);';
340 testit return   => '(return);',         '(return);';
341 testit return   => '(CORE::return);',   '(return);';
342
343 # these are the keywords I couldn't think how to test within this framework
344
345 my %not_tested = map { $_ => 1} qw(
346     __DATA__
347     __END__
348     __FILE__
349     __LINE__
350     __PACKAGE__
351     AUTOLOAD
352     BEGIN
353     CHECK
354     CORE
355     DESTROY
356     END
357     INIT
358     UNITCHECK
359     default
360     else
361     elsif
362     for
363     foreach
364     format
365     given
366     if
367     m
368     no
369     package
370     q
371     qq
372     qr
373     qw
374     qx
375     require
376     s
377     tr
378     unless
379     until
380     use
381     when
382     while
383     y
384 );
385
386
387
388 # Sanity check against keyword data:
389 # make sure we haven't missed any keywords,
390 # and that we got the strength right.
391
392 SKIP:
393 {
394     skip "sanity checks when not PERL_CORE", 1 unless defined $ENV{PERL_CORE};
395     my $count = 0;
396     my $file = '../regen/keywords.pl';
397     my $pass = 1;
398     if (open my $fh, '<', $file) {
399         while (<$fh>) {
400             last if /^__END__$/;
401         }
402         while (<$fh>) {
403             next unless /^([+\-])(\w+)$/;
404             my ($strength, $key) = ($1, $2);
405             $strength = ($strength eq '+') ? 1 : 0;
406             $count++;
407             if (!$SEEN{$key} && !$not_tested{$key}) {
408                 diag("keyword '$key' seen in $file, but not tested here!!");
409                 $pass = 0;
410             }
411             if (exists $SEEN_STRENGH{$key} and $SEEN_STRENGH{$key} != $strength) {
412                 diag("keyword '$key' strengh as seen in $file doen't match here!!");
413                 $pass = 0;
414             }
415         }
416     }
417     else {
418         diag("Can't open $file: $!");
419         $pass = 0;
420     }
421     # insanity check
422     if ($count < 200) {
423         diag("Saw $count keywords: less than 200!");
424         $pass = 0;
425     }
426     ok($pass, "sanity checks");
427 }
428
429
430
431 __DATA__
432 #
433 # format:
434 #   keyword args flags
435 #
436 # args consists of:
437 #  * one of more digits indictating which lengths of args the function accepts,
438 #  * or 'B' to indiate a binary infix operator,
439 #  * or '@' to indicate a list function.
440 #
441 # Flags consists of the following (or '-' if no flags):
442 #    + : strong keyword: can't be overrriden
443 #    p : the args are parenthesised on deparsing;
444 #    1 : parenthesising of 1st arg length is inverted
445 #        so '234 p1' means: foo a1,a2;  foo(a1,a2,a3); foo(a1,a2,a3,a4)
446 #    $ : on the first argument length, there is an implicit extra
447 #        '$_' arg which will appear on deparsing;
448 #        e.g. 12p$  will be tested as: foo(a1);     foo(a1,a2);
449 #                     and deparsed as: foo(a1, $_); foo(a1,a2);
450 #
451 # XXX Note that we really should get this data from regen/keywords.pl
452 # and regen/opcodes (augmented if necessary), rather than duplicating it
453 # here.
454
455 __SUB__          0     -
456 abs              01    $
457 accept           2     p
458 alarm            01    $
459 and              B     -
460 atan2            2     p
461 bind             2     p
462 binmode          12    p
463 bless            1     p
464 break            0     -
465 caller           0     -
466 chdir            01    -
467 chmod            @     p1
468 chomp            @     $
469 chop             @     $
470 chown            @     p1
471 chr              01    $
472 chroot           01    $
473 close            01    -
474 closedir         1     -
475 cmp              B     -
476 connect          2     p
477 continue         0     -
478 cos              01    $
479 crypt            2     p
480 # dbmopen  handled specially
481 # dbmclose handled specially
482 defined          01    $+
483 # delete handled specially
484 die              @     p1
485 # do handled specially
486 # dump handled specially
487 # each handled specially
488 endgrent         0     -
489 endhostent       0     -
490 endnetent        0     -
491 endprotoent      0     -
492 endpwent         0     -
493 endservent       0     -
494 eof              01    - # also tested specially
495 eq               B     -
496 eval             01    $+
497 evalbytes        01    $
498 exec             @     p1 # also tested specially
499 # exists handled specially
500 exit             01    -
501 exp              01    $
502 fc               01    $
503 fcntl            3     p
504 fileno           1     -
505 flock            2     p
506 fork             0     -
507 formline         2     p
508 ge               B     -
509 getc             01    -
510 getgrent         0     -
511 getgrgid         1     -
512 getgrnam         1     -
513 gethostbyaddr    2     p
514 gethostbyname    1     -
515 gethostent       0     -
516 getlogin         0     -
517 getnetbyaddr     2     p
518 getnetbyname     1     -
519 getnetent        0     -
520 getpeername      1     -
521 getpgrp          1     -
522 getppid          0     -
523 getpriority      2     p
524 getprotobyname   1     -
525 getprotobynumber 1     p
526 getprotoent      0     -
527 getpwent         0     -
528 getpwnam         1     -
529 getpwuid         1     -
530 getservbyname    2     p
531 getservbyport    2     p
532 getservent       0     -
533 getsockname      1     -
534 getsockopt       3     p
535 # given handled specially
536 grep             123   p+ # also tested specially
537 # glob handled specially
538 # goto handled specially
539 gmtime           01    -
540 gt               B     -
541 hex              01    $
542 index            23    p
543 int              01    $
544 ioctl            3     p
545 join             13    p
546 # keys handled specially
547 kill             123   p
548 # last handled specially
549 lc               01    $
550 lcfirst          01    $
551 le               B     -
552 length           01    $
553 link             2     p
554 listen           2     p
555 local            1     p+
556 localtime        01    -
557 lock             1     -
558 log              01    $
559 lstat            01    $
560 lt               B     -
561 map              123   p+ # also tested specially
562 mkdir            @     p$
563 msgctl           3     p
564 msgget           2     p
565 msgrcv           5     p
566 msgsnd           3     p
567 my               123   p+ # skip with 0 args, as my() => ()
568 ne               B     -
569 # next handled specially
570 # not handled specially
571 oct              01    $
572 open             12345 p
573 opendir          2     p
574 or               B     -
575 ord              01    $
576 our              123   p+ # skip with 0 args, as our() => ()
577 pack             123   p
578 pipe             2     p
579 pop              0     1 # also tested specially
580 pos              01    $+
581 print            @     p$+
582 printf           @     p$+
583 prototype        1     +
584 # push handled specially
585 quotemeta        01    $
586 rand             01    -
587 read             34    p
588 readdir          1     -
589 # readline handled specially
590 readlink         01    $
591 # readpipe handled specially
592 recv             4     p
593 # redo handled specially
594 ref              01    $
595 rename           2     p
596 # XXX This code prints 'Undefined subroutine &main::require called':
597 #   use subs (); import subs 'require';
598 #   eval q[no strict 'vars'; sub { () = require; }]; print $@;
599 # so disable for now
600 #require          01    $+
601 reset            01    -
602 # return handled specially
603 reverse          @     p1 # also tested specially
604 rewinddir        1     -
605 rindex           23    p
606 rmdir            01    $
607 say              @     p$+
608 scalar           1     +
609 seek             3     p
610 seekdir          2     p
611 select           014   p1
612 semctl           4     p
613 semget           3     p
614 semop            2     p
615 send             34    p
616 setgrent         0     -
617 sethostent       1     -
618 setnetent        1     -
619 setpgrp          2     p
620 setpriority      3     p
621 setprotoent      1     -
622 setpwent         0     -
623 setservent       1     -
624 setsockopt       4     p
625 shift            0     1 # also tested specially
626 shmctl           3     p
627 shmget           3     p
628 shmread          4     p
629 shmwrite         4     p
630 shutdown         2     p
631 sin              01    $
632 sleep            01    -
633 socket           4     p
634 socketpair       5     p
635 sort             @     p1+
636 # split handled specially
637 # splice handled specially
638 sprintf          123   p
639 sqrt             01    $
640 srand            01    -
641 stat             01    $
642 state            123   p+ # skip with 0 args, as state() => ()
643 study            01    $+
644 # sub handled specially
645 substr           234   p
646 symlink          2     p
647 syscall          2     p
648 sysopen          34    p
649 sysread          34    p
650 sysseek          3     p
651 system           @     p1 # also tested specially
652 syswrite         234   p
653 tell             01    -
654 telldir          1     -
655 tie              234   p
656 tied             1     -
657 time             0     -
658 times            0     -
659 truncate         2     p
660 uc               01    $
661 ucfirst          01    $
662 umask            01    -
663 undef            01    +
664 unlink           @     p$
665 unpack           12    p$
666 # unshift handled specially
667 untie            1     -
668 utime            @     p1
669 # values handled specially
670 vec              3     p
671 wait             0     -
672 waitpid          2     p
673 wantarray        0     -
674 warn             @     p1
675 write            01    -
676 x                B     -
677 xor              B     p