Skip to content

Commit 00d8597

Browse files
committed
First crack at high expectation tracking.
1 parent 68a947d commit 00d8597

File tree

3 files changed

+87
-19
lines changed

3 files changed

+87
-19
lines changed

src/QRegex/Cursor.nqp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ my class ParseShared {
33
has $!orig;
44
has str $!target;
55
has int $!highwater;
6+
has @!highexpect;
67
}
78

89
role NQPCursorRole is export {
@@ -79,6 +80,7 @@ role NQPCursorRole is export {
7980
nqp::bindattr_s($shared, ParseShared, '$!target',
8081
pir::trans_encoding__Ssi($orig, pir::find_encoding__Is('ucs4')));
8182
nqp::bindattr_i($shared, ParseShared, '$!highwater', 0);
83+
nqp::bindattr($shared, ParseShared, '@!highexpect', nqp::list());
8284
}
8385
nqp::bindattr($new, $?CLASS, '$!shared', $shared);
8486
if nqp::defined($c) {
@@ -203,16 +205,21 @@ role NQPCursorRole is export {
203205

204206
my @EMPTY := [];
205207
method !protoregex($name) {
206-
# Obtain and run NFA.
207-
my $shared := $!shared;
208-
my $nfa := self.HOW.cache(self, $name, { self.'!protoregex_nfa'($name) });
209-
my @fates := $nfa.run(nqp::getattr_s($shared, ParseShared, '$!target'), $!pos);
210-
211208
# Update highwater mark.
209+
my $shared := $!shared;
212210
my int $highwater := nqp::getattr_i($shared, ParseShared, '$!highwater');
213-
if $!pos > $highwater {
214-
nqp::bindattr_i($shared, ParseShared, '$!highwater', $!pos);
211+
my $highexpect := nqp::null();
212+
if $!pos >= $highwater {
213+
$highexpect := nqp::getattr($shared, ParseShared, '@!highexpect');
214+
if $!pos > $highwater {
215+
pir::assign__0Pi($highexpect, 0);
216+
nqp::bindattr_i($shared, ParseShared, '$!highwater', $!pos);
217+
}
215218
}
219+
220+
# Obtain and run NFA.
221+
my $nfa := self.HOW.cache(self, $name, { self.'!protoregex_nfa'($name) });
222+
my @fates := $nfa.run(nqp::getattr_s($shared, ParseShared, '$!target'), $!pos, $highexpect);
216223

217224
# Visit rules in fate order.
218225
my @rxfate := $nfa.states[0];
@@ -261,13 +268,18 @@ role NQPCursorRole is export {
261268
# Update highwater mark.
262269
my $shared := $!shared;
263270
my int $highwater := nqp::getattr_i($shared, ParseShared, '$!highwater');
264-
if $pos > $highwater {
265-
nqp::bindattr_i($shared, ParseShared, '$!highwater', $pos);
271+
my $highexpect := nqp::null();
272+
if $pos >= $highwater {
273+
$highexpect := nqp::getattr($shared, ParseShared, '@!highexpect');
274+
if $pos > $highwater {
275+
pir::assign__0Pi($highexpect, 0);
276+
nqp::bindattr_i($shared, ParseShared, '$!highwater', $pos);
277+
}
266278
}
267279

268280
# Evaluate the alternation.
269281
my $nfa := self.HOW.cache(self, $name, { self.'!alt_nfa'($!regexsub, $name) });
270-
$nfa.run_alt(nqp::getattr_s($shared, ParseShared, '$!target'), $pos, $!bstack, $!cstack, @labels);
282+
$nfa.run_alt(nqp::getattr_s($shared, ParseShared, '$!target'), $pos, $!bstack, $!cstack, @labels, $highexpect);
271283
}
272284

273285
method !alt_nfa($regex, str $name) {
@@ -312,7 +324,13 @@ role NQPCursorRole is export {
312324
nqp::getattr_i($!shared, ParseShared, '$!highwater')
313325
}
314326

327+
method !highexpect() {
328+
nqp::getattr($!shared, ParseShared, '@!highexpect')
329+
}
330+
315331
method !clear_highwater() {
332+
my $highexpect := nqp::getattr($!shared, ParseShared, '@!highexpect');
333+
pir::assign__0Pi($highexpect, 0);
316334
nqp::bindattr_i($!shared, ParseShared, '$!highwater', -1)
317335
}
318336

src/QRegex/NFA.nqp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class QRegex::NFA {
1313
our $EDGE_CODEPOINT_I := 9;
1414
our $EDGE_CODEPOINT_I_NEG := 10;
1515
our $EDGE_GENERIC_VAR := 11;
16+
our $EDGE_DBA := 12;
1617

1718
has $!states;
1819
has $!edges;
@@ -74,6 +75,10 @@ class QRegex::NFA {
7475
method anchor($node, int $from, int $to) {
7576
self.addedge($from, $to, $EDGE_EPSILON, 0);
7677
}
78+
79+
method dba($node, int $from, int $to) {
80+
self.addedge($from, $to, $EDGE_DBA, $node.name);
81+
}
7782

7883
my %cclass_code;
7984
INIT {
@@ -344,7 +349,7 @@ class QRegex::NFA {
344349
}
345350
}
346351

347-
method run(str $target, int $offset) {
352+
method run(str $target, int $offset, $highexpect) {
348353
# This does what the NQP below says, but these days an op is used since
349354
# it's hugely faster.
350355
#my $eos := nqp::chars($target);
@@ -391,11 +396,11 @@ class QRegex::NFA {
391396
# $gen := $gen + 1;
392397
#}
393398
#@fates;
394-
pir::nqp_nfa_run_protoregex__PPSI($!states, $target, $offset)
399+
pir::nqp_nfa_run_protoregex__PPSIP($!states, $target, $offset, $highexpect)
395400
}
396401

397-
method run_alt(str $target, int $offset, $bstack, $cstack, @labels) {
398-
pir::nqp_nfa_run_alternation__vPSIPPP($!states, $target, $offset, $bstack, $cstack, @labels)
402+
method run_alt(str $target, int $offset, $bstack, $cstack, @labels, $highexpect) {
403+
pir::nqp_nfa_run_alternation__vPSIPPPP($!states, $target, $offset, $bstack, $cstack, @labels, $highexpect)
399404
}
400405

401406
method generic() {

src/ops/nqp.ops

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ static INTVAL nqpdebflags_i = 0;
5050
#define EDGE_CHARLIST_NEG 7
5151
#define EDGE_CODEPOINT_I 9
5252
#define EDGE_CODEPOINT_I_NEG 10
53+
#define EDGE_DBA 12
5354

5455
/* Objects we use every time we run an NFA; since we always run one NFA
5556
* at a time, we can re-use these. */
@@ -143,7 +144,7 @@ quicksort(INTVAL *arr, INTVAL elements) {
143144

144145
/* Does a run of the NFA. Produces a list of integers indicating the
145146
* chosen ordering. */
146-
static INTVAL * nqp_nfa_run(PARROT_INTERP, PMC *states, STRING *target, INTVAL offset, INTVAL *total_fates_out) {
147+
static INTVAL * nqp_nfa_run(PARROT_INTERP, PMC *states, STRING *target, INTVAL offset, INTVAL *total_fates_out, PMC *high_expect) {
147148
INTVAL eos = Parrot_str_length(interp, target);
148149
INTVAL gen = 1;
149150
PMC *curst = nfa_curst;
@@ -219,6 +220,12 @@ static INTVAL * nqp_nfa_run(PARROT_INTERP, PMC *states, STRING *target, INTVAL o
219220
else if (act == EDGE_EPSILON && to < num_states && done[to] != gen) {
220221
VTABLE_push_integer(interp, curst, to);
221222
}
223+
else if (act == EDGE_DBA) {
224+
if (!PMC_IS_NULL(high_expect))
225+
VTABLE_push_pmc(interp, high_expect,
226+
VTABLE_get_pmc_keyed_int(interp, edge_info, i + 1));
227+
VTABLE_push_integer(interp, curst, to);
228+
}
222229
else if (offset >= eos) {
223230
/* Can't match, so drop state. */
224231
}
@@ -2257,14 +2264,14 @@ Pushes a label onto a list.
22572264

22582265
=cut
22592266

2260-
=item nqp_nfa_run_protoregex(fatepos, states, target, offset)
2267+
=item nqp_nfa_run_protoregex(fatepos, states, target, offset, high_expect)
22612268

22622269
Takes a set of states in $2, a target string in $3 and an offset in $4.
22632270
Runs the NFA and puts the order to try the fates into $1.
22642271

22652272
=cut
22662273

2267-
=item nqp_nfa_run_alternation(states, target, offset, bstack, cstack)
2274+
=item nqp_nfa_run_alternation(states, target, offset, bstack, cstack, high_expect)
22682275

22692276
Takes a set of states in $1, a target string in $2 and an offset in $3.
22702277
Updates the bstack in $4 with backtracking points to try the alternation
@@ -2331,7 +2338,7 @@ inline op nqp_push_label(invar PMC, in LABEL) :base_core {
23312338
inline op nqp_nfa_run_protoregex(out PMC, invar PMC, in STR, in INT) :base_core {
23322339
/* Run the NFA. */
23332340
INTVAL total_fates, i;
2334-
INTVAL *fates = nqp_nfa_run(interp, $2, $3, $4, &total_fates);
2341+
INTVAL *fates = nqp_nfa_run(interp, $2, $3, $4, &total_fates, PMCNULL);
23352342

23362343
/* Copy results into an RIA. */
23372344
PMC *fatepmc = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
@@ -2352,7 +2359,7 @@ inline op nqp_nfa_run_alternation(invar PMC, in STR, in INT, invar PMC, invar PM
23522359

23532360
/* Run the NFA. */
23542361
INTVAL total_fates, i;
2355-
INTVAL *fates = nqp_nfa_run(interp, states, target, offset, &total_fates);
2362+
INTVAL *fates = nqp_nfa_run(interp, states, target, offset, &total_fates, PMCNULL);
23562363

23572364
/* Push the results onto the bstack. */
23582365
INTVAL caps = VTABLE_defined(interp, cstack) ? VTABLE_elements(interp, cstack) : 0;
@@ -2366,6 +2373,44 @@ inline op nqp_nfa_run_alternation(invar PMC, in STR, in INT, invar PMC, invar PM
23662373
free(fates);
23672374
}
23682375

2376+
inline op nqp_nfa_run_protoregex(out PMC, invar PMC, in STR, in INT, invar PMC) :base_core {
2377+
/* Run the NFA. */
2378+
INTVAL total_fates, i;
2379+
INTVAL *fates = nqp_nfa_run(interp, $2, $3, $4, &total_fates, $5);
2380+
2381+
/* Copy results into an RIA. */
2382+
PMC *fatepmc = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
2383+
for (i = 0; i < total_fates; i++)
2384+
VTABLE_set_integer_keyed_int(interp, fatepmc, i, fates[i]);
2385+
free(fates);
2386+
2387+
$1 = fatepmc;
2388+
}
2389+
2390+
inline op nqp_nfa_run_alternation(invar PMC, in STR, in INT, invar PMC, invar PMC, invar PMC, invar PMC) :base_core {
2391+
PMC *states = $1;
2392+
STRING *target = $2;
2393+
INTVAL offset = $3;
2394+
PMC *bstack = $4;
2395+
PMC *cstack = $5;
2396+
PMC *labels = $6;
2397+
PMC *highex = $7;
2398+
2399+
/* Run the NFA. */
2400+
INTVAL total_fates, i;
2401+
INTVAL *fates = nqp_nfa_run(interp, states, target, offset, &total_fates, highex);
2402+
2403+
/* Push the results onto the bstack. */
2404+
INTVAL caps = VTABLE_defined(interp, cstack) ? VTABLE_elements(interp, cstack) : 0;
2405+
for (i = 0; i < total_fates; i++) {
2406+
VTABLE_push_integer(interp, bstack,
2407+
VTABLE_get_integer_keyed_int(interp, labels, fates[i]));
2408+
VTABLE_push_integer(interp, bstack, offset);
2409+
VTABLE_push_integer(interp, bstack, 0);
2410+
VTABLE_push_integer(interp, bstack, caps);
2411+
}
2412+
free(fates);
2413+
}
23692414

23702415
/*
23712416

0 commit comments

Comments
 (0)