summaryrefslogtreecommitdiff
path: root/perly.y
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2022-04-16 11:48:20 +0100
committerDavid Mitchell <davem@iabyn.com>2022-04-16 18:22:13 +0100
commitf8245cd9653db9b3e3fef57c3913d9deb33972b2 (patch)
tree754659507371a9a12f8f2a20cbf2a8b814e281a2 /perly.y
parent55d95e1b172db3fff30c261b7b7ea9e0bca8328a (diff)
downloadperl-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.y4
1 files changed, 4 insertions, 0 deletions
diff --git a/perly.y b/perly.y
index 60eca783e1..55321fa41e 100644
--- a/perly.y
+++ b/perly.y
@@ -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;
}