Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
TimToady committed Apr 8, 2015
1 parent bbb164e commit 1fd8cde
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 7 deletions.
15 changes: 13 additions & 2 deletions src/NQP/Actions.nqp
Expand Up @@ -1888,9 +1888,20 @@ class NQP::RegexActions is QRegex::P6Regex::Actions {
for $<arglist>.ast.list { $qast[0].push( $_ ) }
}
elsif $<nibbler> {
$name eq 'after' ??
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>.ast), :anon(1), :addself(1))) !!
if $name eq 'after' {
my int $litlen := self.offset_ast($<nibbler>.ast);
if $litlen >= 0 {
$qast[0][0].value('before');
$qast[0].push(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
$qast[0].push(QAST::IVal.new( :value($litlen) )); # optional offset to before
}
else {
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>.ast), :anon(1), :addself(1)));
}
}
else {
$qast[0].push(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
}
}
}
make $qast;
Expand Down
6 changes: 3 additions & 3 deletions src/QRegex/Cursor.nqp
Expand Up @@ -512,13 +512,13 @@ role NQPCursorRole is export {
$cur;
}

method before($regex) {
method before($regex, $off = 0) {
my int $orig_highwater := nqp::getattr_i($!shared, ParseShared, '$!highwater');
my $orig_highexpect := nqp::getattr($!shared, ParseShared, '@!highexpect');
nqp::bindattr($!shared, ParseShared, '@!highexpect', nqp::list_s());
my $cur := self."!cursor_start_cur"();
nqp::bindattr_i($cur, $?CLASS, '$!pos', $!pos);
nqp::getattr_i($regex($cur), $?CLASS, '$!pos') >= 0 ??
nqp::bindattr_i($cur, $?CLASS, '$!pos', $!pos - $off);
$!pos >= $off && nqp::getattr_i($regex($cur), $?CLASS, '$!pos') >= 0 ??
$cur."!cursor_pass"($!pos, 'before') !!
nqp::bindattr_i($cur, $?CLASS, '$!pos', -3);
nqp::bindattr_i($!shared, ParseShared, '$!highwater', $orig_highwater);
Expand Down
38 changes: 36 additions & 2 deletions src/QRegex/P6Regex/Actions.nqp
Expand Up @@ -566,9 +566,20 @@ class QRegex::P6Regex::Actions is HLL::Actions {
for $<arglist>.ast.list { $qast[0].push( $_ ) }
}
elsif $<nibbler> {
$name eq 'after' ??
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>.ast), :anon(1), :addself(1))) !!
if $name eq 'after' {
my int $litlen := self.offset_ast($<nibbler>.ast);
if $litlen >= 0 {
$qast[0][0].value('before');
$qast[0].push(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
$qast[0].push(QAST::IVal.new( :value($litlen) )); # optional offset to before
}
else {
$qast[0].push(self.qbuildsub(self.flip_ast($<nibbler>.ast), :anon(1), :addself(1)));
}
}
else {
$qast[0].push(self.qbuildsub($<nibbler>.ast, :anon(1), :addself(1)));
}
}
}
make $qast;
Expand Down Expand Up @@ -855,6 +866,29 @@ class QRegex::P6Regex::Actions is HLL::Actions {
$ast.subtype('capture');
}

method offset_ast($qast) {
return -1 unless nqp::istype($qast, QAST::Regex);
if $qast.rxtype eq 'literal' {
return nqp::chars($qast[0]);
}
elsif $qast.rxtype eq 'cclass' {
return 1;
}
elsif $qast.rxtype eq 'anchor' {
return 0;
}
elsif $qast.rxtype eq 'concat' {
my int $litlen;
for @($qast) {
my int $ll := self.offset_ast($_);
return -1 if $ll < 0;
$litlen := $litlen + $ll;
}
return $litlen;
}
return -1;
}

method flip_ast($qast) {
return $qast unless nqp::istype($qast, QAST::Regex);
if $qast.rxtype eq 'literal' {
Expand Down

0 comments on commit 1fd8cde

Please sign in to comment.