1b8851fccSafresh1#!./perl -w 2b8851fccSafresh1 3b8851fccSafresh1# Some miscellaneous checks for the list assignment operator, OP_AASSIGN. 4b8851fccSafresh1# 5b8851fccSafresh1# This file was only added in 2015; before then, such tests were 6b8851fccSafresh1# typically in various other random places like op/array.t. This test file 7b8851fccSafresh1# doesn't therefore attempt to be comprehensive; it merely provides a 8b8851fccSafresh1# central place to new put additional tests, especially those related to 9b8851fccSafresh1# the trickiness of commonality, e.g. ($a,$b) = ($b,$a). 10b8851fccSafresh1# 11b8851fccSafresh1# In particular, it's testing the flags 12b8851fccSafresh1# OPpASSIGN_COMMON_SCALAR 13b8851fccSafresh1# OPpASSIGN_COMMON_RC1 14b8851fccSafresh1# OPpASSIGN_COMMON_AGG 15b8851fccSafresh1 16b8851fccSafresh1BEGIN { 17b8851fccSafresh1 chdir 't' if -d 't'; 18b8851fccSafresh1 require './test.pl'; 195759b3d2Safresh1 set_up_inc('../lib') 20b8851fccSafresh1} 21b8851fccSafresh1 22b8851fccSafresh1use warnings; 23b8851fccSafresh1use strict; 24b8851fccSafresh1 25b8851fccSafresh1# general purpose package vars 26b8851fccSafresh1 27b8851fccSafresh1our $pkg_scalar; 28b8851fccSafresh1our @pkg_array; 29b8851fccSafresh1our %pkg_hash; 30b8851fccSafresh1 31b8851fccSafresh1sub f_ret_14 { return 1..4 } 32b8851fccSafresh1 33b8851fccSafresh1# stringify a hash ref 34b8851fccSafresh1 35b8851fccSafresh1sub sh { 36b8851fccSafresh1 my $rh = $_[0]; 37b8851fccSafresh1 join ',', map "$_:$rh->{$_}", sort keys %$rh; 38b8851fccSafresh1} 39b8851fccSafresh1 40b8851fccSafresh1 41b8851fccSafresh1# where the RHS has surplus elements 42b8851fccSafresh1 43b8851fccSafresh1{ 44b8851fccSafresh1 my ($a,$b); 45b8851fccSafresh1 ($a,$b) = f_ret_14(); 46b8851fccSafresh1 is("$a:$b", "1:2", "surplus"); 47b8851fccSafresh1} 48b8851fccSafresh1 49b8851fccSafresh1# common with slices 50b8851fccSafresh1 51b8851fccSafresh1{ 52b8851fccSafresh1 my @a = (1,2); 53b8851fccSafresh1 @a[0,1] = @a[1,0]; 54b8851fccSafresh1 is("$a[0]:$a[1]", "2:1", "lex array slice"); 55b8851fccSafresh1} 56b8851fccSafresh1 57b8851fccSafresh1# package alias 58b8851fccSafresh1 59b8851fccSafresh1{ 60b8851fccSafresh1 my ($a, $b) = 1..2; 61b8851fccSafresh1 for $pkg_scalar ($a) { 62b8851fccSafresh1 ($pkg_scalar, $b) = (3, $a); 63b8851fccSafresh1 is($pkg_scalar, 3, "package alias pkg"); 64b8851fccSafresh1 is("$a:$b", "3:1", "package alias a:b"); 65b8851fccSafresh1 } 66b8851fccSafresh1} 67b8851fccSafresh1 68b8851fccSafresh1# my array/hash populated via closure 69b8851fccSafresh1 70b8851fccSafresh1{ 71b8851fccSafresh1 my $ra = f1(); 72b8851fccSafresh1 my ($x, @a) = @$ra; 73b8851fccSafresh1 sub f1 { $x = 1; @a = 2..4; \@a } 74b8851fccSafresh1 is($x, 2, "my: array closure x"); 75b8851fccSafresh1 is("@a", "3 4", "my: array closure a"); 76b8851fccSafresh1 77b8851fccSafresh1 my $rh = f2(); 78b8851fccSafresh1 my ($k, $v, %h) = (d => 4, %$rh, e => 6); 79b8851fccSafresh1 sub f2 { $k = 'a'; $v = 1; %h = qw(b 2 c 3); \%h } 80b8851fccSafresh1 is("$k:$v", "d:4", "my: hash closure k:v"); 81b8851fccSafresh1 is(sh(\%h), "b:2,c:3,e:6", "my: hash closure h"); 82b8851fccSafresh1} 83b8851fccSafresh1 84b8851fccSafresh1 85b8851fccSafresh1# various shared element scenarios within a my (...) 86b8851fccSafresh1 87b8851fccSafresh1{ 88b8851fccSafresh1 my ($x,$y) = f3(); # $x and $y on both sides 89b8851fccSafresh1 sub f3 : lvalue { ($x,$y) = (1,2); $y, $x } 90b8851fccSafresh1 is ("$x:$y", "2:1", "my: scalar and lvalue sub"); 91b8851fccSafresh1} 92b8851fccSafresh1 93b8851fccSafresh1{ 94b8851fccSafresh1 my $ra = f4(); 95b8851fccSafresh1 my @a = @$ra; # elements of @a on both sides 96b8851fccSafresh1 sub f4 { @a = 1..4; \@a } 97b8851fccSafresh1 is("@a", "1 2 3 4", "my: array and elements"); 98b8851fccSafresh1} 99b8851fccSafresh1 100b8851fccSafresh1{ 101b8851fccSafresh1 my $rh = f5(); 102b8851fccSafresh1 my %h = %$rh; # elements of %h on both sides 103b8851fccSafresh1 sub f5 { %h = qw(a 1 b 2 c 3); \%h } 104b8851fccSafresh1 is(sh(\%h), "a:1,b:2,c:3", "my: hash and elements"); 105b8851fccSafresh1} 106b8851fccSafresh1 107b8851fccSafresh1{ 108b8851fccSafresh1 f6(); 109b8851fccSafresh1 our $xalias6; 110b8851fccSafresh1 my ($x, $y) = (2, $xalias6); 111b8851fccSafresh1 sub f6 { $x = 1; *xalias6 = \$x; } 112b8851fccSafresh1 is ("$x:$y", "2:1", "my: pkg var aliased to lexical"); 113b8851fccSafresh1} 114b8851fccSafresh1 115b8851fccSafresh1 116b8851fccSafresh1{ 117b8851fccSafresh1 my @a; 118b8851fccSafresh1 f7(); 119b8851fccSafresh1 my ($x,$y) = @a; 120b8851fccSafresh1 is ("$x:$y", "2:1", "my: lex array elements aliased"); 121b8851fccSafresh1 122b8851fccSafresh1 sub f7 { 123b8851fccSafresh1 ($x, $y) = (1,2); 124b8851fccSafresh1 use feature 'refaliasing'; 125b8851fccSafresh1 no warnings 'experimental'; 126b8851fccSafresh1 \($a[0], $a[1]) = \($y,$x); 127b8851fccSafresh1 } 128b8851fccSafresh1} 129b8851fccSafresh1 130b8851fccSafresh1{ 131b8851fccSafresh1 @pkg_array = (); 132b8851fccSafresh1 f8(); 133b8851fccSafresh1 my ($x,$y) = @pkg_array; 134b8851fccSafresh1 is ("$x:$y", "2:1", "my: pkg array elements aliased"); 135b8851fccSafresh1 136b8851fccSafresh1 sub f8 { 137b8851fccSafresh1 ($x, $y) = (1,2); 138b8851fccSafresh1 use feature 'refaliasing'; 139b8851fccSafresh1 no warnings 'experimental'; 140b8851fccSafresh1 \($pkg_array[0], $pkg_array[1]) = \($y,$x); 141b8851fccSafresh1 } 142b8851fccSafresh1} 143b8851fccSafresh1 144b8851fccSafresh1{ 145b8851fccSafresh1 f9(); 146b8851fccSafresh1 my ($x,$y) = f9(); 147b8851fccSafresh1 is ("$x:$y", "2:1", "my: pkg scalar alias"); 148b8851fccSafresh1 149b8851fccSafresh1 our $xalias9; 150b8851fccSafresh1 sub f9 : lvalue { 151b8851fccSafresh1 ($x, $y) = (1,2); 152b8851fccSafresh1 *xalias9 = \$x; 153b8851fccSafresh1 $y, $xalias9; 154b8851fccSafresh1 } 155b8851fccSafresh1} 156b8851fccSafresh1 157b8851fccSafresh1{ 158b8851fccSafresh1 use feature 'refaliasing'; 159b8851fccSafresh1 no warnings 'experimental'; 160b8851fccSafresh1 161b8851fccSafresh1 f10(); 162b8851fccSafresh1 our $pkg10; 163b8851fccSafresh1 \(my $lex) = \$pkg10; 164b8851fccSafresh1 my @a = ($lex,3); # equivalent to ($a[0],3) 165b8851fccSafresh1 is("@a", "1 3", "my: lex alias of array alement"); 166b8851fccSafresh1 167b8851fccSafresh1 sub f10 { 168b8851fccSafresh1 @a = (1,2); 169b8851fccSafresh1 \$pkg10 = \$a[0]; 170b8851fccSafresh1 } 171b8851fccSafresh1 172b8851fccSafresh1} 173b8851fccSafresh1 174b8851fccSafresh1{ 175b8851fccSafresh1 use feature 'refaliasing'; 176b8851fccSafresh1 no warnings 'experimental'; 177b8851fccSafresh1 178b8851fccSafresh1 f11(); 179b8851fccSafresh1 my @b; 180b8851fccSafresh1 my @a = (@b); 181b8851fccSafresh1 is("@a", "2 1", "my: lex alias of array alements"); 182b8851fccSafresh1 183b8851fccSafresh1 sub f11 { 184b8851fccSafresh1 @a = (1,2); 185b8851fccSafresh1 \$b[0] = \$a[1]; 186b8851fccSafresh1 \$b[1] = \$a[0]; 187b8851fccSafresh1 } 188b8851fccSafresh1} 189b8851fccSafresh1 190b8851fccSafresh1# package aliasing 191b8851fccSafresh1 192b8851fccSafresh1{ 193b8851fccSafresh1 my ($x, $y) = (1,2); 194b8851fccSafresh1 195b8851fccSafresh1 for $pkg_scalar ($x) { 196b8851fccSafresh1 ($pkg_scalar, $y) = (3, $x); 197b8851fccSafresh1 is("$pkg_scalar,$y", "3,1", "package scalar aliased"); 198b8851fccSafresh1 } 199b8851fccSafresh1} 200b8851fccSafresh1 201b8851fccSafresh1# lvalue subs on LHS 202b8851fccSafresh1 203b8851fccSafresh1{ 204b8851fccSafresh1 my @a; 205b8851fccSafresh1 sub f12 : lvalue { @a } 206b8851fccSafresh1 (f12()) = 1..3; 207b8851fccSafresh1 is("@a", "1 2 3", "lvalue sub on RHS returns array"); 208b8851fccSafresh1} 209b8851fccSafresh1 210b8851fccSafresh1{ 211b8851fccSafresh1 my ($x,$y); 212b8851fccSafresh1 sub f13 : lvalue { $x,$y } 213b8851fccSafresh1 (f13()) = 1..3; 214b8851fccSafresh1 is("$x:$y", "1:2", "lvalue sub on RHS returns scalars"); 215b8851fccSafresh1} 216b8851fccSafresh1 217b8851fccSafresh1 218b8851fccSafresh1# package shared scalar vars 219b8851fccSafresh1 220b8851fccSafresh1{ 221b8851fccSafresh1 our $pkg14a = 1; 222b8851fccSafresh1 our $pkg14b = 2; 223b8851fccSafresh1 ($pkg14a,$pkg14b) = ($pkg14b,$pkg14a); 224b8851fccSafresh1 is("$pkg14a:$pkg14b", "2:1", "shared package scalars"); 225b8851fccSafresh1} 226b8851fccSafresh1 227b8851fccSafresh1# lexical shared scalar vars 228b8851fccSafresh1 229b8851fccSafresh1{ 230b8851fccSafresh1 my $a = 1; 231b8851fccSafresh1 my $b = 2; 232b8851fccSafresh1 ($a,$b) = ($b,$a); 233b8851fccSafresh1 is("$a:$b", "2:1", "shared lexical scalars"); 234b8851fccSafresh1} 235b8851fccSafresh1 236b8851fccSafresh1 237b8851fccSafresh1# lexical nested array elem swap 238b8851fccSafresh1 239b8851fccSafresh1{ 240b8851fccSafresh1 my @a; 241b8851fccSafresh1 $a[0][0] = 1; 242b8851fccSafresh1 $a[0][1] = 2; 243b8851fccSafresh1 ($a[0][0],$a[0][1]) = ($a[0][1],$a[0][0]); 244b8851fccSafresh1 is("$a[0][0]:$a[0][1]", "2:1", "lexical nested array elem swap"); 245b8851fccSafresh1} 246b8851fccSafresh1 247b8851fccSafresh1# package nested array elem swap 248b8851fccSafresh1 249b8851fccSafresh1{ 250b8851fccSafresh1 our @a15; 251b8851fccSafresh1 $a15[0][0] = 1; 252b8851fccSafresh1 $a15[0][1] = 2; 253b8851fccSafresh1 ($a15[0][0],$a15[0][1]) = ($a15[0][1],$a15[0][0]); 254b8851fccSafresh1 is("$a15[0][0]:$a15[0][1]", "2:1", "package nested array elem swap"); 255b8851fccSafresh1} 256b8851fccSafresh1 257b8851fccSafresh1# surplus RHS junk 258b8851fccSafresh1# 259b8851fccSafresh1{ 260b8851fccSafresh1 our ($a16, $b16); 261b8851fccSafresh1 ($a16, undef, $b16) = 1..30; 262b8851fccSafresh1 is("$a16:$b16", "1:3", "surplus RHS junk"); 263b8851fccSafresh1} 264b8851fccSafresh1 265b8851fccSafresh1# my ($scalar,....) = @_ 266b8851fccSafresh1# 267b8851fccSafresh1# technically this is an unsafe usage commonality-wise, but 268b8851fccSafresh1# a) you have to try really hard to break it, as this test shows; 269b8851fccSafresh1# b) it's such an important usage that for performance reasons we 270b8851fccSafresh1# mark it as safe even though it isn't really. Hence it's a TODO. 271b8851fccSafresh1 272b8851fccSafresh1SKIP: { 273b8851fccSafresh1 use Config; 274b8851fccSafresh1 # debugging builds will detect this failure and panic 2755759b3d2Safresh1 skip "DEBUGGING build" if $::Config{ccflags} =~ /(?<!\S)-DDEBUGGING(?!\S)/ 276b8851fccSafresh1 or $^O eq 'VMS' && $::Config{usedebugging_perl} eq 'Y'; 277b8851fccSafresh1 local $::TODO = 'cheat and optimise my (....) = @_'; 278b8851fccSafresh1 local @_ = 1..3; 279b8851fccSafresh1 &f17; 280b8851fccSafresh1 my ($a, @b) = @_; 281b8851fccSafresh1 is("($a)(@b)", "(3)(2 1)", 'my (....) = @_'); 282b8851fccSafresh1 283b8851fccSafresh1 sub f17 { 284b8851fccSafresh1 use feature 'refaliasing'; 285b8851fccSafresh1 no warnings 'experimental'; 286b8851fccSafresh1 ($a, @b) = @_; 287b8851fccSafresh1 \($_[2], $_[1], $_[0]) = \($a, $b[0], $b[1]); 288b8851fccSafresh1 } 289b8851fccSafresh1} 290b8851fccSafresh1 291b8851fccSafresh1# single scalar on RHS that's in an aggregate on LHS 292b8851fccSafresh1 293b8851fccSafresh1{ 294b8851fccSafresh1 my @a = 1..3; 295b8851fccSafresh1 for my $x ($a[0]) { 296b8851fccSafresh1 (@a) = ($x); 297b8851fccSafresh1 is ("(@a)", "(1)", 'single scalar on RHS, agg'); 298b8851fccSafresh1 } 299b8851fccSafresh1} 300b8851fccSafresh1 301b8851fccSafresh1# TEMP buffer stealing. 302b8851fccSafresh1# In something like 303b8851fccSafresh1# (...) = (f())[0,0] 304b8851fccSafresh1# the same TEMP RHS element may be used more than once, so when copying 305b8851fccSafresh1# it, we mustn't steal its buffer. 3065759b3d2Safresh1# DAPM 10/2016 - but in that case the SvTEMP flag is sometimes getting 3075759b3d2Safresh1# cleared: using split() instead as a source of temps seems more reliable, 3085759b3d2Safresh1# so I've added splut variants too. 309b8851fccSafresh1 310b8851fccSafresh1{ 311b8851fccSafresh1 # a string long enough for COW and buffer stealing to be enabled 312b8851fccSafresh1 my $long = 'def' . ('x' x 2000); 313b8851fccSafresh1 314b8851fccSafresh1 # a sub that is intended to return a TEMP string that isn't COW 315b8851fccSafresh1 # the concat returns a non-COW PADTMP; pp_leavesub sees a long 316b8851fccSafresh1 # stealable string, so creates a TEMP with the stolen buffer from the 3175759b3d2Safresh1 # PADTMP - hence it returns a non-COW string. It also returns a couple 3185759b3d2Safresh1 # of key strings for the hash tests 319b8851fccSafresh1 sub f18 { 320b8851fccSafresh1 my $x = "abc"; 3215759b3d2Safresh1 ($x . $long, "key1", "key2"); 322b8851fccSafresh1 } 323b8851fccSafresh1 3245759b3d2Safresh1 my (@a, %h); 325b8851fccSafresh1 326b8851fccSafresh1 # with @a initially empty,the code path creates a new copy of each 327b8851fccSafresh1 # RHS element to store in the array 328b8851fccSafresh1 329b8851fccSafresh1 @a = (f18())[0,0]; 3305759b3d2Safresh1 is (substr($a[0], 0, 7), "abcdefx", 'NOSTEAL f18 empty $a[0]'); 3315759b3d2Safresh1 is (substr($a[1], 0, 7), "abcdefx", 'NOSTEAL f18 empty $a[1]'); 3325759b3d2Safresh1 @a = (split /-/, "abc-def")[0,0]; 3335759b3d2Safresh1 is ($a[0], "abc", 'NOSTEAL split empty $a[0]'); 3345759b3d2Safresh1 is ($a[1], "abc", 'NOSTEAL split empty $a[1]'); 335b8851fccSafresh1 336b8851fccSafresh1 # with @a initially non-empty, it takes a different code path that 337b8851fccSafresh1 # makes a mortal copy of each RHS element 338b8851fccSafresh1 @a = 1..3; 339b8851fccSafresh1 @a = (f18())[0,0]; 3405759b3d2Safresh1 is (substr($a[0], 0, 7), "abcdefx", 'NOSTEAL f18 non-empty $a[0]'); 3415759b3d2Safresh1 is (substr($a[1], 0, 7), "abcdefx", 'NOSTEAL f18 non-empty $a[1]'); 3425759b3d2Safresh1 @a = 1..3; 3435759b3d2Safresh1 @a = (split /-/, "abc-def")[0,0]; 3445759b3d2Safresh1 is ($a[0], "abc", 'NOSTEAL split non-empty $a[0]'); 3455759b3d2Safresh1 is ($a[1], "abc", 'NOSTEAL split non-empty $a[1]'); 346b8851fccSafresh1 3475759b3d2Safresh1 # similarly with PADTMPs 3485759b3d2Safresh1 3495759b3d2Safresh1 @a = (); 3505759b3d2Safresh1 @a = ($long . "x")[0,0]; 3515759b3d2Safresh1 is (substr($a[0], 0, 4), "defx", 'NOSTEAL PADTMP empty $a[0]'); 3525759b3d2Safresh1 is (substr($a[1], 0, 4), "defx", 'NOSTEAL PADTMP empty $a[1]'); 3535759b3d2Safresh1 3545759b3d2Safresh1 @a = 1..3; 3555759b3d2Safresh1 @a = ($long . "x")[0,0]; 3565759b3d2Safresh1 is (substr($a[0], 0, 4), "defx", 'NOSTEAL PADTMP non-empty $a[0]'); 3575759b3d2Safresh1 is (substr($a[1], 0, 4), "defx", 'NOSTEAL PADTMP non-empty $a[1]'); 3585759b3d2Safresh1 3595759b3d2Safresh1 # as above, but assigning to a hash 3605759b3d2Safresh1 3615759b3d2Safresh1 %h = (f18())[1,0,2,0]; 3625759b3d2Safresh1 is (substr($h{key1}, 0, 7), "abcdefx", 'NOSTEAL f18 empty $h{key1}'); 3635759b3d2Safresh1 is (substr($h{key2}, 0, 7), "abcdefx", 'NOSTEAL f18 empty $h{key2}'); 3645759b3d2Safresh1 %h = (split /-/, "key1-val-key2")[0,1,2,1]; 3655759b3d2Safresh1 is ($h{key1}, "val", 'NOSTEAL split empty $h{key1}'); 3665759b3d2Safresh1 is ($h{key2}, "val", 'NOSTEAL split empty $h{key2}'); 3675759b3d2Safresh1 3685759b3d2Safresh1 %h = qw(key1 foo key2 bar key3 baz); 3695759b3d2Safresh1 %h = (f18())[1,0,2,0]; 3705759b3d2Safresh1 is (substr($h{key1}, 0, 7), "abcdefx", 'NOSTEAL f18 non-empty $h{key1}'); 3715759b3d2Safresh1 is (substr($h{key2}, 0, 7), "abcdefx", 'NOSTEAL f18 non-empty $h{key2}'); 3725759b3d2Safresh1 %h = qw(key1 foo key2 bar key3 baz); 3735759b3d2Safresh1 %h = (split /-/, "key1-val-key2")[0,1,2,1]; 3745759b3d2Safresh1 is ($h{key1}, "val", 'NOSTEAL split non-empty $h{key1}'); 3755759b3d2Safresh1 is ($h{key2}, "val", 'NOSTEAL split non-empty $h{key2}'); 3765759b3d2Safresh1 3775759b3d2Safresh1 %h = (); 3785759b3d2Safresh1 %h = ($long . "x", "key1", "key2")[1,0,2,0]; 3795759b3d2Safresh1 is (substr($h{key1}, 0, 4), "defx", 'NOSTEAL PADTMP empty $h{key1}'); 3805759b3d2Safresh1 is (substr($h{key2}, 0, 4), "defx", 'NOSTEAL PADTMP empty $h{key2}'); 3815759b3d2Safresh1 3825759b3d2Safresh1 %h = qw(key1 foo key2 bar key3 baz); 3835759b3d2Safresh1 %h = ($long . "x", "key1", "key2")[1,0,2,0]; 3845759b3d2Safresh1 is (substr($h{key1}, 0, 4), "defx", 'NOSTEAL PADTMP non-empty $h{key1}'); 3855759b3d2Safresh1 is (substr($h{key2}, 0, 4), "defx", 'NOSTEAL PADTMP non-empty $h{key2}'); 3865759b3d2Safresh1 3875759b3d2Safresh1 # both keys and values stealable 3885759b3d2Safresh1 @a = (%h = (split /-/, "abc-def")[0,1,0,1]); 389*eac174f2Safresh1 is (join(':', keys %h), "abc", "NOSTEAL split list-context keys"); 390*eac174f2Safresh1 is (join(':', values %h), "def", "NOSTEAL split list-context values"); 391*eac174f2Safresh1 is (join(':', @a), "abc:def", "NOSTEAL split list-context result"); 392b8851fccSafresh1} 393b8851fccSafresh1 394b8851fccSafresh1{ 395b8851fccSafresh1 my $x = 1; 396b8851fccSafresh1 my $y = 2; 397b8851fccSafresh1 ($x,$y) = (undef, $x); 398b8851fccSafresh1 is($x, undef, 'single scalar on RHS, but two on LHS: x'); 399b8851fccSafresh1 is($y, 1, 'single scalar on RHS, but two on LHS: y'); 400b8851fccSafresh1} 401b8851fccSafresh1 402b8851fccSafresh1{ # magic handling, see #126633 403b8851fccSafresh1 use v5.22; 404b8851fccSafresh1 my $set; 405b8851fccSafresh1 package ArrayProxy { 406b8851fccSafresh1 sub TIEARRAY { bless [ $_[1] ] } 407b8851fccSafresh1 sub STORE { $_[0][0]->[$_[1]] = $_[2]; $set = 1 } 408b8851fccSafresh1 sub FETCH { $_[0][0]->[$_[1]] } 409b8851fccSafresh1 sub CLEAR { @{$_[0][0]} = () } 410b8851fccSafresh1 sub EXTEND {} 411b8851fccSafresh1 }; 412b8851fccSafresh1 my @base = ( "a", "b" ); 413b8851fccSafresh1 my @real = @base; 414b8851fccSafresh1 my @proxy; 415b8851fccSafresh1 my $temp; 416b8851fccSafresh1 tie @proxy, "ArrayProxy", \@real; 417b8851fccSafresh1 @proxy[0, 1] = @real[1, 0]; 418b8851fccSafresh1 is($real[0], "b", "tied left first"); 419b8851fccSafresh1 is($real[1], "a", "tied left second"); 420b8851fccSafresh1 @real = @base; 421b8851fccSafresh1 @real[0, 1] = @proxy[1, 0]; 422b8851fccSafresh1 is($real[0], "b", "tied right first"); 423b8851fccSafresh1 is($real[1], "a", "tied right second"); 424b8851fccSafresh1 @real = @base; 425b8851fccSafresh1 @proxy[0, 1] = @proxy[1, 0]; 426b8851fccSafresh1 is($real[0], "b", "tied both first"); 427b8851fccSafresh1 is($real[1], "a", "tied both second"); 428b8851fccSafresh1 @real = @base; 429b8851fccSafresh1 ($temp, @real) = @proxy[1, 0]; 430b8851fccSafresh1 is($real[0], "a", "scalar/array tied right"); 431b8851fccSafresh1 @real = @base; 432b8851fccSafresh1 ($temp, @proxy) = @real[1, 0]; 433b8851fccSafresh1 is($real[0], "a", "scalar/array tied left"); 434b8851fccSafresh1 @real = @base; 435b8851fccSafresh1 ($temp, @proxy) = @proxy[1, 0]; 436b8851fccSafresh1 is($real[0], "a", "scalar/array tied both"); 437b8851fccSafresh1 $set = 0; 438b8851fccSafresh1 my $orig; 439b8851fccSafresh1 ($proxy[0], $orig) = (1, $set); 440b8851fccSafresh1 is($orig, 0, 'previous value of $set'); 441b8851fccSafresh1 442b8851fccSafresh1 # from cpan #110278 443b8851fccSafresh1 SKIP: { 444b8851fccSafresh1 skip "no List::Util::min on miniperl", 2, if is_miniperl; 445b8851fccSafresh1 require List::Util; 446b8851fccSafresh1 my $x = 1; 447b8851fccSafresh1 my $y = 2; 448b8851fccSafresh1 ( $x, $y ) = ( List::Util::min($y), List::Util::min($x) ); 449b8851fccSafresh1 is($x, 2, "check swap for \$x"); 450b8851fccSafresh1 is($y, 1, "check swap for \$y"); 451b8851fccSafresh1 } 452b8851fccSafresh1} 453b8851fccSafresh1 4545759b3d2Safresh1{ 4555759b3d2Safresh1 # check that a second aggregate is empted but doesn't suck up 4565759b3d2Safresh1 # anything random 4575759b3d2Safresh1 4585759b3d2Safresh1 my (@a, @b) = qw(x y); 4595759b3d2Safresh1 is(+@a, 2, "double array A len"); 4605759b3d2Safresh1 is(+@b, 0, "double array B len"); 4615759b3d2Safresh1 is("@a", "x y", "double array A contents"); 4625759b3d2Safresh1 4635759b3d2Safresh1 @a = 1..10; 4645759b3d2Safresh1 @b = 100..200; 4655759b3d2Safresh1 (@a, @b) = qw(x y); 4665759b3d2Safresh1 is(+@a, 2, "double array non-empty A len"); 4675759b3d2Safresh1 is(+@b, 0, "double array non-empty B len"); 4685759b3d2Safresh1 is("@a", "x y", "double array non-empty A contents"); 4695759b3d2Safresh1 4705759b3d2Safresh1 my (%a, %b) = qw(k1 v1 k2 v2); 4715759b3d2Safresh1 is(+(keys %a), 2, "double hash A len"); 4725759b3d2Safresh1 is(+(keys %b), 0, "double hash B len"); 4735759b3d2Safresh1 is(join(' ', sort keys %a), "k1 k2", "double hash A keys"); 4745759b3d2Safresh1 is(join(' ', sort values %a), "v1 v2", "double hash A values"); 4755759b3d2Safresh1 4765759b3d2Safresh1 %a = 1..10; 4775759b3d2Safresh1 %b = 101..200; 4785759b3d2Safresh1 (%a, %b) = qw(k1 v1 k2 v2); 4795759b3d2Safresh1 is(+(keys %a), 2, "double hash non-empty A len"); 4805759b3d2Safresh1 is(+(keys %b), 0, "double hash non-empty B len"); 4815759b3d2Safresh1 is(join(' ', sort keys %a), "k1 k2", "double hash non-empty A keys"); 4825759b3d2Safresh1 is(join(' ', sort values %a), "v1 v2", "double hash non-empty A values"); 4835759b3d2Safresh1} 4845759b3d2Safresh1 4855759b3d2Safresh1# list and lval context: filling of missing elements, returning correct 4865759b3d2Safresh1# lvalues. 4875759b3d2Safresh1# ( Note that these partially duplicate some tests in hashassign.t which 4885759b3d2Safresh1# I didn't spot at first - DAPM) 4895759b3d2Safresh1 4905759b3d2Safresh1{ 4915759b3d2Safresh1 my ($x, $y, $z); 4925759b3d2Safresh1 my (@a, %h); 4935759b3d2Safresh1 4945759b3d2Safresh1 sub lval { 4955759b3d2Safresh1 my $n = shift; 4965759b3d2Safresh1 my $desc = shift; 4975759b3d2Safresh1 is($x, $n >= 1 ? "assign1" : undef, "lval: X pre $n $desc"); 4985759b3d2Safresh1 is($y, $n >= 2 ? "assign2" : undef, "lval: Y pre $n $desc"); 4995759b3d2Safresh1 is($z, undef, "lval: Z pre $n $desc"); 5005759b3d2Safresh1 5015759b3d2Safresh1 my $i = 0; 5025759b3d2Safresh1 for (@_) { 5035759b3d2Safresh1 $_ = "lval$i"; 5045759b3d2Safresh1 $i++; 5055759b3d2Safresh1 } 5065759b3d2Safresh1 is($x, "lval0", "lval: a post $n $desc"); 5075759b3d2Safresh1 is($y, "lval1", "lval: b post $n $desc"); 5085759b3d2Safresh1 is($z, "lval2", "lval: c post $n $desc"); 5095759b3d2Safresh1 } 5105759b3d2Safresh1 lval(0, "XYZ", (($x,$y,$z) = ())); 5115759b3d2Safresh1 lval(1, "XYZ", (($x,$y,$z) = (qw(assign1)))); 5125759b3d2Safresh1 lval(2, "XYZ", (($x,$y,$z) = (qw(assign1 assign2)))); 5135759b3d2Safresh1 5145759b3d2Safresh1 lval(0, "XYZA", (($x,$y,$z,@a) = ())); 5155759b3d2Safresh1 lval(1, "XYZA", (($x,$y,$z,@a) = (qw(assign1)))); 5165759b3d2Safresh1 lval(2, "XYZA", (($x,$y,$z,@a) = (qw(assign1 assign2)))); 5175759b3d2Safresh1 5185759b3d2Safresh1 lval(0, "XYAZ", (($x,$y,@a,$z) = ())); 5195759b3d2Safresh1 lval(1, "XYAZ", (($x,$y,@a,$z) = (qw(assign1)))); 5205759b3d2Safresh1 lval(2, "XYAZ", (($x,$y,@a,$z) = (qw(assign1 assign2)))); 5215759b3d2Safresh1 5225759b3d2Safresh1 lval(0, "XYZH", (($x,$y,$z,%h) = ())); 5235759b3d2Safresh1 lval(1, "XYZH", (($x,$y,$z,%h) = (qw(assign1)))); 5245759b3d2Safresh1 lval(2, "XYZH", (($x,$y,$z,%h) = (qw(assign1 assign2)))); 5255759b3d2Safresh1 5265759b3d2Safresh1 lval(0, "XYHZ", (($x,$y,%h,$z) = ())); 5275759b3d2Safresh1 lval(1, "XYHZ", (($x,$y,%h,$z) = (qw(assign1)))); 5285759b3d2Safresh1 lval(2, "XYHZ", (($x,$y,%h,$z) = (qw(assign1 assign2)))); 5295759b3d2Safresh1 5305759b3d2Safresh1 # odd number of hash elements 5315759b3d2Safresh1 5325759b3d2Safresh1 { 5335759b3d2Safresh1 no warnings 'misc'; 5345759b3d2Safresh1 @a = ((%h) = qw(X)); 5355759b3d2Safresh1 is (join(":", map $_ // "u", @a), "X:u", "lval odd singleton"); 5365759b3d2Safresh1 @a = (($x, $y, %h) = qw(X Y K)); 5375759b3d2Safresh1 is (join(":", map $_ // "u", @a), "X:Y:K:u", "lval odd"); 5385759b3d2Safresh1 @a = (($x, $y, %h, $z) = qw(X Y K)); 5395759b3d2Safresh1 is (join(":", map $_ // "u", @a), "X:Y:K:u:u", "lval odd with z"); 5405759b3d2Safresh1 } 5415759b3d2Safresh1 5425759b3d2Safresh1 # undef on LHS uses RHS as lvalue instead 54356d68f1eSafresh1 # Note that this just codifies existing behaviour - it may not be 5445759b3d2Safresh1 # correct. See http://nntp.perl.org/group/perl.perl5.porters/240358. 5455759b3d2Safresh1 5465759b3d2Safresh1 { 5475759b3d2Safresh1 ($x, $y, $z) = (0, 10, 20); 5485759b3d2Safresh1 $_++ for ((undef, $x) = ($y, $z)); 5495759b3d2Safresh1 is "$x:$y:$z", "21:11:20", "undef as lvalue"; 5505759b3d2Safresh1 } 5515759b3d2Safresh1 5525759b3d2Safresh1} 5535759b3d2Safresh1 5545759b3d2Safresh1{ 5555759b3d2Safresh1 # [perl #129991] assert failure in S_aassign_copy_common 5565759b3d2Safresh1 # the LHS of a list assign can be aliased to an immortal SV; 5575759b3d2Safresh1 # we used to assert that this couldn't happen 5585759b3d2Safresh1 eval { ($_,$0)=(1,0) for 0 gt 0 }; 5595759b3d2Safresh1 like($@, qr//, "RT #129991"); 5605759b3d2Safresh1} 5615759b3d2Safresh1 5625759b3d2Safresh1{ 5635759b3d2Safresh1 # [perl #130132] 5645759b3d2Safresh1 # lexical refs on LHS, dereffed on the RHS 5655759b3d2Safresh1 5665759b3d2Safresh1 my $fill; 5675759b3d2Safresh1 5685759b3d2Safresh1 my $sref = do { my $tmp = 2; \$tmp }; 5695759b3d2Safresh1 ($sref, $fill) = (1, $$sref); 5705759b3d2Safresh1 is ($sref, 1, "RT #130132 scalar 1"); 5715759b3d2Safresh1 is ($fill, 2, "RT #130132 scalar 2"); 5725759b3d2Safresh1 5735759b3d2Safresh1 my $x = 1; 5745759b3d2Safresh1 $sref = \$x; 5755759b3d2Safresh1 ($sref, $$sref) = (2, 3); 5765759b3d2Safresh1 is ($sref, 2, "RT #130132 scalar derefffed 1"); 5775759b3d2Safresh1 is ($x, 3, "RT #130132 scalar derefffed 2"); 5785759b3d2Safresh1 5795759b3d2Safresh1 $x = 1; 5805759b3d2Safresh1 $sref = \$x; 5815759b3d2Safresh1 ($sref, $$sref) = (2); 5825759b3d2Safresh1 is ($sref, 2, "RT #130132 scalar undef 1"); 5835759b3d2Safresh1 is ($x, undef, "RT #130132 scalar undef 2"); 5845759b3d2Safresh1 5855759b3d2Safresh1 my @a; 5865759b3d2Safresh1 $sref = do { my $tmp = 2; \$tmp }; 5875759b3d2Safresh1 @a = (($sref) = (1, $$sref)); 5885759b3d2Safresh1 is ($sref, 1, "RT #130132 scalar list cxt 1"); 5895759b3d2Safresh1 is ($a[0], 1, "RT #130132 scalar list cxt a[0]"); 5905759b3d2Safresh1 5915759b3d2Safresh1 my $aref = [ 1, 2 ]; 5925759b3d2Safresh1 ($aref, $fill) = @$aref; 5935759b3d2Safresh1 is ($aref, 1, "RT #130132 array 1"); 5945759b3d2Safresh1 is ($fill, 2, "RT #130132 array 2"); 5955759b3d2Safresh1} 5965759b3d2Safresh1 59756d68f1eSafresh1{ 598*eac174f2Safresh1 # GH #17816 59956d68f1eSafresh1 # don't use the "1-arg on LHS can't be common" optimisation 60056d68f1eSafresh1 # when there are undef's there 60156d68f1eSafresh1 my $x = 1; 60256d68f1eSafresh1 my @a = (($x, undef) = (2 => $x)); 60356d68f1eSafresh1 is("@a", "2 1", "GH #17816"); 60456d68f1eSafresh1} 60556d68f1eSafresh1 60656d68f1eSafresh1{ 607*eac174f2Safresh1 # GH #16685 60856d68f1eSafresh1 # honour trailing undef's in list context 60956d68f1eSafresh1 my $x = 1; 61056d68f1eSafresh1 my @a = (($x, undef, undef) = (1)); 611*eac174f2Safresh1 is(scalar @a, 3, "GH #16685"); 61256d68f1eSafresh1} 61356d68f1eSafresh1 61456d68f1eSafresh1 615b8851fccSafresh1done_testing(); 616