From: Rafael Garcia-Suarez Date: Tue, 27 Mar 2007 09:42:44 +0000 (+0000) Subject: Fix return value of state assignment ($x=state $y=$z). X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=84f64f45c90987f3228c0b57886fceba4991c2aa;p=p5sagit%2Fp5-mst-13.2.git Fix return value of state assignment ($x=state $y=$z). Fix a form of state assignment (state($x)=$y). Minor optimisation in pp_aassign for state variables. New tests. p4raw-id: //depot/perl@30772 --- diff --git a/op.c b/op.c index 23b4b81..f05be0b 100644 --- a/op.c +++ b/op.c @@ -3925,6 +3925,17 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) 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)) + { + o->op_private |= OPpASSIGN_STATE; + /* hijacking PADSTALE for uninitialized state variables */ + SvPADSTALE_on(PAD_SVl(left->op_targ)); + } if (right && right->op_type == OP_SPLIT) { OP* tmpop = ((LISTOP*)right)->op_first; diff --git a/pp_hot.c b/pp_hot.c index f01a3e0..83ed613 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -130,8 +130,11 @@ PP(pp_sassign) else if (PL_op->op_private & OPpASSIGN_STATE) { if (SvPADSTALE(right)) SvPADSTALE_off(right); - else + else { + (void)POPs; + PUSHs(right); RETURN; /* ignore assignment */ + } } if (PL_tainting && PL_tainted && !SvTAINTED(left)) TAINT_NOT; @@ -969,6 +972,12 @@ PP(pp_aassign) int duplicates = 0; SV **firsthashrelem = NULL; /* "= 0" keeps gcc 2.95 quiet */ + if (PL_op->op_private & OPpASSIGN_STATE) { + if (SvPADSTALE(*firstlelem)) + SvPADSTALE_off(*firstlelem); + else + RETURN; /* ignore assignment */ + } PL_delaymagic = DM_DELAY; /* catch simultaneous items */ gimme = GIMME_V; @@ -986,12 +995,6 @@ PP(pp_aassign) } } } - if (PL_op->op_private & OPpASSIGN_STATE) { - if (SvPADSTALE(*firstlelem)) - SvPADSTALE_off(*firstlelem); - else - RETURN; /* ignore assignment */ - } relem = firstrelem; lelem = firstlelem; diff --git a/t/op/state.t b/t/op/state.t index 9f618b0..57b46ab 100644 --- a/t/op/state.t +++ b/t/op/state.t @@ -10,7 +10,7 @@ BEGIN { use strict; use feature "state"; -plan tests => 37; +plan tests => 46; ok( ! defined state $uninit, q(state vars are undef by default) ); @@ -20,23 +20,27 @@ sub stateful { state $x; state $y = 1; my $z = 2; - return ($x++, $y++, $z++); + state ($t) = 3; + return ($x++, $y++, $z++, $t++); } -my ($x, $y, $z) = stateful(); +my ($x, $y, $z, $t) = stateful(); is( $x, 0, 'uninitialized state var' ); is( $y, 1, 'initialized state var' ); is( $z, 2, 'lexical' ); +is( $t, 3, 'initialized state var, list syntax' ); -($x, $y, $z) = stateful(); +($x, $y, $z, $t) = stateful(); is( $x, 1, 'incremented state var' ); is( $y, 2, 'incremented state var' ); is( $z, 2, 'reinitialized lexical' ); +is( $t, 4, 'incremented state var, list syntax' ); -($x, $y, $z) = stateful(); +($x, $y, $z, $t) = stateful(); is( $x, 2, 'incremented state var' ); is( $y, 3, 'incremented state var' ); is( $z, 2, 'reinitialized lexical' ); +is( $t, 5, 'incremented state var, list syntax' ); # in a nested block @@ -126,6 +130,18 @@ is( $xsize, 0, 'uninitialized state array' ); $xsize = stateful_array(); is( $xsize, 1, 'uninitialized state array after one iteration' ); +sub stateful_array_init { + state @x = (1, 2); + push @x, 'x'; + return $#x; +} + +$xsize = stateful_array_init(); +is( $xsize, 2, 'initialized state array' ); + +$xsize = stateful_array_init(); +is( $xsize, 3, 'initialized state array after one iteration' ); + # hash state vars sub stateful_hash { @@ -139,6 +155,17 @@ is( $xhval, 0, 'uninitialized state hash' ); $xhval = stateful_hash(); is( $xhval, 1, 'uninitialized state hash after one iteration' ); +sub stateful_hash_init { + state %hx = (foo => 10); + return $hx{foo}++; +} + +$xhval = stateful_hash_init(); +is( $xhval, 10, 'initialized state hash' ); + +$xhval = stateful_hash_init(); +is( $xhval, 11, 'initialized state hash after one iteration' ); + # state declaration with a list sub statelist { @@ -175,3 +202,10 @@ sub noseworth { noseworth($level - 1) if $level; } noseworth(2); + +# Assignment return value + +sub pugnax { my $x = state $y = 42; $y++; $x; } + +is( pugnax(), 42, 'scalar state assignment return value' ); +is( pugnax(), 43, 'scalar state assignment return value' );