xref: /openbsd-src/gnu/usr.bin/perl/t/comp/fold.t (revision 9f11ffb7133c203312a01e4b986886bc88c7d74b)
1b39c5158Smillert#!./perl -w
2850e2753Smillert
3b39c5158Smillert# Uncomment this for testing, but don't leave it in for "production", as
4b39c5158Smillert# we've not yet verified that use works.
5b39c5158Smillert# use strict;
6850e2753Smillert
7*9f11ffb7Safresh1print "1..35\n";
8b39c5158Smillertmy $test = 0;
9850e2753Smillert
10850e2753Smillert# Historically constant folding was performed by evaluating the ops, and if
11850e2753Smillert# they threw an exception compilation failed. This was seen as buggy, because
12850e2753Smillert# even illegal constants in unreachable code would cause failure. So now
13850e2753Smillert# illegal expressions are reported at runtime, if the expression is reached,
14850e2753Smillert# making constant folding consistent with many other languages, and purely an
15850e2753Smillert# optimisation rather than a behaviour change.
16850e2753Smillert
17850e2753Smillert
18b39c5158Smillertsub failed {
19b39c5158Smillert    my ($got, $expected, $name) = @_;
20b39c5158Smillert
21b39c5158Smillert    print "not ok $test - $name\n";
22b39c5158Smillert    my @caller = caller(1);
23b39c5158Smillert    print "# Failed test at $caller[1] line $caller[2]\n";
24b39c5158Smillert    if (defined $got) {
25b39c5158Smillert	print "# Got '$got'\n";
26b39c5158Smillert    } else {
27b39c5158Smillert	print "# Got undef\n";
28b39c5158Smillert    }
29b39c5158Smillert    print "# Expected $expected\n";
30b39c5158Smillert    return;
31b39c5158Smillert}
32b39c5158Smillert
33b39c5158Smillertsub like {
34b39c5158Smillert    my ($got, $pattern, $name) = @_;
35b39c5158Smillert    $test = $test + 1;
36b39c5158Smillert    if (defined $got && $got =~ $pattern) {
37b39c5158Smillert	print "ok $test - $name\n";
38b39c5158Smillert	# Principle of least surprise - maintain the expected interface, even
39b39c5158Smillert	# though we aren't using it here (yet).
40b39c5158Smillert	return 1;
41b39c5158Smillert    }
42b39c5158Smillert    failed($got, $pattern, $name);
43b39c5158Smillert}
44b39c5158Smillert
45b39c5158Smillertsub is {
46b39c5158Smillert    my ($got, $expect, $name) = @_;
47b39c5158Smillert    $test = $test + 1;
48b39c5158Smillert    if (defined $got && $got eq $expect) {
49b39c5158Smillert	print "ok $test - $name\n";
50b39c5158Smillert	return 1;
51b39c5158Smillert    }
52b39c5158Smillert    failed($got, "'$expect'", $name);
53b39c5158Smillert}
54b39c5158Smillert
55898184e3Ssthensub ok {
56898184e3Ssthen    my ($got, $name) = @_;
57898184e3Ssthen    $test = $test + 1;
58898184e3Ssthen    if ($got) {
59898184e3Ssthen	print "ok $test - $name\n";
60898184e3Ssthen	return 1;
61898184e3Ssthen    }
62898184e3Ssthen    failed($got, "a true value", $name);
63898184e3Ssthen}
64898184e3Ssthen
65850e2753Smillertmy $a;
66850e2753Smillert$a = eval '$b = 0/0 if 0; 3';
67b39c5158Smillertis ($a, 3, 'constants in conditionals don\'t affect constant folding');
68b39c5158Smillertis ($@, '', 'no error');
69850e2753Smillert
70850e2753Smillertmy $b = 0;
71850e2753Smillert$a = eval 'if ($b) {return sqrt -3} 3';
72b39c5158Smillertis ($a, 3, 'variables in conditionals don\'t affect constant folding');
73b39c5158Smillertis ($@, '', 'no error');
74850e2753Smillert
75850e2753Smillert$a = eval q{
76850e2753Smillert	$b = eval q{if ($b) {return log 0} 4};
77b39c5158Smillert 	is ($b, 4, 'inner eval folds constant');
78b39c5158Smillert	is ($@, '', 'no error');
79850e2753Smillert	5;
80850e2753Smillert};
81b39c5158Smillertis ($a, 5, 'outer eval folds constant');
82b39c5158Smillertis ($@, '', 'no error');
83850e2753Smillert
84850e2753Smillert# warn and die hooks should be disabled during constant folding
85850e2753Smillert
86850e2753Smillert{
87850e2753Smillert    my $c = 0;
88850e2753Smillert    local $SIG{__WARN__} = sub { $c++   };
89850e2753Smillert    local $SIG{__DIE__}  = sub { $c+= 2 };
90850e2753Smillert    eval q{
91850e2753Smillert	is($c, 0, "premature warn/die: $c");
92850e2753Smillert	my $x = "a"+5;
93850e2753Smillert	is($c, 1, "missing warn hook");
94850e2753Smillert	is($x, 5, "a+5");
95850e2753Smillert	$c = 0;
96850e2753Smillert	$x = 1/0;
97850e2753Smillert    };
98850e2753Smillert    like ($@, qr/division/, "eval caught division");
99850e2753Smillert    is($c, 2, "missing die hook");
100850e2753Smillert}
101898184e3Ssthen
102898184e3Ssthen# [perl #20444] Constant folding should not change the meaning of match
103898184e3Ssthen# operators.
104898184e3Ssthen{
105898184e3Ssthen local *_;
106898184e3Ssthen $_="foo"; my $jing = 1;
107898184e3Ssthen ok scalar $jing =~ (1 ? /foo/ : /bar/),
108898184e3Ssthen   'lone m// is not bound via =~ after ? : folding';
109898184e3Ssthen ok scalar $jing =~ (0 || /foo/),
110898184e3Ssthen   'lone m// is not bound via =~ after || folding';
111898184e3Ssthen ok scalar $jing =~ (1 ? s/foo/foo/ : /bar/),
112898184e3Ssthen   'lone s/// is not bound via =~ after ? : folding';
113898184e3Ssthen ok scalar $jing =~ (0 || s/foo/foo/),
114898184e3Ssthen   'lone s/// is not bound via =~ after || folding';
115898184e3Ssthen $jing = 3;
116898184e3Ssthen ok scalar $jing =~ (1 ? y/fo// : /bar/),
117898184e3Ssthen   'lone y/// is not bound via =~ after ? : folding';
118898184e3Ssthen ok scalar $jing =~ (0 || y/fo//),
119898184e3Ssthen   'lone y/// is not bound via =~ after || folding';
120898184e3Ssthen}
12191f110e0Safresh1
12291f110e0Safresh1# [perl #78064] or print
12391f110e0Safresh1package other { # hide the "ok" sub
12491f110e0Safresh1 BEGIN { $^W = 0 }
12591f110e0Safresh1 print 0 ? not_ok : ok;
12691f110e0Safresh1 print " ", ++$test, " - print followed by const ? BEAR : BEAR\n";
12791f110e0Safresh1 print 1 ? ok : not_ok;
12891f110e0Safresh1 print " ", ++$test, " - print followed by const ? BEAR : BEAR (again)\n";
12991f110e0Safresh1 print 1 && ok;
13091f110e0Safresh1 print " ", ++$test, " - print followed by const && BEAR\n";
13191f110e0Safresh1 print 0 || ok;
13291f110e0Safresh1 print " ", ++$test, " - print followed by const || URSINE\n";
13391f110e0Safresh1 BEGIN { $^W = 1 }
13491f110e0Safresh1}
13591f110e0Safresh1
13691f110e0Safresh1# or stat
13791f110e0Safresh1print "not " unless stat(1 ? INSTALL : 0) eq stat("INSTALL");
13891f110e0Safresh1print "ok ", ++$test, " - stat(const ? word : ....)\n";
13991f110e0Safresh1# in case we are in t/
14091f110e0Safresh1print "not " unless stat(1 ? TEST : 0) eq stat("TEST");
14191f110e0Safresh1print "ok ", ++$test, " - stat(const ? word : ....)\n";
14291f110e0Safresh1
14391f110e0Safresh1# or truncate
14491f110e0Safresh1my $n = "for_fold_dot_t$$";
14591f110e0Safresh1open F, ">$n" or die "open: $!";
14691f110e0Safresh1print F "bralh blah blah \n";
14791f110e0Safresh1close F or die "close $!";
14891f110e0Safresh1eval "truncate 1 ? $n : 0, 0;";
14991f110e0Safresh1print "not " unless -z $n;
15091f110e0Safresh1print "ok ", ++$test, " - truncate(const ? word : ...)\n";
15191f110e0Safresh1unlink $n;
1526fb12b70Safresh1
1536fb12b70Safresh1# Constant folding should not change the mutability of returned values.
1546fb12b70Safresh1for(1+2) {
1556fb12b70Safresh1    eval { $_++ };
1566fb12b70Safresh1    print "not " unless $_ eq 4;
1576fb12b70Safresh1    print "ok ", ++$test,
1586fb12b70Safresh1          " - 1+2 returns mutable value, just like \$a+\$b",
1596fb12b70Safresh1          "\n";
1606fb12b70Safresh1}
1616fb12b70Safresh1
1626fb12b70Safresh1# [perl #119055]
1636fb12b70Safresh1# We hide the implementation detail that qq "foo" is implemented using
1646fb12b70Safresh1# constant folding.
1656fb12b70Safresh1eval { ${\"hello\n"}++ };
1666fb12b70Safresh1print "not " unless $@ =~ "Modification of a read-only value attempted at";
1676fb12b70Safresh1print "ok ", ++$test, " - qq with no vars is a constant\n";
1686fb12b70Safresh1
1696fb12b70Safresh1# [perl #119501]
1706fb12b70Safresh1my @values;
1716fb12b70Safresh1for (1,2) { for (\(1+3)) { push @values, $$_; $$_++ } }
1726fb12b70Safresh1is "@values", "4 4",
1736fb12b70Safresh1   '\1+3 folding making modification affect future retvals';
174b8851fccSafresh1
175b8851fccSafresh1{
176b8851fccSafresh1    BEGIN { $^W = 0; $::{u} = \undef }
177b8851fccSafresh1    my $w;
178b8851fccSafresh1    local $SIG{__WARN__} = sub { ++$w };
179b8851fccSafresh1    () = 1 + u;
180b8851fccSafresh1    is $w, 1, '1+undef_constant is not folded outside warninsg scope';
181b8851fccSafresh1    BEGIN { $^W = 1 }
182b8851fccSafresh1}
183*9f11ffb7Safresh1
184*9f11ffb7Safresh1$a = eval 'my @z; @z = 0..~0 if 0; 3';
185*9f11ffb7Safresh1is ($a, 3, "list constant folding doesn't signal compile-time error");
186*9f11ffb7Safresh1is ($@, '', 'no error');
187*9f11ffb7Safresh1
188*9f11ffb7Safresh1$b = 0;
189*9f11ffb7Safresh1$a = eval 'my @z; @z = 0..~0 if $b; 3';
190*9f11ffb7Safresh1is ($a, 3, "list constant folding doesn't signal compile-time error");
191*9f11ffb7Safresh1is ($@, '', 'no error');
192*9f11ffb7Safresh1
193*9f11ffb7Safresh1$a = eval 'local $SIG{__WARN__} = sub {}; join("", ":".."~", "z")';
194*9f11ffb7Safresh1is ($a, ":z", "aborted list constant folding still executable");
195