Skip to content

Commit 87bb1c3

Browse files
committed
In a token foo { <bar>+ }, the captures would not be stored. This was due to a bad interaction between :r and the cstack; the bstack contains the current cstack index we're at, but we don't grow the bstack when :r is on. We thus lost the count of captures, popping the entire cstack. This adds an extra bstack frame when :r is on to keep such counts, fixing the issue.
1 parent 7fc7a08 commit 87bb1c3

File tree

2 files changed

+20
-0
lines changed

2 files changed

+20
-0
lines changed

src/QAST/Compiler.nqp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ class QAST::Compiler is HLL::Compiler {
289289
my $prefix := self.unique('rxquant' ~ $backtrack);
290290
my $looplabel := self.post_new('Label', :result($prefix ~ '_loop'));
291291
my $donelabel := self.post_new('Label', :result($prefix ~ '_done'));
292+
my $rcslabel := self.post_new('Label', :result($prefix ~ '_ratchet_cstack'));
292293
my $min := $node.min || 0;
293294
my $max := $node.max // -1;
294295
my $needrep := $min > 1 || $max > 1;
@@ -318,6 +319,8 @@ class QAST::Compiler is HLL::Compiler {
318319
$ops.push($donelabel);
319320
}
320321
else {
322+
self.regex_mark($ops, $rcslabel, -1, 0) # to track cstack as we ratchet
323+
if $backtrack eq 'r' && $max != 1;
321324
if $min == 0 { self.regex_mark($ops, $donelabel, %*REG<pos>, 0); }
322325
elsif $needmark { self.regex_mark($ops, $donelabel, -1, 0); }
323326
$ops.push($looplabel);
@@ -331,10 +334,16 @@ class QAST::Compiler is HLL::Compiler {
331334
}
332335
unless $max == 1 {
333336
self.regex_mark($ops, $donelabel, %*REG<pos>, %*REG<rep>);
337+
$ops.push_pirop('nqp_rxsetcaps', %*REG<bstack>, %*REG<cstack>)
338+
if $backtrack eq 'r';
334339
$ops.push(self.regex_post($sep)) if $sep;
335340
$ops.push_pirop('goto', $looplabel);
336341
}
337342
$ops.push($donelabel);
343+
if $backtrack eq 'r' && $max != 1 {
344+
self.regex_commit($ops, $rcslabel); # pop cstack/ratchet tracking mark
345+
$ops.push($rcslabel);
346+
}
338347
$ops.push_pirop('lt', %*REG<rep>, +$node.min, %*REG<fail>)
339348
if $min > 1;
340349
}

src/ops/nqp.ops

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,6 +1678,11 @@ Push a new backtracking mark onto $1 with label $2, position $3, and count $4
16781678

16791679
Set $1 to be the index of latest mark frame $3 in stack $2.
16801680

1681+
=item nqp_rxsetcaps(ptr, cstack)
1682+
1683+
Sets the top cstack count in $1 to be the elements in $2, or 0 if it's null.
1684+
Used to not lose count when doing ratcheting and replacing marks.
1685+
16811686
=cut
16821687

16831688
*/
@@ -1705,6 +1710,12 @@ inline op nqp_rxpeek(out INT, in PMC, in LABEL) :base_core {
17051710
$1 = ptr;
17061711
}
17071712

1713+
inline op nqp_rxsetcaps(in PMC, in PMC) :base_core {
1714+
PMC *bstack = $1;
1715+
VTABLE_set_integer_keyed_int(interp, bstack,
1716+
VTABLE_elements(interp, bstack) - 5,
1717+
PMC_IS_NULL($2) ? 0 : VTABLE_elements(interp, $2));
1718+
}
17081719

17091720
/*
17101721

0 commit comments

Comments
 (0)