This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
mktables: Add field to constructor
[perl5.git] / lib / B / Deparse-core.t
CommitLineData
4a1ac32e
FC
1#!./perl
2
d8e99b97
DM
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
e5bb0a1f 7# to fully test both CORE:: versus none, plus that any arguments
d8e99b97
DM
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#
aaaaf427
DM
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#
d8e99b97
DM
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
4a1ac32e 29BEGIN {
9ee672c4
NC
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 }
4a1ac32e
FC
35}
36
9ee672c4
NC
37use strict;
38use Test::More;
26230909 39plan tests => 3886;
d8e99b97 40
7d789282
FC
41use feature (sprintf(":%vd", $^V)); # to avoid relying on the feature
42 # logic to add CORE::
4a1ac32e
FC
43use B::Deparse;
44my $deparse = new B::Deparse;
45
d8e99b97
DM
46my %SEEN;
47my %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
52sub testit {
3188a821 53 my ($keyword, $expr, $expected_expr, $lexsub) = @_;
d8e99b97
DM
54
55 $expected_expr //= $expr;
56 $SEEN{$keyword} = 1;
57
d8e99b97 58
aaaaf427
DM
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/;
aaaaf427
DM
65 }
66 my $vars = $lex == 1 ? 'my($a, $b, $c, $d, $e);' . "\n " : "";
67
68 if ($lex == 2) {
69 my $repl = 'my $a';
c569a7fb 70 if ($expr =~ 'CORE::do') {
f92b363c
FC
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 }
aaaaf427
DM
76 s/\$a/$repl/ for $expr, $expected_expr;
77 }
78
79 my $desc = "$keyword: lex=$lex $expr => $expected_expr";
3188a821 80 $desc .= " (lex sub)" if $lexsub;
aaaaf427
DM
81
82
83 my $code_ref;
3188a821
FC
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 {
aaaaf427
DM
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
d4f1bfe7 103 unless ($got_text =~ /
3188a821 104 package (?:lexsub)?test;
d8e99b97 105 use strict 'refs', 'subs';
aaaaf427
DM
106 use feature [^\n]+
107 \Q$vars\E\(\) = (.*)
d8e99b97 108}/s) {
aaaaf427
DM
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;
d8e99b97 117 }
4a1ac32e
FC
118}
119
d8e99b97
DM
120
121# Deparse can't distinguish 'and' from '&&' etc
122my %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
129sub 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;
3188a821
FC
142 testit $keyword, "(\$a CORE::$keyword \$b)", $exp, 1;
143 testit $keyword, "(\$a $keyword \$b)", $exp, 1;
d8e99b97 144 if (!$strong) {
a958cfbb
FC
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.
c837f29a
FC
148 my $pre = "test::" x ($keyword ne 'x');
149 testit $keyword, "$keyword(\$a, \$b)", "$pre$keyword(\$a, \$b);";
d8e99b97 150 }
3188a821 151 testit $keyword, "$keyword(\$a, \$b)", "$keyword(\$a, \$b);", 1;
d8e99b97
DM
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
161sub 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
3188a821 167 for my $lexsub (0,1) { # if true, define lex sub
d8e99b97
DM
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];
3188a821
FC
171 push @args, '$_'
172 if $dollar && $do_exp && ($strong && !$lexsub or $core);
d8e99b97 173 my $args = join(', ', @args);
3188a821
FC
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)
d8e99b97
DM
179 ? "($args)"
180 : @args ? " $args" : "";
a958cfbb 181 push @code, (($core && !($do_exp && $strong))
3188a821
FC
182 ? "CORE::"
183 : $lexsub && $do_exp
184 ? "CORE::" x $core
a958cfbb 185 : $do_exp && !$core && !$strong ? "test::" : "")
d8e99b97
DM
186 . "$keyword$args;";
187 }
3188a821
FC
188 # code[0]: to run; code[1]: expected
189 testit $keyword, @code, $lexsub;
190 }
d8e99b97
DM
191 }
192}
193
194
195while (<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 }
4a1ac32e
FC
226}
227
d8e99b97 228
4a1ac32e 229# Special cases
d8e99b97
DM
230
231testit dbmopen => 'CORE::dbmopen(%foo, $bar, $baz);';
232testit dbmclose => 'CORE::dbmclose %foo;';
233
234testit delete => 'CORE::delete $h{\'foo\'};', 'delete $h{\'foo\'};';
3188a821
FC
235testit delete => 'CORE::delete $h{\'foo\'};', undef, 1;
236testit delete => 'CORE::delete @h{\'foo\'};', undef, 1;
237testit delete => 'CORE::delete $h[0];', undef, 1;
238testit delete => 'CORE::delete @h[0];', undef, 1;
d8e99b97
DM
239testit 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
243testit do => 'CORE::do $a;';
a958cfbb 244testit do => 'do $a;', 'test::do($a);';
d8e99b97
DM
245testit do => 'CORE::do { 1 }',
246 "do {\n 1\n };";
3188a821
FC
247testit do => 'CORE::do { 1 }',
248 "CORE::do {\n 1\n };", 1;
d8e99b97
DM
249testit do => 'do { 1 };',
250 "do {\n 1\n };";
251
252testit each => 'CORE::each %bar;';
26230909 253testit each => 'CORE::each @foo;';
d8e99b97
DM
254
255testit eof => 'CORE::eof();';
256
257testit exists => 'CORE::exists $h{\'foo\'};', 'exists $h{\'foo\'};';
3188a821
FC
258testit exists => 'CORE::exists $h{\'foo\'};', undef, 1;
259testit exists => 'CORE::exists &foo;', undef, 1;
260testit exists => 'CORE::exists $h[0];', undef, 1;
d8e99b97
DM
261testit exists => 'exists $h{\'foo\'};', 'exists $h{\'foo\'};';
262
263testit exec => 'CORE::exec($foo $bar);';
264
93860275
FC
265testit glob => 'glob;', 'glob($_);';
266testit glob => 'CORE::glob;', 'CORE::glob($_);';
267testit glob => 'glob $a;', 'glob($a);';
268testit glob => 'CORE::glob $a;', 'CORE::glob($a);';
d8e99b97
DM
269
270testit grep => 'CORE::grep { $a } $b, $c', 'grep({$a;} $b, $c);';
271
272testit keys => 'CORE::keys %bar;';
26230909 273testit keys => 'CORE::keys @bar;';
d8e99b97
DM
274
275testit map => 'CORE::map { $a } $b, $c', 'map({$a;} $b, $c);';
276
277testit not => '3 unless CORE::not $a && $b;';
278
26230909
AC
279testit pop => 'CORE::pop @foo;';
280
281testit push => 'CORE::push @foo;', 'CORE::push(@foo);';
282testit push => 'CORE::push @foo, 1;', 'CORE::push(@foo, 1);';
283testit push => 'CORE::push @foo, 1, 2;', 'CORE::push(@foo, 1, 2);';
284
d8e99b97
DM
285testit readline => 'CORE::readline $a . $b;';
286
287testit readpipe => 'CORE::readpipe $a + $b;';
288
289testit reverse => 'CORE::reverse sort(@foo);';
290
26230909
AC
291testit shift => 'CORE::shift @foo;';
292
293testit splice => q{CORE::splice @foo;}, q{CORE::splice(@foo);};
294testit splice => q{CORE::splice @foo, 0;}, q{CORE::splice(@foo, 0);};
295testit splice => q{CORE::splice @foo, 0, 1;}, q{CORE::splice(@foo, 0, 1);};
296testit splice => q{CORE::splice @foo, 0, 1, 'a';}, q{CORE::splice(@foo, 0, 1, 'a');};
297testit splice => q{CORE::splice @foo, 0, 1, 'a', 'b';}, q{CORE::splice(@foo, 0, 1, 'a', 'b');};
298
d8e99b97
DM
299# note that the test does '() = split...' which is why the
300# limit is optimised to 1
301testit split => 'split;', q{split(' ', $_, 1);};
302testit split => 'CORE::split;', q{split(' ', $_, 1);};
303testit split => 'split $a;', q{split(/$a/u, $_, 1);};
304testit split => 'CORE::split $a;', q{split(/$a/u, $_, 1);};
305testit split => 'split $a, $b;', q{split(/$a/u, $b, 1);};
306testit split => 'CORE::split $a, $b;', q{split(/$a/u, $b, 1);};
307testit split => 'split $a, $b, $c;', q{split(/$a/u, $b, $c);};
308testit split => 'CORE::split $a, $b, $c;', q{split(/$a/u, $b, $c);};
309
310testit sub => 'CORE::sub { $a, $b }',
311 "sub {\n \$a, \$b;\n }\n ;";
312
313testit system => 'CORE::system($foo $bar);';
314
26230909
AC
315testit unshift => 'CORE::unshift @foo;', 'CORE::unshift(@foo);';
316testit unshift => 'CORE::unshift @foo, 1;', 'CORE::unshift(@foo, 1);';
317testit unshift => 'CORE::unshift @foo, 1, 2;', 'CORE::unshift(@foo, 1, 2);';
318
d8e99b97 319testit values => 'CORE::values %bar;';
26230909 320testit values => 'CORE::values @foo;';
d8e99b97
DM
321
322
323# XXX These are deparsed wrapped in parens.
324# whether they should be, I don't know!
325
326testit dump => '(CORE::dump);';
327testit dump => '(CORE::dump FOO);';
328testit goto => '(CORE::goto);', '(goto);';
329testit goto => '(CORE::goto FOO);', '(goto FOO);';
330testit last => '(CORE::last);', '(last);';
331testit last => '(CORE::last FOO);', '(last FOO);';
332testit next => '(CORE::next);', '(next);';
333testit next => '(CORE::next FOO);', '(next FOO);';
334testit redo => '(CORE::redo);', '(redo);';
335testit redo => '(CORE::redo FOO);', '(redo FOO);';
336testit redo => '(CORE::redo);', '(redo);';
337testit redo => '(CORE::redo FOO);', '(redo FOO);';
338testit return => '(return);', '(return);';
339testit return => '(CORE::return);', '(return);';
340
341# these are the keywords I couldn't think how to test within this framework
342
343my %not_tested = map { $_ => 1} qw(
344 __DATA__
345 __END__
346 __FILE__
347 __LINE__
348 __PACKAGE__
d8e99b97
DM
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
37fc255e
CB
390SKIP:
391{
392 skip "sanity checks when not PERL_CORE", 1 unless defined $ENV{PERL_CORE};
d8e99b97 393 my $count = 0;
7263d211 394 my $file = '../regen/keywords.pl';
d8e99b97
DM
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 -
454abs 01 $
455accept 2 p
456alarm 01 $
457and B -
458atan2 2 p
459bind 2 p
460binmode 12 p
461bless 1 p
462break 0 -
463caller 0 -
464chdir 01 -
465chmod @ p1
466chomp @ $
467chop @ $
468chown @ p1
469chr 01 $
470chroot 01 $
471close 01 -
472closedir 1 -
473cmp B -
474connect 2 p
475continue 0 -
476cos 01 $
477crypt 2 p
478# dbmopen handled specially
479# dbmclose handled specially
480defined 01 $+
481# delete handled specially
482die @ p1
483# do handled specially
484# dump handled specially
26230909 485# each handled specially
d8e99b97
DM
486endgrent 0 -
487endhostent 0 -
488endnetent 0 -
489endprotoent 0 -
490endpwent 0 -
491endservent 0 -
492eof 01 - # also tested specially
493eq B -
494eval 01 $+
495evalbytes 01 $
496exec @ p1 # also tested specially
497# exists handled specially
498exit 01 -
499exp 01 $
500fc 01 $
501fcntl 3 p
502fileno 1 -
503flock 2 p
504fork 0 -
505formline 2 p
506ge B -
507getc 01 -
508getgrent 0 -
509getgrgid 1 -
510getgrnam 1 -
511gethostbyaddr 2 p
512gethostbyname 1 -
513gethostent 0 -
514getlogin 0 -
515getnetbyaddr 2 p
516getnetbyname 1 -
517getnetent 0 -
518getpeername 1 -
519getpgrp 1 -
520getppid 0 -
521getpriority 2 p
522getprotobyname 1 -
523getprotobynumber 1 p
524getprotoent 0 -
525getpwent 0 -
526getpwnam 1 -
527getpwuid 1 -
528getservbyname 2 p
529getservbyport 2 p
530getservent 0 -
531getsockname 1 -
532getsockopt 3 p
533# given handled specially
534grep 123 p+ # also tested specially
535# glob handled specially
536# goto handled specially
537gmtime 01 -
538gt B -
539hex 01 $
540index 23 p
541int 01 $
542ioctl 3 p
987c9691 543join 13 p
26230909 544# keys handled specially
d8e99b97
DM
545kill 123 p
546# last handled specially
547lc 01 $
548lcfirst 01 $
549le B -
550length 01 $
551link 2 p
552listen 2 p
553local 1 p+
554localtime 01 -
555lock 1 -
556log 01 $
557lstat 01 $
558lt B -
559map 123 p+ # also tested specially
560mkdir @ p$
561msgctl 3 p
562msgget 2 p
563msgrcv 5 p
564msgsnd 3 p
565my 123 p+ # skip with 0 args, as my() => ()
566ne B -
567# next handled specially
568# not handled specially
569oct 01 $
570open 12345 p
571opendir 2 p
572or B -
573ord 01 $
574our 123 p+ # skip with 0 args, as our() => ()
575pack 123 p
576pipe 2 p
26230909 577pop 0 1 # also tested specially
d8e99b97
DM
578pos 01 $+
579print @ p$+
580printf @ p$+
581prototype 1 +
26230909 582# push handled specially
d8e99b97
DM
583quotemeta 01 $
584rand 01 -
585read 34 p
586readdir 1 -
587# readline handled specially
588readlink 01 $
589# readpipe handled specially
590recv 4 p
591# redo handled specially
592ref 01 $
593rename 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 $+
599reset 01 -
600# return handled specially
601reverse @ p1 # also tested specially
602rewinddir 1 -
603rindex 23 p
604rmdir 01 $
605say @ p$+
606scalar 1 +
607seek 3 p
608seekdir 2 p
609select 014 p1
610semctl 4 p
611semget 3 p
612semop 2 p
613send 34 p
614setgrent 0 -
615sethostent 1 -
616setnetent 1 -
617setpgrp 2 p
618setpriority 3 p
619setprotoent 1 -
620setpwent 0 -
621setservent 1 -
622setsockopt 4 p
26230909 623shift 0 1 # also tested specially
d8e99b97
DM
624shmctl 3 p
625shmget 3 p
626shmread 4 p
627shmwrite 4 p
628shutdown 2 p
629sin 01 $
630sleep 01 -
631socket 4 p
632socketpair 5 p
9d52f6f3 633sort @ p1+
d8e99b97 634# split handled specially
26230909 635# splice handled specially
d8e99b97
DM
636sprintf 123 p
637sqrt 01 $
638srand 01 -
639stat 01 $
640state 123 p+ # skip with 0 args, as state() => ()
641study 01 $+
642# sub handled specially
643substr 234 p
644symlink 2 p
645syscall 2 p
646sysopen 34 p
647sysread 34 p
648sysseek 3 p
649system @ p1 # also tested specially
650syswrite 234 p
651tell 01 -
652telldir 1 -
653tie 234 p
654tied 1 -
655time 0 -
656times 0 -
657truncate 2 p
658uc 01 $
659ucfirst 01 $
660umask 01 -
661undef 01 +
662unlink @ p$
663unpack 12 p$
26230909 664# unshift handled specially
d8e99b97
DM
665untie 1 -
666utime @ p1
26230909 667# values handled specially
d8e99b97
DM
668vec 3 p
669wait 0 -
670waitpid 2 p
671wantarray 0 -
672warn @ p1
673write 01 -
674x B -
675xor B p