Skip to content

Commit

Permalink
finish s/NQPCursor/NQPMatch/ tranformation
Browse files Browse the repository at this point in the history
NQPMatch is now both a cursor and a match object.  (The name 'NQPCursor'
still exists but is an alias to NQPMatch now.)  A new method is provided
to clone match information for when we need a new NQPMatch identity for
operator reductions.  (The rakudo compiler also uses this for its old
'AS_MATCH' method.)

The )> regex assertion is now passed on the cstack as '$!pos' rather than
as '$!to', since at that level NQPMatch is more like a cursor than a match.

Now passes all nqp tests again.
  • Loading branch information
TimToady committed Apr 10, 2017
1 parent 2a31c20 commit e32ad16
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 41 deletions.
41 changes: 20 additions & 21 deletions src/HLL/Grammar.nqp
Expand Up @@ -368,7 +368,7 @@ An operator precedence parser.

method EXPR(str $preclim = '', int :$noinfix = 0) {
my $here := self.'!cursor_start_cur'();
my int $pos := nqp::getattr_i($here, NQPCursor, '$!from');
my int $pos := nqp::getattr_i($here, NQPMatch, '$!from');
my str $termishrx := 'termish';
my @opstack;
my @termstack;
Expand All @@ -388,10 +388,10 @@ An operator precedence parser.
my int $term_done;

while 1 {
nqp::bindattr_i($here, NQPCursor, '$!pos', $pos);
nqp::bindattr_i($here, NQPMatch, '$!pos', $pos);
$termcur := $here."$termishrx"();
$pos := nqp::getattr_i($termcur, NQPCursor, '$!pos');
nqp::bindattr_i($here, NQPCursor, '$!pos', $pos);
$pos := nqp::getattr_i($termcur, NQPMatch, '$!pos');
nqp::bindattr_i($here, NQPMatch, '$!pos', $pos);
if $pos < 0 {
$here.panic('Missing required term after infix') if @opstack;
return $here;
Expand Down Expand Up @@ -443,18 +443,18 @@ An operator precedence parser.
while $more_infix {
# Now see if we can fetch an infix operator
# First, we need ws to match.
nqp::bindattr_i($here, NQPCursor, '$!pos', $pos);
nqp::bindattr_i($here, NQPMatch, '$!pos', $pos);
$wscur := $here.ws();
$pos := nqp::getattr_i($wscur, NQPCursor, '$!pos');
$pos := nqp::getattr_i($wscur, NQPMatch, '$!pos');
if $pos < 0 {
$term_done := 1;
last;
}

# Next, try the infix itself.
nqp::bindattr_i($here, NQPCursor, '$!pos', $pos);
nqp::bindattr_i($here, NQPMatch, '$!pos', $pos);
$infixcur := $here.infixish();
$pos := nqp::getattr_i($infixcur, NQPCursor, '$!pos');
$pos := nqp::getattr_i($infixcur, NQPMatch, '$!pos');
if $pos < 0 {
$term_done := 1;
last;
Expand Down Expand Up @@ -510,20 +510,19 @@ An operator precedence parser.
}

nqp::push(@opstack, $infix); # The Shift
nqp::bindattr_i($here, NQPCursor, '$!pos', $pos);
nqp::bindattr_i($here, NQPMatch, '$!pos', $pos);
$wscur := $here.ws();
$pos := nqp::getattr_i($wscur, NQPCursor, '$!pos');
nqp::bindattr_i($here, NQPCursor, '$!pos', $pos);
$pos := nqp::getattr_i($wscur, NQPMatch, '$!pos');
nqp::bindattr_i($here, NQPMatch, '$!pos', $pos);
return $here if $pos < 0;
}

self.EXPR_reduce(@termstack, @opstack) while @opstack;
$pos := nqp::getattr_i($here, NQPCursor, '$!pos');
$here := nqp::pop(@termstack);
$here.'!cursor_pass'($pos);
nqp::bindattr_i($here, NQPCursor, '$!pos', $pos);
$here.'!reduce'('EXPR');
$here;

self.'!clone_match_at'(
nqp::pop(@termstack),
nqp::getattr_i($here, NQPMatch, '$!pos')
).'!reduce'('EXPR')
}

method EXPR_reduce(@termstack, @opstack) {
Expand Down Expand Up @@ -584,7 +583,7 @@ An operator precedence parser.

method MARKER(str $markname) {
my %markhash := nqp::getattr(
nqp::getattr(self, NQPCursor, '$!shared'),
nqp::getattr(self, NQPMatch, '$!shared'),
ParseShared, '%!marks');
my $cur := nqp::atkey(%markhash, $markname);
if nqp::isnull($cur) {
Expand All @@ -593,18 +592,18 @@ An operator precedence parser.
nqp::bindkey(%markhash, $markname, $cur);
}
else {
nqp::bindattr_i($cur, NQPCursor, '$!from', self.from);
nqp::bindattr_i($cur, NQPMatch, '$!from', self.from);
$cur."!cursor_pos"(self.pos());
$cur
}
}

method MARKED(str $markname) {
my %markhash := nqp::getattr(
nqp::getattr(self, NQPCursor, '$!shared'),
nqp::getattr(self, NQPMatch, '$!shared'),
ParseShared, '%!marks');
my $cur := nqp::atkey(%markhash, $markname);
unless nqp::istype($cur, NQPCursor) && $cur.pos() == self.pos() {
unless nqp::istype($cur, NQPMatch) && $cur.pos() == self.pos() {
$cur := self.'!cursor_start_fail'();
}
$cur
Expand Down
4 changes: 2 additions & 2 deletions src/NQP/Actions.nqp
Expand Up @@ -658,7 +658,7 @@ class NQP::Actions is HLL::Actions {
}
}
elsif nqp::can($how, 'set_default_parent') {
my $default := $*PKGDECL eq 'grammar' ?? ['NQPCursor'] !! ['NQPMu'];
my $default := $*PKGDECL eq 'grammar' ?? ['NQPMatch'] !! ['NQPMu'];
$*W.pkg_add_parent_or_role($package, "set_default_parent",
$*W.find_sym($default));
}
Expand Down Expand Up @@ -1932,7 +1932,7 @@ class NQP::RegexActions is QRegex::P6Regex::Actions {
method set_cursor_type($qast) {
my $cursor_type := nqp::null();
try {
$cursor_type := $*W.find_sym(['NQPCursor']);
$cursor_type := $*W.find_sym(['NQPMatch']);
};
$qast.cursor_type($cursor_type) unless nqp::isnull($cursor_type);
}
Expand Down
42 changes: 27 additions & 15 deletions src/QRegex/Cursor.nqp
Expand Up @@ -65,7 +65,7 @@ my class Braid is export {
}
}

role NQPCursorRole is export {
role NQPMatchRole is export {
has $!shared;
has int $!from;
has int $!pos;
Expand Down Expand Up @@ -610,6 +610,18 @@ role NQPCursorRole is export {
$!regexsub($new);
}

method !clone_match_at($term, int $pos) {
my $new := self.'!cursor_start_cur'();
$new.'!cursor_pass'($pos);
nqp::bindattr_i($new, NQPMatch, '$!pos', $pos);
nqp::bindattr_i($new, NQPMatch, '$!from', nqp::getattr($term, NQPMatch, '$!from' ));
nqp::bindattr( $new, NQPMatch, '$!made', nqp::getattr($term, NQPMatch, '$!made' ));
nqp::bindattr( $new, NQPCapture, '@!array', nqp::getattr($term, NQPCapture, '@!array'));
nqp::bindattr( $new, NQPCapture, '%!hash', nqp::getattr($term, NQPCapture, '%!hash' ));
nqp::bindattr( $new, NQPMatch, '$!match', nqp::getattr($term, NQPMatch, '$!match'));
$new;
}

method !reduce(str $name) {
my $actions := self.actions;
nqp::findmethod($actions, $name)($actions, self.MATCH)
Expand Down Expand Up @@ -1100,24 +1112,24 @@ class NQPOldMatch {
method Bool() { 1 }
}

class NQPCursor is NQPCapture does NQPCursorRole {
class NQPMatch is NQPCapture does NQPMatchRole {
my @EMPTY_LIST := [];
my $NO_CAPS := nqp::hash();
method MATCH() {
my $match := nqp::getattr(self, NQPCursor, '$!match');
my $match := nqp::getattr(self, NQPMatch, '$!match');
if nqp::isnull($match) || (!nqp::istype($match, NQPOldMatch) && !nqp::ishash($match)) {
# Set up basic state of (old) Match.
my $list;
my $hash := nqp::hash();
$match := nqp::create(NQPOldMatch);
nqp::bindattr(self, NQPCursor, '$!match',
nqp::getattr_i(self, NQPCursor, '$!pos') >= nqp::getattr_i(self, NQPCursor, '$!from')
nqp::bindattr(self, NQPMatch, '$!match',
nqp::getattr_i(self, NQPMatch, '$!pos') >= nqp::getattr_i(self, NQPMatch, '$!from')
?? $match
!! nqp::null());

# For captures with lists, initialize the lists.
my %caplist := $NO_CAPS;
my $rxsub := nqp::getattr(self, NQPCursor, '$!regexsub');
my $rxsub := nqp::getattr(self, NQPMatch, '$!regexsub');
my str $onlyname := '';
my int $namecount := 0;
if !nqp::isnull($rxsub) && nqp::defined($rxsub) {
Expand All @@ -1141,7 +1153,7 @@ class NQPCursor is NQPCapture does NQPCursorRole {
}

# Walk the Cursor stack and populate the Cursor.
my $cs := nqp::getattr(self, NQPCursor, '$!cstack');
my $cs := nqp::getattr(self, NQPMatch, '$!cstack');
if nqp::isnull($cs) || !nqp::istrue($cs) {}
elsif $namecount == 1 && $onlyname ne '' && !nqp::eqat($onlyname, '$!', 0) {
# If there's only one destination, avoid repeated hash lookups
Expand Down Expand Up @@ -1173,8 +1185,8 @@ class NQPCursor is NQPCapture does NQPCursorRole {
my str $name := nqp::getattr_s($subcur, $?CLASS, '$!name');
if !nqp::isnull_s($name) && nqp::defined($name) && $name ne '' {
my $submatch := $subcur.MATCH();
if nqp::ord($name) == 36 && ($name eq '$!from' || $name eq '$!to') {
nqp::bindattr_i($match, NQPOldMatch, $name, $submatch.from);
if nqp::ord($name) == 36 && ($name eq '$!from' || $name eq '$!pos') {
nqp::bindattr_i(self, NQPMatch, $name, $submatch.from);
}
elsif nqp::index($name, '=') < 0 {
my int $needs_list := %caplist{$name} >= 2;
Expand Down Expand Up @@ -1239,9 +1251,9 @@ class NQPCursor is NQPCapture does NQPCursorRole {

# Once we've produced the captures, and if we know we're finished and
# will never be backtracked into, we can release cstack and regexsub.
unless nqp::defined(nqp::getattr(self, NQPCursor, '$!bstack')) {
nqp::bindattr(self, NQPCursor, '$!cstack', nqp::null());
nqp::bindattr(self, NQPCursor, '$!regexsub', nqp::null());
unless nqp::defined(nqp::getattr(self, NQPMatch, '$!bstack')) {
nqp::bindattr(self, NQPMatch, '$!cstack', nqp::null());
nqp::bindattr(self, NQPMatch, '$!regexsub', nqp::null());
}
}
self
Expand Down Expand Up @@ -1322,15 +1334,15 @@ class NQPCursor is NQPCapture does NQPCursorRole {
}
}

my constant NQPMatch := NQPCursor;
my constant NQPCursor := NQPMatch;

class NQPRegexMethod {
has $!code;
method new($code) {
self.bless(:code($code));
}
multi method ACCEPTS(NQPRegexMethod:D $self: $target) {
NQPCursor.parse($target, :rule(self))
NQPMatch.parse($target, :rule(self))
}
method name() {
nqp::getcodename($!code)
Expand All @@ -1343,7 +1355,7 @@ nqp::setinvokespec(NQPRegexMethod, NQPRegexMethod, '$!code', nqp::null);

class NQPRegex is NQPRegexMethod {
multi method ACCEPTS(NQPRegex:D $self: $target) {
NQPCursor.parse($target, :rule(self), :c(0))
NQPMatch.parse($target, :rule(self), :c(0))
}
}
nqp::setinvokespec(NQPRegex, NQPRegexMethod, '$!code', nqp::null);
4 changes: 2 additions & 2 deletions src/QRegex/P5Regex/Actions.nqp
Expand Up @@ -432,7 +432,7 @@ class QRegex::P5Regex::Actions is HLL::Actions {
}
%capnames{''} := $count;
nqp::deletekey(%capnames, '$!from');
nqp::deletekey(%capnames, '$!to');
nqp::deletekey(%capnames, '$!pos');
%capnames;
}

Expand Down Expand Up @@ -504,7 +504,7 @@ class QRegex::P5Regex::Actions is HLL::Actions {

method metachar:sym<to>($/) {
make QAST::Regex.new( :rxtype<subrule>, :subtype<capture>,
:backtrack<r>, :name<$!to>, :node($/),
:backtrack<r>, :name<$!pos>, :node($/),
QAST::NodeList.new(
QAST::SVal.new( :value('!LITERAL') ),
QAST::SVal.new( :value('') ) ) );
Expand Down
2 changes: 1 addition & 1 deletion src/QRegex/P6Regex/Actions.nqp
Expand Up @@ -273,7 +273,7 @@ class QRegex::P6Regex::Actions is HLL::Actions {

method metachar:sym<to>($/) {
make QAST::Regex.new( :rxtype<subrule>, :subtype<capture>,
:backtrack<r>, :name<$!to>, :node($/),
:backtrack<r>, :name<$!pos>, :node($/),
QAST::NodeList.new(
QAST::SVal.new( :value('!LITERAL') ),
QAST::SVal.new( :value('') ) ) );
Expand Down

0 comments on commit e32ad16

Please sign in to comment.