diff options
author | David Mitchell <davem@iabyn.com> | 2022-04-16 11:48:20 +0100 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2022-04-16 18:22:13 +0100 |
commit | f8245cd9653db9b3e3fef57c3913d9deb33972b2 (patch) | |
tree | 754659507371a9a12f8f2a20cbf2a8b814e281a2 /perly.y | |
parent | 55d95e1b172db3fff30c261b7b7ea9e0bca8328a (diff) | |
download | perl-f8245cd9653db9b3e3fef57c3913d9deb33972b2.tar.gz |
for my ($x) ...: fix handling of degenerate 1-var
The new
for my ($x,$y,...) (...) { ... }
syntax has a couple of problems in the degenerate case of a single
variable:
for my ($x) (...) { ... }
First, the loop variable is marked as lexical, but not as a variable
to be introduced. So it behaves roughly as if written like:
{ my $x; for $x (...) { ... } }
I can't think of any user-visible runtime change in behaviour this bug
causes, so I haven't included a test for it.
Second, it was being incorrectly deparsed as
for $x (...) { ... }
(i.e. without the 'my').
This commit fixes both of these issues.
The basic problem is that the parser, in the case of multiple vars,
passes a list subtree of PADSVs as the 'sv' argument of Perl_newFOROP,
but in the case of a single var, passes a single PADSV op instead.
This single PADSV doesn't have the LVINTRO flag set, so is
indistinguishable from plain
my $x; for $x ....
This commit makes the parser set the OPf_PARENS flag on the lone PADSV
to signal to newFOROP() that it's a degenerate 1-var list, and
newFOROP() sets the OPf_PARENS flag on the ENTERITER op to signal to the
deparser that this is "for my (...)" syntax, even if it only has a
single var.
Diffstat (limited to 'perly.y')
-rw-r--r-- | perly.y | 4 |
1 files changed, 4 insertions, 0 deletions
@@ -433,6 +433,10 @@ barestmt: PLUGSTMT } | FOR MY remember PERLY_PAREN_OPEN my_list_of_scalars PERLY_PAREN_CLOSE PERLY_PAREN_OPEN mexpr PERLY_PAREN_CLOSE mblock cont { + if ($my_list_of_scalars->op_type == OP_PADSV) + /* degenerate case of 1 var: for my ($x) .... + Flag it so it can be special-cased in newFOROP */ + $my_list_of_scalars->op_flags |= OPf_PARENS; $$ = block_end($remember, newFOROP(0, $my_list_of_scalars, $mexpr, $mblock, $cont)); parser->copline = (line_t)$FOR; } |