diff --git a/src/builtins/guts.pir b/src/builtins/guts.pir index 0f253a24596..16f8d2d8008 100644 --- a/src/builtins/guts.pir +++ b/src/builtins/guts.pir @@ -1143,14 +1143,11 @@ Reblesses a sub into a new type. =item !state_var_init -Takes a list of state variables to initialize. Returns wether we need to run -the initial setting of values for them. +Loads any existing values of state variables for a block. =cut .sub '!state_var_init' - .param pmc names :slurpy - .local pmc lexpad, state_store, names_it $P0 = new 'ParrotInterpreter' lexpad = $P0['lexpad'; 1] @@ -1161,19 +1158,33 @@ the initial setting of values for them. setprop $P0, '$!state_store', state_store have_state_store: - names_it = iter names + names_it = iter state_store names_loop: unless names_it goto names_loop_end $S0 = shift names_it $P0 = state_store[$S0] - if null $P0 goto need_init lexpad[$S0] = $P0 goto names_loop names_loop_end: - .return (0) +.end - need_init: - .return (1) + +=item !state_var_inited + +Takes the name of a state variable and returns true if it's been +initialized already. + +=cut + +.sub '!state_var_inited' + .param string name + $P0 = new 'ParrotInterpreter' + $P0 = $P0['sub'; 1] + $P0 = getprop '$!state_store', $P0 + $P0 = $P0[name] + $I0 = isnull $P0 + $I0 = not $I0 + .return ($I0) .end =back diff --git a/src/parser/actions.pm b/src/parser/actions.pm index fe78a30eeb1..975b71eb660 100644 --- a/src/parser/actions.pm +++ b/src/parser/actions.pm @@ -1877,6 +1877,13 @@ method scope_declarator($/) { else { $past.name('infix:,'); $past.pasttype('call'); } if $scope eq 'state' { $past := $scope; + unless $block { + $block[0].push(PAST::Op.new( + :pasttype('call'), + :name('!state_var_init') + )); + $block := 1; + } } } make $past; @@ -2477,16 +2484,14 @@ method EXPR($/, $key) { } elsif $lhs eq 'state' { # State variables - only want to actually do an assignment if - # there is no value. This calls !state_var_init, which does the - # initialization of state vars to their previous values and then - # returns a false value. In the event that there are not any - # existing values, however, it does the assignment. + # there is no value. $past := PAST::Op.new( - :pasttype('if'), + :pasttype('unless'), :node($/), PAST::Op.new( :pasttype('call'), - :name('!state_var_init'), + :name('!state_var_inited'), + $lhs.isa(PAST::Var) ?? $lhs.name() !! $lhs[0].name() ), PAST::Op.new( :pasttype('call'), @@ -2496,12 +2501,6 @@ method EXPR($/, $key) { $rhs ) ); - if $lhs.isa(PAST::Op) { - for @($lhs) { $past[0].push($_.name()); } - } - else { - $past[0].push($lhs.name()); - } } else { # Just a normal assignment. diff --git a/src/pctextensions/state.pir b/src/pctextensions/state.pir index 146281af5f2..3624ca3ffc0 100644 --- a/src/pctextensions/state.pir +++ b/src/pctextensions/state.pir @@ -44,11 +44,11 @@ XXX TODO: Doesn't yet handle binding beyond the initial one. # Do a call to restore any previous values. We can skip the rest # if it returns a false value. $P0 = self.'uniquereg'('I') - ops.'push_pirop'('call', '"!state_var_init"', name, 'result'=>$P0) + ops.'push_pirop'('call', '"!state_var_inited"', name, 'result'=>$P0) $P1 = get_hll_global ['POST'], 'Label' $S0 = self.'unique'('state') $P1 = $P1.'new'('result'=>$S0) - ops.'push_pirop'('unless', $P0, $P1) + ops.'push_pirop'('if', $P0, $P1) # Vivify and store vivification. .local pmc viviself, vivipost