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