From: Nicholas Clark Date: Sat, 8 Sep 2007 22:34:29 +0000 (+0000) Subject: For now, forbid all list assignment initialisation of state variables, X-Git-Tag: v5.10.0~644 X-Git-Url: https://perl5.git.perl.org/perl5.git/commitdiff_plain/6dbe9451abb7e30d650de45d484c69e6c34bbd36 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 --- diff --git a/op.c b/op.c index 6975d83..ca488a2 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 cd741ab..9123a01 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 as +C to change from list to scalar context. Constructions such +as C 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 7be1666..6d835c4 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 () { + 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) = ();