This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
lvref.t: do-block err msg is no longer to-do
[perl5.git] / t / op / lvref.t
index 4c4035d..2cd863b 100644 (file)
@@ -4,7 +4,7 @@ BEGIN {
     set_up_inc("../lib");
 }
 
-plan 22;
+plan 104;
 
 sub on { $::TODO = ' ' }
 sub off{ $::TODO = ''  }
@@ -12,6 +12,9 @@ sub off{ $::TODO = ''  }
 eval '\$x = \$y';
 like $@, qr/^Experimental lvalue references not enabled/,
     'error when feature is disabled';
+eval '\($x) = \$y';
+like $@, qr/^Experimental lvalue references not enabled/,
+    'error when feature is disabled (aassign)';
 
 use feature 'lvalue_refs';
 
@@ -22,6 +25,11 @@ use feature 'lvalue_refs';
     is $c, 1, 'one warning from lv ref assignment';
     like $w, qr/^Lvalue references are experimental/,
         'experimental warning';
+    undef $c;
+    eval '\($x) = \$y';
+    is $c, 1, 'one warning from lv ref list assignment';
+    like $w, qr/^Lvalue references are experimental/,
+        'experimental warning';
 }
 
 no warnings 'experimental::lvalue_refs';
@@ -33,43 +41,194 @@ is \$x, \$y, '\$pkg_scalar = ...';
 my $m;
 \$m = \$y;
 is \$m, \$y, '\$lexical = ...';
-on;
-eval '\my $n = \$y';
+\my $n = \$y;
 is \$n, \$y, '\my $lexical = ...';
 @_ = \$_;
-eval '\($x) = @_';
+\($x) = @_;
 is \$x, \$_, '\($pkgvar) = ... gives list context';
+undef *x;
+(\$x) = @_;
+is \$x, \$_, '(\$pkgvar) = ... gives list context';
 my $o;
-eval '\($o) = @_';
+\($o) = @_;
 is \$o, \$_, '\($lexical) = ... gives list cx';
-eval '\(my $p) = @_';
+my $q;
+(\$q) = @_;
+is \$q, \$_, '(\$lexical) = ... gives list cx';
+\(my $p) = @_;
 is \$p, \$_, '\(my $lexical) = ... gives list cx';
-eval '\($_a, my $a) = @{[\$b, \$c]}';
+(\my $r) = @_;
+is \$r, \$_, '(\my $lexical) = ... gives list cx';
+\my($s) = @_;
+is \$s, \$_, '\my($lexical) = ... gives list cx';
+\($_a, my $a) = @{[\$b, \$c]};
 is \$_a, \$b, 'package scalar in \(...)';
 is \$a, \$c, 'lex scalar in \(...)';
-eval '(\$_b, \my $b) = @{[\$b, \$c]}';
+(\$_b, \my $b) = @{[\$b, \$c]};
 is \$_b, \$::b, 'package scalar in (\$foo, \$bar)';
 is \$b, \$c, 'lex scalar in (\$foo, \$bar)';
-is eval '\local $l = \3; $l', 3, '\local $scalar assignment';
-off;
+is do { \local $l = \3; $l }, 3, '\local $scalar assignment';
 is $l, undef, 'localisation unwound';
-on;
+is do { \(local $l) = \4; $l }, 4, '\(local $scalar) assignment';
+is $l, undef, 'localisation unwound';
+\$foo = \*bar;
+is *foo{SCALAR}, *bar{GLOB}, 'globref-to-scalarref assignment';
 
 # Array Elements
 
-# ...
+sub expect_scalar_cx { wantarray ? 0 : \$_ }
+sub expect_list_cx { wantarray ? (\$_,\$_) : 0 }
+\$a[0] = expect_scalar_cx;
+is \$a[0], \$_, '\$array[0]';
+\($a[1]) = expect_list_cx;
+is \$a[1], \$_, '\($array[0])';
+{
+  my @a;
+  \$a[0] = expect_scalar_cx;
+  is \$a[0], \$_, '\$lexical_array[0]';
+  \($a[1]) = expect_list_cx;
+  is \$a[1], \$_, '\($lexical_array[0])';
+  my $tmp;
+  {
+    \local $a[0] = \$tmp;
+    is \$a[0], \$tmp, '\local $a[0]';
+  }
+  is \$a[0], \$_, '\local $a[0] unwound';
+  {
+    \local ($a[1]) = \$tmp;
+    is \$a[1], \$tmp, '\local ($a[0])';
+  }
+  is \$a[1], \$_, '\local $a[0] unwound';
+}
+{
+  my @a;
+  \@a[0,1] = expect_list_cx;
+  is \$a[0].\$a[1], \$_.\$_, '\@array[indices]';
+  \(@a[2,3]) = expect_list_cx;
+  is \$a[0].\$a[1], \$_.\$_, '\(@array[indices])';
+  my $tmp;
+  {
+    \local @a[0,1] = (\$tmp)x2;
+    is \$a[0].\$a[1], \$tmp.\$tmp, '\local @a[indices]';
+  }
+  is \$a[0].\$a[1], \$_.\$_, '\local @a[indices] unwound';
+}
 
 # Hash Elements
 
-# ...
+\$h{a} = expect_scalar_cx;
+is \$h{a}, \$_, '\$hash{a}';
+\($h{b}) = expect_list_cx;
+is \$h{b}, \$_, '\($hash{a})';
+{
+  my @h;
+  \$h{a} = expect_scalar_cx;
+  is \$h{a}, \$_, '\$lexical_array{a}';
+  \($h{b}) = expect_list_cx;
+  is \$h{b}, \$_, '\($lexical_array{a})';
+  my $tmp;
+  {
+    \local $h{a} = \$tmp;
+    is \$h{a}, \$tmp, '\local $h{a}';
+  }
+  is \$h{a}, \$_, '\local $h{a} unwound';
+  {
+    \local ($h{b}) = \$tmp;
+    is \$h{b}, \$tmp, '\local ($h{a})';
+  }
+  is \$h{b}, \$_, '\local $h{a} unwound';
+}
+{
+  my @h;
+  \@h{"a","b"} = expect_list_cx;
+  is \$h{a}.\$h{b}, \$_.\$_, '\@hash{indices}';
+  \(@h{2,3}) = expect_list_cx;
+  is \$h{a}.\$h{b}, \$_.\$_, '\(@hash{indices})';
+  my $tmp;
+  {
+    \local @h{"a","b"} = (\$tmp)x2;
+    is \$h{a}.\$h{b}, \$tmp.\$tmp, '\local @h{indices}';
+  }
+  is \$h{a}.\$h{b}, \$_.\$_, '\local @h{indices} unwound';
+}
 
 # Arrays
 
-# ...
+package ArrayTest {
+  BEGIN { *is = *main::is }
+  sub expect_scalar_cx { wantarray ? 0 : \@ThatArray }
+  sub expect_list_cx   { wantarray ? (\$_,\$_) : 0 }
+  sub expect_list_cx_a { wantarray ? (\@ThatArray)x2 : 0 }
+  eval '\@a = expect_scalar_cx';
+  is \@a, \@ThatArray, '\@pkg';
+  my @a;
+  \@a = expect_scalar_cx;
+  is \@a, \@ThatArray, '\@lexical';
+  (\@b) = expect_list_cx_a;
+  is \@b, \@ThatArray, '(\@pkg)';
+  my @b;
+  (\@b) = expect_list_cx_a;
+  is \@b, \@ThatArray, '(\@lexical)';
+  \my @c = expect_scalar_cx;
+  is \@c, \@ThatArray, '\my @lexical';
+  (\my @d) = expect_list_cx_a;
+  is \@d, \@ThatArray, '(\my @lexical)';
+  \(@e) = expect_list_cx;
+  is \$e[0].\$e[1], \$_.\$_, '\(@pkg)';
+  my @e;
+  \(@e) = expect_list_cx;
+  is \$e[0].\$e[1], \$_.\$_, '\(@lexical)';
+  \(my @f) = expect_list_cx;
+  is \$f[0].\$f[1], \$_.\$_, '\(my @lexical)';
+  \my(@g) = expect_list_cx;
+  is \$g[0].\$g[1], \$_.\$_, '\my(@lexical)';
+  my $old = \@h;
+  {
+    \local @h = \@ThatArray;
+    is \@h, \@ThatArray, '\local @a';
+  }
+  is \@h, $old, '\local @a unwound';
+  $old = \@i;
+  eval q{
+    (\local @i) = \@ThatArray;
+    is \@i, \@ThatArray, '(\local @a)';
+  } or do { SKIP: { ::skip 'unimplemented' } };
+  is \@i, $old, '(\local @a) unwound';
+}
 
 # Hashes
 
-# ...
+package HashTest {
+  BEGIN { *is = *main::is }
+  sub expect_scalar_cx { wantarray ? 0 : \%ThatHash }
+  sub expect_list_cx   { wantarray ? (\%ThatHash)x2 : 0 }
+  \%a = expect_scalar_cx;
+  is \%a, \%ThatHash, '\%pkg';
+  my %a;
+  \%a = expect_scalar_cx;
+  is \%a, \%ThatHash, '\%lexical';
+  (\%b) = expect_list_cx;
+  is \%b, \%ThatHash, '(\%pkg)';
+  my %b;
+  (\%b) = expect_list_cx;
+  is \%b, \%ThatHash, '(\%lexical)';
+  \my %c = expect_scalar_cx;
+  is \%c, \%ThatHash, '\my %lexical';
+  (\my %d) = expect_list_cx;
+  is \%d, \%ThatHash, '(\my %lexical)';
+  my $old = \%h;
+  {
+    \local %h = \%ThatHash;
+    is \%h, \%ThatHash, '\local %a';
+  }
+  is \%h, $old, '\local %a unwound';
+  $old = \%i;
+  eval q{
+    (\local %i) = \%ThatHash;
+    is \%i, \%ThatHash, '(\local %a)';
+  } or do { SKIP: { ::skip 'unimplemented' } };
+  is \%i, $old, '(\local %a) unwound';
+}
 
 # Subroutines
 
@@ -77,7 +236,56 @@ on;
 
 # Mixed List Assignments
 
-# ...
+(\$tahi, $rua) = \(1,2);
+is join(' ', $tahi, $$rua), '1 2',
+  'mixed scalar ref and scalar list assignment';
+
+# Conditional expressions
+
+$_ = 3;
+$_ == 3 ? \$tahi : $rua = \3;
+is $tahi, 3, 'cond assignment resolving to scalar ref';
+$_ == 0 ? \$toru : $wha = \3;
+is $$wha, 3, 'cond assignment resolving to scalar';
+$_ == 3 ? \$rima : \$ono = \5;
+is $rima, 5, 'cond assignment with refgens on both branches';
+\($_ == 3 ? $whitu : $waru) = \5;
+is $whitu, 5, '\( ?: ) assignment';
+
+# Foreach
+
+on;
+eval '
+  for \my $a(\$for1, \$for2) {
+    push @for, \$a;
+  }
+';
+is "@for", \$for1 . ' ' . \$for2, 'foreach \my $a';
+
+@for = ();
+eval '
+  for \my @a([1,2], [3,4]) {
+    push @for, @a;
+  }
+';
+is "@for", "1 2 3 4", 'foreach \my @a [perl #22335]';
+
+@for = ();
+eval '
+  for \my %a({5,6}, {7,8}) {
+    push @for, %a;
+  }
+';
+is "@for", "5 6 7 8", 'foreach \my %a [perl #22335]';
+
+@for = ();
+eval '
+  for \my &a(sub {9}, sub {10}) {
+    push @for, &a;
+  }
+';
+is "@for", "9 10", 'foreach \my &a';
+
 
 # Errors
 
@@ -90,8 +298,67 @@ like $@, qr/^Assigned value is not a SCALAR reference at/,
 eval { \$::x = [] };
 like $@, qr/^Assigned value is not a SCALAR reference at/,
     'assigning non-scalar ref to package scalar ref';
+eval { my @x; \@x = {} };
+like $@, qr/^Assigned value is not an ARRAY reference at/,
+    'assigning non-array ref to array ref';
+eval { \@::x = {} };
+like $@, qr/^Assigned value is not an ARRAY reference at/,
+    'assigning non-array ref to package array ref';
+eval { my %x; \%x = [] };
+like $@, qr/^Assigned value is not a HASH reference at/,
+    'assigning non-hash ref to hash ref';
+eval { \%::x = [] };
+like $@, qr/^Assigned value is not a HASH reference at/,
+    'assigning non-hash ref to package hash ref';
+
+eval '(\do{}) = 42';
+like $@, qr/^Can't modify reference to do block in list assignment at /,
+    "Can't modify reference to do block in list assignment";
+eval '(\pos) = 42';
+like $@,
+     qr/^Can't modify reference to match position in list assignment at /,
+    "Can't modify ref to some scalar-returning op in list assignment";
+eval '(\glob) = 42';
+like $@,
+     qr/^Can't modify reference to glob in list assignment at /,
+    "Can't modify reference to some list-returning op in list assignment";
+eval '\pos = 42';
+like $@,
+    qr/^Can't modify reference to match position in scalar assignment at /,
+   "Can't modify ref to some scalar-returning op in scalar assignment";
+eval '\(local @b) = 42';
+like $@,
+    qr/^Can't modify reference to localized parenthesized array in list(?x:
+      ) assignment at /,
+   q"Can't modify \(local @array) in list assignment";
+eval '\local(@b) = 42';
+like $@,
+    qr/^Can't modify reference to localized parenthesized array in list(?x:
+      ) assignment at /,
+   q"Can't modify \local(@array) in list assignment";
+eval '\local(@{foo()}) = 42';
+like $@,
+    qr/^Can't modify reference to array dereference in list assignment at/,
+   q"'Array deref' error takes prec. over 'local paren' error";
+eval '\(%b) = 42';
+like $@,
+    qr/^Can't modify reference to parenthesized hash in list assignment a/,
+   "Can't modify ref to parenthesized package hash in scalar assignment";
+eval '\(my %b) = 42';
+like $@,
+    qr/^Can't modify reference to parenthesized hash in list assignment a/,
+   "Can't modify ref to parenthesized hash (\(my %b)) in list assignment";
+eval '\my(%b) = 42';
+like $@,
+    qr/^Can't modify reference to parenthesized hash in list assignment a/,
+   "Can't modify ref to parenthesized hash (\my(%b)) in list assignment";
+eval '\%{"42"} = 42';
+like $@,
+    qr/^Can't modify reference to hash dereference in scalar assignment a/,
+   "Can't modify reference to hash dereference in scalar assignment";
 on;
 
+
 # Miscellaneous
 
 {