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