summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2007-09-08 22:34:29 +0000
committerNicholas Clark <nick@ccl4.org>2007-09-08 22:34:29 +0000
commit6dbe9451abb7e30d650de45d484c69e6c34bbd36 (patch)
tree9ffa248394ec7c0919a7a814e2e1b1a461f0f674
parentaab6a793686b4f073e16b436e1705cd0e9106ced (diff)
downloadperl-6dbe9451abb7e30d650de45d484c69e6c34bbd36.tar.gz
For now, forbid all list assignment initialisation of state variables,
as the precise semantics in Perl 6 are not clear. Better to make it a syntax error, than to have one behaviour now, but change it later. [I believe that this is the consensus. If not, it will be backed out] p4raw-id: //depot/perl@31824
-rw-r--r--op.c50
-rw-r--r--pod/perldiag.pod7
-rw-r--r--t/op/state.t38
3 files changed, 83 insertions, 12 deletions
diff --git a/op.c b/op.c
index 6975d83824..ca488a279b 100644
--- a/op.c
+++ b/op.c
@@ -3968,6 +3968,8 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
}
if (is_list_assignment(left)) {
+ static const char no_list_state[] = "Initialization of state variables"
+ " in list context currently forbidden";
OP *curop;
PL_modcount = 0;
@@ -4061,6 +4063,54 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right)
o->op_private |= OPpASSIGN_COMMON;
}
+ if ((left->op_type == OP_LIST
+ || (left->op_type == OP_NULL && left->op_targ == OP_LIST))) {
+ OP* lop = ((LISTOP*)left)->op_first;
+ while (lop) {
+ if (lop->op_type == OP_PADSV ||
+ lop->op_type == OP_PADAV ||
+ lop->op_type == OP_PADHV ||
+ lop->op_type == OP_PADANY) {
+ if (lop->op_private & OPpPAD_STATE) {
+ if (left->op_private & OPpLVAL_INTRO) {
+ /* Each variable in state($a, $b, $c) = ... */
+ }
+ else {
+ /* Each state variable in
+ (state $a, my $b, our $c, $d, undef) = ... */
+ }
+ yyerror(no_list_state);
+ } else {
+ /* Each my variable in
+ (state $a, my $b, our $c, $d, undef) = ... */
+ }
+ } else {
+ /* Other ops in the list. undef may be interesting in
+ (state $a, undef, state $c) */
+ }
+ lop = lop->op_sibling;
+ }
+ }
+ else if (((left->op_private & (OPpLVAL_INTRO | OPpPAD_STATE))
+ == (OPpLVAL_INTRO | OPpPAD_STATE))
+ && ( left->op_type == OP_PADSV
+ || left->op_type == OP_PADAV
+ || left->op_type == OP_PADHV
+ || left->op_type == OP_PADANY))
+ {
+ /* All single variable list context state assignments, hence
+ state ($a) = ...
+ (state $a) = ...
+ state @a = ...
+ state (@a) = ...
+ (state @a) = ...
+ state %a = ...
+ state (%a) = ...
+ (state %a) = ...
+ */
+ yyerror(no_list_state);
+ }
+
if (right && right->op_type == OP_SPLIT && !PL_madskills) {
OP* tmpop = ((LISTOP*)right)->op_first;
if (tmpop && (tmpop->op_type == OP_PUSHRE)) {
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index cd741abf7e..9123a01267 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -1999,6 +1999,13 @@ either consume text or fail.
The <-- HERE shows in the regular expression about where the problem was
discovered.
+=item Initialization of state variables in list context currently forbidden
+
+(F) Currently the implementation of "state" only permits the initialization
+of scalar variables in scalar context. Re-write C<state ($a) = 42> as
+C<state $a = 42> to change from list to scalar context. Constructions such
+as C<state (@a) = foo()> will be supported in a future perl release.
+
=item Insecure dependency in %s
(F) You tried to do something that the tainting mechanism didn't like.
diff --git a/t/op/state.t b/t/op/state.t
index 7be16667d3..6d835c466d 100644
--- a/t/op/state.t
+++ b/t/op/state.t
@@ -10,7 +10,7 @@ BEGIN {
use strict;
use feature ":5.10";
-plan tests => 108;
+plan tests => 117;
ok( ! defined state $uninit, q(state vars are undef by default) );
@@ -301,17 +301,6 @@ foreach my $x (0 .. 4) {
#
-# List context reassigns, but scalar doesn't.
-#
-my @swords = qw [Stormbringer Szczerbiec Grimtooth Corrougue];
-foreach my $sword (@swords) {
- state ($s1) = state $s2 = $sword;
- is $s1, $swords [0], 'mixed context';
- is $s2, $swords [0], 'mixed context';
-}
-
-
-#
# Use with given.
#
my @spam = qw [spam ham bacon beans];
@@ -331,3 +320,28 @@ foreach my $spam (@spam) {
state $x = "two";
is $x, "two", "masked"
}
+
+foreach my $forbidden (<DATA>) {
+ chomp $forbidden;
+ no strict 'vars';
+ eval $forbidden;
+ like $@, qr/Initialization of state variables in list context currently forbidden/, "Currently forbidden: $forbidden";
+}
+__DATA__
+state ($a) = 1;
+(state $a) = 1;
+state @a = 1;
+state (@a) = 1;
+(state @a) = 1;
+state %a = ();
+state (%a) = ();
+(state %a) = ();
+state ($a, $b) = ();
+state ($a, @b) = ();
+(state $a, state $b) = ();
+(state $a, $b) = ();
+(state $a, my $b) = ();
+(state $a, state @b) = ();
+(state $a, local @b) = ();
+(state $a, undef, state $b) = ();
+state ($a, undef, $b) = ();