[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]
Re: [ID 20000119.002] 'next' undefines variables in 'continue' block
On Wed, 19 Jan 2000 09:48:19 MST, oracle@tauceti.pcr.com wrote:
>File test_next:
>$^W = 1;
>my $x = 3;
>while(my $i = $x--) {
> print "while block: \$i = $i\n";
> next if $i == 2;
>} continue {
> print "cont. block: \$i = $i\n";
>}
>Output:
>
>while block: $i = 3
>cont. block: $i = 3
>while block: $i = 2
>Use of uninitialized value at test_next line 5.
>cont. block: $i =
>while block: $i = 1
>cont. block: $i = 1
>
>Also, when 'next' is used to jump to a labelled outer loop with a
>continue block, the same thing happens for variables declared in
>the outer block's control expression.
>
>After digging around in the perl source code, it seems that a
>compiled while statement has an unstack op at the end. Without
>a continue block, a next op jumps directly to the beginning of
>the while block, skipping the unstack op, and so has to do the
>unstacking itself. With a continue block, the next op jumps right
>into the continue block, but still does the unstacking.
Thanks for that accurate diagnosis of the problem.
I noticed another longstanding bug: local-ized values inside a while block
are visible in the continue block!
These two changes fix both problems.
There is one remaining problem with local-ized values still being visible
in the continue block after a next, but that will have to wait for another
day.
Sarathy
gsar@ActiveState.com
-----------------------------------8<-----------------------------------
Change 4848 by gsar@auger on 2000/01/23 06:43:51
fix scope cleanup when next jumps to a continue block; this is rather
in the nature of a kludge; it doesn't fix the longstanding bug that
makes C<while (!$x++) { local $x = 7 } continue { print $x }> print "7"
instead of "1")
Affected files ...
... //depot/perl/pp_ctl.c#174 edit
... //depot/perl/t/cmd/while.t#8 edit
Differences ...
==== //depot/perl/pp_ctl.c#174 (text) ====
Index: perl/pp_ctl.c
--- perl/pp_ctl.c.~1~ Sat Jan 22 22:43:56 2000
+++ perl/pp_ctl.c Sat Jan 22 22:43:56 2000
@@ -1960,9 +1960,15 @@
dounwind(cxix);
TOPBLOCK(cx);
- oldsave = PL_scopestack[PL_scopestack_ix - 1];
- LEAVE_SCOPE(oldsave);
- return cx->blk_loop.next_op;
+ {
+ OP *nextop = cx->blk_loop.next_op;
+ /* clean scope, but only if there's no continue block */
+ if (nextop == cUNOPx(cx->blk_loop.last_op)->op_first->op_next) {
+ oldsave = PL_scopestack[PL_scopestack_ix - 1];
+ LEAVE_SCOPE(oldsave);
+ }
+ return nextop;
+ }
}
PP(pp_redo)
==== //depot/perl/t/cmd/while.t#8 (xtext) ====
Index: perl/t/cmd/while.t
--- perl/t/cmd/while.t.~1~ Sat Jan 22 22:43:56 2000
+++ perl/t/cmd/while.t Sat Jan 22 22:43:56 2000
@@ -2,7 +2,7 @@
# $RCSfile: while.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:15 $
-print "1..15\n";
+print "1..17\n";
open (tmp,'>Cmd_while.tmp') || die "Can't create Cmd_while.tmp.";
print tmp "tvi925\n";
@@ -128,3 +128,16 @@
$i++;
print "not " unless $` . $& . $' eq "abc";
print "ok $i\n";
+
+# check that scope cleanup happens right when there's a continue block
+{
+ my $var = 16;
+ while (my $i = ++$var) {
+ next if $i == 17;
+ last if $i > 17;
+ my $i = 0;
+ }
+ continue {
+ print "ok ", $var-1, "\nok $i\n";
+ }
+}
End of Patch.
Change 4849 by gsar@auger on 2000/01/23 08:17:30
fix localization in while BLOCK when there is a continue BLOCK
by introducing an explicit scope (c.f. change#4848)
Affected files ...
... //depot/perl/op.c#242 edit
... //depot/perl/pp_ctl.c#175 edit
... //depot/perl/t/cmd/while.t#9 edit
Differences ...
==== //depot/perl/op.c#242 (text) ====
Index: perl/op.c
--- perl/op.c.~1~ Sun Jan 23 00:17:34 2000
+++ perl/op.c Sun Jan 23 00:17:34 2000
@@ -3753,6 +3753,9 @@
if (!block)
block = newOP(OP_NULL, 0);
+ else if (cont) {
+ block = scope(block);
+ }
if (cont)
next = LINKLIST(cont);
==== //depot/perl/pp_ctl.c#175 (text) ====
Index: perl/pp_ctl.c
--- perl/pp_ctl.c.~1~ Sun Jan 23 00:17:34 2000
+++ perl/pp_ctl.c Sun Jan 23 00:17:34 2000
@@ -1959,11 +1959,12 @@
if (cxix < cxstack_ix)
dounwind(cxix);
- TOPBLOCK(cx);
+ cx = &cxstack[cxstack_ix];
{
OP *nextop = cx->blk_loop.next_op;
/* clean scope, but only if there's no continue block */
if (nextop == cUNOPx(cx->blk_loop.last_op)->op_first->op_next) {
+ TOPBLOCK(cx);
oldsave = PL_scopestack[PL_scopestack_ix - 1];
LEAVE_SCOPE(oldsave);
}
==== //depot/perl/t/cmd/while.t#9 (xtext) ====
Index: perl/t/cmd/while.t
--- perl/t/cmd/while.t.~1~ Sun Jan 23 00:17:34 2000
+++ perl/t/cmd/while.t Sun Jan 23 00:17:34 2000
@@ -1,8 +1,6 @@
#!./perl
-# $RCSfile: while.t,v $$Revision: 4.1 $$Date: 92/08/07 18:27:15 $
-
-print "1..17\n";
+print "1..19\n";
open (tmp,'>Cmd_while.tmp') || die "Can't create Cmd_while.tmp.";
print tmp "tvi925\n";
@@ -141,3 +139,24 @@
print "ok ", $var-1, "\nok $i\n";
}
}
+
+{
+ local $l = 18;
+ {
+ local $l = 0
+ }
+ continue {
+ print "ok $l\n"
+ }
+}
+
+{
+ local $l = 19;
+ my $x = 0;
+ while (!$x++) {
+ local $l = 0
+ }
+ continue {
+ print "ok $l\n"
+ }
+}
End of Patch.
- Follow-Ups from:
-
Tim Bunce <Tim.Bunce@ig.co.uk>
Larry Wall <larry@wall.org>
- References to:
-
oracle@tauceti.pcr.com
[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]