Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Clean up the fate sorting silliness (temporary extra op due to needin…
…g a trip around the bootstrap to eliminate it; will keep the old one for another day or so in case the new way introduces issues). This shaves 10% off parse/actions time for CORE.setting.
  • Loading branch information
jnthn committed May 26, 2012
1 parent 0197389 commit 25680d9
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 27 deletions.
35 changes: 12 additions & 23 deletions src/QRegex/Cursor.nqp
Expand Up @@ -147,31 +147,20 @@ role NQPCursorRole {
}

method !protoregex($name) {
# Obtain and run NFA.
my $nfa := self.HOW.cache(self, $name, { self.'!protoregex_nfa'($name) });
my @fatepos := $nfa.run($!target, $!pos);
my @fates := $nfa.run($!target, $!pos);

# Visit rules in fate order.
my @rxfate := $nfa.states[0];
my $cur;
if @fatepos {
my $fate := 0;
my @fatesort;
my @rxfate := $nfa.states[0];
while $fate < @fatepos {
my $pos := @fatepos[$fate];
if pir::defined($pos) {
my $n := nqp::elems(@fatesort) - 1;
while $n >= 0
&& @fatepos[@fatesort[$n]] >= @fatepos[$fate] {
$n := $n - 1;
}
nqp::splice(@fatesort, [$fate], $n+1, 0);
}
$fate := $fate + 1;
}
while @fatesort {
my $rxname := @rxfate[nqp::pop(@fatesort)];
#nqp::say("invoking $rxname");
$cur := self."$rxname"();
last if nqp::getattr_i($cur, $?CLASS, '$!pos') >= 0;
}
my $i := nqp::elems(@fates);
while $i > 0 {
$i := $i - 1;
my $rxname := nqp::atpos(@rxfate, nqp::atpos_i(@fates, $i));
#nqp::say("invoking $rxname");
$cur := self."$rxname"();
last if nqp::getattr_i($cur, $?CLASS, '$!pos') >= 0;
}
$cur // self."!cursor_start"();
}
Expand Down
8 changes: 4 additions & 4 deletions src/QRegex/NFA.nqp
Expand Up @@ -253,7 +253,7 @@ class QRegex::NFA {
# This does what the NQP below says, but these days an op is used since
# it's hugely faster.
#my $eos := nqp::chars($target);
#my @fatepos;
#my @fates;
#my @nextst := [1];
#my $gen := 1;
#my @done;
Expand All @@ -266,7 +266,7 @@ class QRegex::NFA {
# @done[$st] := $gen;
# for $!states[$st] -> $act, $arg, $to {
# if $act == $EDGE_FATE {
# @fatepos[$arg] := $offset;
# @fates.push($arg);
# }
# elsif $act == $EDGE_EPSILON && @done[$to] != $gen {
# nqp::push(@curst, $to);
Expand Down Expand Up @@ -295,8 +295,8 @@ class QRegex::NFA {
# $offset := $offset + 1;
# $gen := $gen + 1;
#}
#@fatepos;
pir::nqp_nfa_run__PPSI($!states, $target, $offset)
#@fates;
pir::nqp_nfa_run_new__PPSI($!states, $target, $offset)
}

method __dump($dumper, $label) {
Expand Down
94 changes: 94 additions & 0 deletions src/ops/nqp.ops
Expand Up @@ -2210,6 +2210,100 @@ inline op nqp_nfa_run(out PMC, in PMC, in STR, in INT) :base_core {
$1 = fatepos;
}

inline op nqp_nfa_run_new(out PMC, in PMC, in STR, in INT) :base_core {
PMC *states = $2;
STRING *target = $3;
INTVAL offset = $4;
INTVAL eos = Parrot_str_length(interp, target);
PMC *fates = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
PMC *done = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
INTVAL gen = 1;
PMC *curst = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
PMC *nextst = Parrot_pmc_new(interp, enum_class_ResizableIntegerArray);
INTVAL i, num_states;

/* Zero out the done array; we don't get zeroed memory by default. */
num_states = VTABLE_elements(interp, states);
for (i = 0; i < num_states; i++)
VTABLE_set_integer_keyed_int(interp, done, i, 0);

VTABLE_push_integer(interp, nextst, 1);
while (VTABLE_elements(interp, nextst) && offset <= eos) {
/* Translation of:
* my @curst := @nextst;
* @nextst := [];
* But avoids an extra allocation per offset. */
PMC *temp = curst;
curst = nextst;
VTABLE_set_integer_native(interp, temp, 0);
nextst = temp;

while (VTABLE_elements(interp, curst)) {
PMC *edge_info;
INTVAL edge_info_elems;

INTVAL st = VTABLE_pop_integer(interp, curst);
if (VTABLE_get_integer_keyed_int(interp, done, st) == gen)
continue;
VTABLE_set_integer_keyed_int(interp, done, st, gen);

edge_info = VTABLE_get_pmc_keyed_int(interp, states, st);
edge_info_elems = VTABLE_elements(interp, edge_info);
for (i = 0; i < edge_info_elems; i += 3) {
INTVAL act = VTABLE_get_integer_keyed_int(interp, edge_info, i);
INTVAL to = VTABLE_get_integer_keyed_int(interp, edge_info, i + 2);

if (act == EDGE_FATE) {
INTVAL arg = VTABLE_get_integer_keyed_int(interp, edge_info, i + 1);
VTABLE_push_integer(interp, fates, arg);
}
else if (act == EDGE_EPSILON && VTABLE_get_integer_keyed_int(interp, done, to) != gen) {
VTABLE_push_integer(interp, curst, to);
}
else if (offset >= eos) {
/* Can't match, so drop state. */
}
else if (act == EDGE_CODEPOINT) {
UINTVAL arg = VTABLE_get_integer_keyed_int(interp, edge_info, i + 1);
if (STRING_ord(interp, target, offset) == arg)
VTABLE_push_integer(interp, nextst, to);
}
else if (act == EDGE_CODEPOINT_NEG) {
UINTVAL arg = VTABLE_get_integer_keyed_int(interp, edge_info, i + 1);
if (STRING_ord(interp, target, offset) != arg)
VTABLE_push_integer(interp, nextst, to);
}
else if (act == EDGE_CHARCLASS) {
INTVAL arg = VTABLE_get_integer_keyed_int(interp, edge_info, i + 1);
if (Parrot_str_is_cclass(interp, arg, target, offset))
VTABLE_push_integer(interp, nextst, to);
}
else if (act == EDGE_CHARCLASS_NEG) {
INTVAL arg = VTABLE_get_integer_keyed_int(interp, edge_info, i + 1);
if (!Parrot_str_is_cclass(interp, arg, target, offset))
VTABLE_push_integer(interp, nextst, to);
}
else if (act == EDGE_CHARLIST) {
STRING *arg = VTABLE_get_string_keyed_int(interp, edge_info, i + 1);
STRING *chr = STRING_substr(interp, target, offset, 1);
if (STRING_index(interp, arg, chr, 0) >= 0)
VTABLE_push_integer(interp, nextst, to);
}
else if (act == EDGE_CHARLIST_NEG) {
STRING *arg = VTABLE_get_string_keyed_int(interp, edge_info, i + 1);
STRING *chr = STRING_substr(interp, target, offset, 1);
if (STRING_index(interp, arg, chr, 0) < 0)
VTABLE_push_integer(interp, nextst, to);
}
}
}
offset++;
gen++;
}

$1 = fates;
}


/*

Expand Down

0 comments on commit 25680d9

Please sign in to comment.