Skip to content

Commit 1fd8cde

Browse files
committed
optimize after of known length to before w/ offset
This saves allocating and flipping a million or so bytes in rakudo compilation just for the occasional <?after '>'> and such. In fact, all of the afters in nqp and rakudo are of known length, though one of them is just <?after .>. We handle both dot and character classes, as well as any embedded anchors.
1 parent bbb164e commit 1fd8cde

File tree

3 files changed

+52
-7
lines changed

3 files changed

+52
-7
lines changed

src/NQP/Actions.nqp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,9 +1888,20 @@ class NQP::RegexActions is QRegex::P6Regex::Actions {
18881888
for $<arglist>.ast.list { $qast[0].push( $_ ) }
18891889
}
18901890
elsif $<nibbler> {
1891-
$name eq 'after' ??
1892-
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>.ast), :anon(1), :addself(1))) !!
1891+
if $name eq 'after' {
1892+
my int $litlen := self.offset_ast($<nibbler>.ast);
1893+
if $litlen >= 0 {
1894+
$qast[0][0].value('before');
1895+
$qast[0].push(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
1896+
$qast[0].push(QAST::IVal.new( :value($litlen) )); # optional offset to before
1897+
}
1898+
else {
1899+
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>.ast), :anon(1), :addself(1)));
1900+
}
1901+
}
1902+
else {
18931903
$qast[0].push(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
1904+
}
18941905
}
18951906
}
18961907
make $qast;

src/QRegex/Cursor.nqp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,13 +512,13 @@ role NQPCursorRole is export {
512512
$cur;
513513
}
514514

515-
method before($regex) {
515+
method before($regex, $off = 0) {
516516
my int $orig_highwater := nqp::getattr_i($!shared, ParseShared, '$!highwater');
517517
my $orig_highexpect := nqp::getattr($!shared, ParseShared, '@!highexpect');
518518
nqp::bindattr($!shared, ParseShared, '@!highexpect', nqp::list_s());
519519
my $cur := self."!cursor_start_cur"();
520-
nqp::bindattr_i($cur, $?CLASS, '$!pos', $!pos);
521-
nqp::getattr_i($regex($cur), $?CLASS, '$!pos') >= 0 ??
520+
nqp::bindattr_i($cur, $?CLASS, '$!pos', $!pos - $off);
521+
$!pos >= $off && nqp::getattr_i($regex($cur), $?CLASS, '$!pos') >= 0 ??
522522
$cur."!cursor_pass"($!pos, 'before') !!
523523
nqp::bindattr_i($cur, $?CLASS, '$!pos', -3);
524524
nqp::bindattr_i($!shared, ParseShared, '$!highwater', $orig_highwater);

src/QRegex/P6Regex/Actions.nqp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,9 +566,20 @@ class QRegex::P6Regex::Actions is HLL::Actions {
566566
for $<arglist>.ast.list { $qast[0].push( $_ ) }
567567
}
568568
elsif $<nibbler> {
569-
$name eq 'after' ??
570-
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>.ast), :anon(1), :addself(1))) !!
569+
if $name eq 'after' {
570+
my int $litlen := self.offset_ast($<nibbler>.ast);
571+
if $litlen >= 0 {
572+
$qast[0][0].value('before');
573+
$qast[0].push(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
574+
$qast[0].push(QAST::IVal.new( :value($litlen) )); # optional offset to before
575+
}
576+
else {
577+
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>.ast), :anon(1), :addself(1)));
578+
}
579+
}
580+
else {
571581
$qast[0].push(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
582+
}
572583
}
573584
}
574585
make $qast;
@@ -855,6 +866,29 @@ class QRegex::P6Regex::Actions is HLL::Actions {
855866
$ast.subtype('capture');
856867
}
857868

869+
method offset_ast($qast) {
870+
return -1 unless nqp::istype($qast, QAST::Regex);
871+
if $qast.rxtype eq 'literal' {
872+
return nqp::chars($qast[0]);
873+
}
874+
elsif $qast.rxtype eq 'cclass' {
875+
return 1;
876+
}
877+
elsif $qast.rxtype eq 'anchor' {
878+
return 0;
879+
}
880+
elsif $qast.rxtype eq 'concat' {
881+
my int $litlen;
882+
for @($qast) {
883+
my int $ll := self.offset_ast($_);
884+
return -1 if $ll < 0;
885+
$litlen := $litlen + $ll;
886+
}
887+
return $litlen;
888+
}
889+
return -1;
890+
}
891+
858892
method flip_ast($qast) {
859893
return $qast unless nqp::istype($qast, QAST::Regex);
860894
if $qast.rxtype eq 'literal' {

0 commit comments

Comments
 (0)