diff options
Diffstat (limited to 'awkgram.y')
-rw-r--r-- | awkgram.y | 25 |
1 files changed, 22 insertions, 3 deletions
@@ -1644,17 +1644,26 @@ let_var_list } | NAME ASSIGN exp { - add_let(in_function, $1); + bool is_reused_location = add_let(in_function, $1); $1->opcode = Op_push; $1->memory = variable($1->source_line, $1->lextok, Node_var_new); $$ = list_append(mk_assignment(list_create($1), $3, $2), instruction(Op_pop)); - + /* Even for initialized variables, we must emit the Op_clear_var + instruction. This is because the variable may previously have + been an array and is now being assigned as a scalar value. + the Op_clear_var will reset the type to allow that. */ + if (in_loop || is_reused_location) { + INSTRUCTION *clr = instruction(Op_clear_var); + UPREF($1->memory); + clr->memory = $1->memory; + $$ = list_prepend($$, clr); + } } | let_var_list comma NAME ASSIGN exp { INSTRUCTION *assn; - add_let(in_function, $3); + bool is_reused_location = add_let(in_function, $3); $3->opcode = Op_push; $3->memory = variable($3->source_line, $3->lextok, Node_var_new); assn = list_append(mk_assignment(list_create($3), $5, $4), @@ -1663,6 +1672,16 @@ let_var_list $$ = assn; else $$ = list_merge($1, assn); + /* Even for initialized variables, we must emit the Op_clear_var + instruction. This is because the variable may previously have + been an array and is now being assigned as a scalar value. + the Op_clear_var will reset the type to allow that. */ + if (in_loop || is_reused_location) { + INSTRUCTION *clr = instruction(Op_clear_var); + UPREF($3->memory); + clr->memory = $3->memory; + $$ = list_prepend($$, clr); + } } | error { $$ = NULL; } |