Skip to content

Commit eae48c8

Browse files
ZeframFather Chrysostomos
Zefram
authored and
Father Chrysostomos
committed
refactor and regularise label/statement grammar
Refactoring of the grammar around statements. New production <barestmt> encompasses a statement without label. It includes all statement types, including declarations, with no unnecessary intermediate non-terminals. It generates an op tree for the statement's content, with no leading state op. The <fullstmt> production has just one rule, consisting of optional label followed by <barestmt>. It puts a state op on the front of the statement's content ops. To support the regular statement op structure, the op sequence for for(;;) loops no longer has a second state op between the initialisation and the loop. Instead, the unstack op type is slightly adapted to achieve the stack clearing without a state op. The newFOROP() constructor function no longer generates a state op, that now being the job of the <fullstmt> production. Consequently it no longer takes a parameter stating what label is to go in the state op. This brings it in line with the other op constructors.
1 parent ff0c75a commit eae48c8

File tree

13 files changed

+1543
-1701
lines changed

13 files changed

+1543
-1701
lines changed

dist/B-Deparse/Deparse.pm

+14-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use B qw(class main_root main_start main_cv svref_2object opnumber perlstring
2323
PMf_MULTILINE PMf_SINGLELINE PMf_FOLD PMf_EXTENDED),
2424
($] < 5.009 ? 'PMf_SKIPWHITE' : 'RXf_SKIPWHITE'),
2525
($] < 5.011 ? 'CVf_LOCKED' : ());
26-
$VERSION = 0.99;
26+
$VERSION = 1.00;
2727
use strict;
2828
use vars qw/$AUTOLOAD/;
2929
use warnings ();
@@ -958,14 +958,19 @@ sub is_for_loop {
958958
my $op = shift;
959959
# This OP might be almost anything, though it won't be a
960960
# nextstate. (It's the initialization, so in the canonical case it
961-
# will be an sassign.) The sibling is a lineseq whose first child
962-
# is a nextstate and whose second is a leaveloop.
961+
# will be an sassign.) The sibling is (old style) a lineseq whose
962+
# first child is a nextstate and whose second is a leaveloop, or
963+
# (new style) an unstack whose sibling is a leaveloop.
963964
my $lseq = $op->sibling;
964-
if (!is_state $op and !null($lseq) and $lseq->name eq "lineseq") {
965+
return 0 unless !is_state($op) and !null($lseq);
966+
if ($lseq->name eq "lineseq") {
965967
if ($lseq->first && !null($lseq->first) && is_state($lseq->first)
966968
&& (my $sib = $lseq->first->sibling)) {
967969
return (!null($sib) && $sib->name eq "leaveloop");
968970
}
971+
} elsif ($lseq->name eq "unstack" && ($lseq->flags & OPf_SPECIAL)) {
972+
my $sib = $lseq->sibling;
973+
return $sib && !null($sib) && $sib->name eq "leaveloop";
969974
}
970975
return 0;
971976
}
@@ -1215,7 +1220,8 @@ sub walk_lineseq {
12151220
}
12161221
}
12171222
if (is_for_loop($kids[$i])) {
1218-
$callback->($expr . $self->for_loop($kids[$i], 0), $i++);
1223+
$callback->($expr . $self->for_loop($kids[$i], 0),
1224+
$i += $kids[$i]->sibling->name eq "unstack" ? 2 : 1);
12191225
next;
12201226
}
12211227
$expr .= $self->deparse($kids[$i], (@kids != 1)/2);
@@ -2757,7 +2763,9 @@ sub for_loop {
27572763
my $self = shift;
27582764
my($op, $cx) = @_;
27592765
my $init = $self->deparse($op, 1);
2760-
return $self->loop_common($op->sibling->first->sibling, $cx, $init);
2766+
my $s = $op->sibling;
2767+
my $ll = $s->name eq "unstack" ? $s->sibling : $s->first->sibling;
2768+
return $self->loop_common($ll, $cx, $init);
27612769
}
27622770

27632771
sub pp_leavetry {

embed.fnc

+1-1
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ Ap |OP* |newFORM |I32 floor|NULLOK OP* o|NULLOK OP* block
780780
#else
781781
Ap |void |newFORM |I32 floor|NULLOK OP* o|NULLOK OP* block
782782
#endif
783-
Apda |OP* |newFOROP |I32 flags|NULLOK char* label|line_t forline \
783+
Apda |OP* |newFOROP |I32 flags|line_t forline \
784784
|NULLOK OP* sv|NN OP* expr|NULLOK OP* block|NULLOK OP* cont
785785
Apda |OP* |newGIVENOP |NN OP* cond|NN OP* block|PADOFFSET defsv_off
786786
Apda |OP* |newLOGOP |I32 optype|I32 flags|NN OP *first|NN OP *other

embed.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@
311311
#define newCONDOP(a,b,c,d) Perl_newCONDOP(aTHX_ a,b,c,d)
312312
#define newCONSTSUB(a,b,c) Perl_newCONSTSUB(aTHX_ a,b,c)
313313
#define newCVREF(a,b) Perl_newCVREF(aTHX_ a,b)
314-
#define newFOROP(a,b,c,d,e,f,g) Perl_newFOROP(aTHX_ a,b,c,d,e,f,g)
314+
#define newFOROP(a,b,c,d,e,f) Perl_newFOROP(aTHX_ a,b,c,d,e,f)
315315
#define newGIVENOP(a,b,c) Perl_newGIVENOP(aTHX_ a,b,c)
316316
#define newGVOP(a,b,c) Perl_newGVOP(aTHX_ a,b,c)
317317
#define newGVREF(a,b) Perl_newGVREF(aTHX_ a,b)

ext/B/t/f_map.t

+2-2
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ checkOptree(note => q{},
185185
# p <2> sassign vKS/2
186186
# q <0> unstack s
187187
# goto r
188-
# t <2> leaveloop K/2
188+
# t <2> leaveloop KP/2
189189
# u <2> leaveloop K/2
190190
# v <1> leavesub[1 ref] K/REFC,1
191191
EOT_EOT
@@ -218,7 +218,7 @@ EOT_EOT
218218
# p <2> sassign vKS/2
219219
# q <0> unstack s
220220
# goto r
221-
# t <2> leaveloop K/2
221+
# t <2> leaveloop KP/2
222222
# u <2> leaveloop K/2
223223
# v <1> leavesub[1 ref] K/REFC,1
224224
EONT_EONT

ext/B/t/optree_samples.t

+4-6
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,6 @@ checkOptree ( name => '-basic sub { print "foo $_" foreach (1..10) }',
281281
# g <1> leavesub[1 ref] K/REFC,1 ->(end)
282282
# - <@> lineseq KP ->g
283283
# 1 <;> nextstate(main 445 optree.t:167) v:>,<,% ->2
284-
# - <0> null v ->-
285284
# f <2> leaveloop K/2 ->g
286285
# 6 <{> enteriter(next->c last->f redo->7) lKS/8 ->d
287286
# - <0> ex-pushmark s ->2
@@ -307,7 +306,6 @@ EOT_EOT
307306
# g <1> leavesub[1 ref] K/REFC,1 ->(end)
308307
# - <@> lineseq KP ->g
309308
# 1 <;> nextstate(main 446 optree_samples.t:192) v:>,<,% ->2
310-
# - <0> null v ->-
311309
# f <2> leaveloop K/2 ->g
312310
# 6 <{> enteriter(next->c last->f redo->7) lKS/8 ->d
313311
# - <0> ex-pushmark s ->2
@@ -337,7 +335,7 @@ checkOptree ( name => '-exec -e foreach (1..10) {print qq{foo $_}}',
337335
strip_open_hints => 1,
338336
expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
339337
# 1 <0> enter
340-
# 2 <;> nextstate(main 2 -e:1) v:>,<,%
338+
# 2 <;> nextstate(main 2 -e:1) v:>,<,%,{
341339
# 3 <0> pushmark s
342340
# 4 <$> const[IV 1] s
343341
# 5 <$> const[IV 10] s
@@ -357,7 +355,7 @@ checkOptree ( name => '-exec -e foreach (1..10) {print qq{foo $_}}',
357355
# i <@> leave[1 ref] vKP/REFC
358356
EOT_EOT
359357
# 1 <0> enter
360-
# 2 <;> nextstate(main 2 -e:1) v:>,<,%
358+
# 2 <;> nextstate(main 2 -e:1) v:>,<,%,{
361359
# 3 <0> pushmark s
362360
# 4 <$> const(IV 1) s
363361
# 5 <$> const(IV 10) s
@@ -545,7 +543,7 @@ checkOptree ( name => '%h=(); for $_(@a){$h{getkey($_)} = $_}',
545543
# n <2> sassign vKS/2
546544
# o <0> unstack s
547545
# goto p
548-
# r <2> leaveloop K/2
546+
# r <2> leaveloop KP/2
549547
# s <1> leavesub[1 ref] K/REFC,1
550548
EOT_EOT
551549
# 1 <;> nextstate(main 505 (eval 24):1) v
@@ -575,7 +573,7 @@ EOT_EOT
575573
# n <2> sassign vKS/2
576574
# o <0> unstack s
577575
# goto p
578-
# r <2> leaveloop K/2
576+
# r <2> leaveloop KP/2
579577
# s <1> leavesub[1 ref] K/REFC,1
580578
EONT_EONT
581579

op.c

+4-8
Original file line numberDiff line numberDiff line change
@@ -5429,7 +5429,7 @@ whileline, OP *expr, OP *block, OP *cont, I32 has_my)
54295429
}
54305430

54315431
/*
5432-
=for apidoc Am|OP *|newFOROP|I32 flags|char *label|line_t forline|OP *sv|OP *expr|OP *block|OP *cont
5432+
=for apidoc Am|OP *|newFOROP|I32 flags|line_t forline|OP *sv|OP *expr|OP *block|OP *cont
54335433
54345434
Constructs, checks, and returns an op tree expressing a C<foreach>
54355435
loop (iteration through a list of values). This is a heavyweight loop,
@@ -5447,16 +5447,13 @@ I<flags> gives the eight bits of C<op_flags> for the C<leaveloop>
54475447
op and, shifted up eight bits, the eight bits of C<op_private> for
54485448
the C<leaveloop> op, except that (in both cases) some bits will be set
54495449
automatically. I<forline> is the line number that should be attributed
5450-
to the loop's list expression. If I<label> is non-null, it supplies
5451-
the name of a label to attach to the state op at the start of the loop;
5452-
this function takes ownership of the memory pointed at by I<label>,
5453-
and will free it.
5450+
to the loop's list expression.
54545451
54555452
=cut
54565453
*/
54575454

54585455
OP *
5459-
Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP *block, OP *cont)
5456+
Perl_newFOROP(pTHX_ I32 flags, line_t forline, OP *sv, OP *expr, OP *block, OP *cont)
54605457
{
54615458
dVAR;
54625459
LOOP *loop;
@@ -5577,8 +5574,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP
55775574
wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont, 0);
55785575
if (madsv)
55795576
op_getmad(madsv, (OP*)loop, 'v');
5580-
PL_parser->copline = forline;
5581-
return newSTATEOP(0, label, wop);
5577+
return wop;
55825578
}
55835579

55845580
/*

0 commit comments

Comments
 (0)