Skip to content

Commit

Permalink
Give NState responsibilities for backtrack control
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Sep 14, 2010
1 parent 69dcd45 commit 65081a4
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 101 deletions.
83 changes: 31 additions & 52 deletions lib/Cursor.cs
Expand Up @@ -6,11 +6,14 @@
// stuff that should 'N'est, like subrules do
public sealed class NState {
public NState next;
public string name;
public Choice cut_to;
public int quant;
public DynMetaObject klass;

public NState(NState proto) {
next = proto; if (proto != null) klass = proto.klass;
public NState(Choice cut_to, string name, NState proto) {
next = proto; this.cut_to = cut_to; this.name = name;
if (proto != null) klass = proto.klass;
}
}

Expand Down Expand Up @@ -39,31 +42,19 @@ public sealed class Choice {
// the current Choice doesn't really have any of these fields, which are
// used for backtrack control
public int ip;
public string tag;
public bool committed;

public void Commit() {
// we aren't going to backtrack here, so we can't use this.
// help out the GC
st.subrule_iter = null;
committed = true;
ip = (ip < 0) ? ip : (-ip-1);
}

public Choice(Choice prev, string tag, int ip, State st) {
this.tag = tag;
public Choice(Choice prev, int ip, State st) {
this.ip = ip;
this.st = st;
this.prev = prev;
}

public void Dump(string st) {
string ac = st;
for (Choice x = this; x != null; x = x.prev) {
ac += x.committed ? " + " : " - ";
ac += x.tag;
}
Console.WriteLine(ac);
}
}

// extends Frame for a time/space tradeoff
Expand Down Expand Up @@ -93,16 +84,16 @@ public sealed class RxFrame {
orig = csr.backing_ca;
orig_s = csr.backing;
end = orig.Length;
rootf = bt = new Choice(csr.xact, "RULE " + name, -1, default(State));
st.ns = new NState(csr.nstate);
rootf = bt = csr.xact;
st.ns = new NState(rootf, "RULE " + name, csr.nstate);
st.ns.klass = csr.klass;
st.pos = csr.pos;
from = csr.pos;
}

public Frame Backtrack(Frame th) {
// throw away cut or mark-only frames
while (bt != rootf && (bt.committed || bt.ip < 0))
while (bt != rootf && (bt.ip < 0))
bt = bt.prev;
if (bt == rootf) {
if (return_one) {
Expand All @@ -124,8 +115,8 @@ public sealed class RxFrame {
}
}

public void PushBacktrack(string name, int ip) {
bt = new Choice(bt, name, ip, st);
public void PushBacktrack(int ip) {
bt = new Choice(bt, ip, st);
}

public void PushCapture(string[] cn, Cursor cl) {
Expand All @@ -144,21 +135,18 @@ public sealed class RxFrame {
st.pos = pos;
}

public void CommitAll() {
Choice x = bt;
while (x != null) {
x.Commit();
x = x.prev;
}
public void PushCutGroup(string tag) {
st.ns = new NState(bt, tag, st.ns);
}

public void CommitSpecificRule(string name) {
public void PopCutGroup() {
st.ns = st.ns.next;
}

public void CommitAll() {
Choice x = bt;
name = "RULE " + name;
while (x != null) {
x.Commit();
if (x.tag.Equals(name))
break;
x = x.prev;
}
}
Expand All @@ -171,27 +159,18 @@ public sealed class RxFrame {
}
}

public void CommitGroup(string open, string close) {
Choice x = bt;
if (Cursor.Trace)
x.Dump("committing " + open + "," + close);
int level = 1;
while (x != null) {
x.Commit();
if (x.tag == open)
level--;
else if (x.tag == close)
level++;
x = x.prev;
if (level == 0)
break;
public void CommitGroup(string id) {
NState nsi = st.ns;
while (nsi != null && !nsi.name.Equals(id))
nsi = nsi.next;
Choice to = (nsi != null) ? nsi.cut_to : null;
Choice it = bt;
while (it != to) {
it.Commit();
it = it.prev;
}
}

public bool IsTopCut() {
return bt.committed;
}

public bool Exact(string str) {
if (st.pos + str.Length > end)
return false;
Expand Down Expand Up @@ -224,15 +203,15 @@ public sealed class RxFrame {
}

public void LTMPushAlts(Lexer lx, int[] addrs) {
PushBacktrack("LTM", -1);
PushCutGroup("LTM");
int[] cases = lx.Run(orig_s, st.pos);
for (int i = cases.Length - 1; i >= 0; i--) {
PushBacktrack("LTMALT", addrs[cases[i]]);
PushBacktrack(addrs[cases[i]]);
}
}

public void OpenQuant() {
st.ns = new NState(st.ns);
st.ns = new NState(bt, "QUANT", st.ns);
}

public int CloseQuant() {
Expand Down
3 changes: 3 additions & 0 deletions src/CgOp.pm
Expand Up @@ -554,6 +554,9 @@ use warnings;
}

sub rxframe { getfield('rx', callframe) }
sub rxcall { rawcall(rxframe, @_) }
sub pushcut { rxcall('PushCutGroup', clr_string($_[0])) }
sub popcut { rxcall('PopCutGroup') }

sub letvar {
$_[1] ?
Expand Down
7 changes: 3 additions & 4 deletions src/CodeGen.pm
Expand Up @@ -64,15 +64,15 @@ use 5.010;
'RxFrame' =>
{ Exact => [m => 'Boolean'],
Exact1 => [m => 'Boolean'],
IsTopCut => [m => 'Boolean'],
IncQuant => [m => 'Void'],
GetQuant => [m => 'Int32'],
OpenQuant => [m => 'Void'],
CloseQuant => [m => 'Int32'],
CommitGroup => [m => 'Void'],
CommitRule => [m => 'Void'],
CommitAll => [m => 'Void'],
CommitSpecificRule => [m => 'Void'],
PushCutGroup => [m => 'Void'],
PopCutGroup => [m => 'Void'],
GetCursorList=> [m => 'Variable'],
SetCursorList=> [m => 'Void'],
LTMPushAlts => [m => 'Void'],
Expand Down Expand Up @@ -692,8 +692,7 @@ use 5.010;

sub rxpushb {
my ($self, $tag, $label) = @_;
push @{ $self->buffer }, " th.rx.PushBacktrack(" . qm($tag) .
", " . ($label ? "\@\@L$label" : "-1") . ");\n";
push @{ $self->buffer }, " th.rx.PushBacktrack(\@\@L$label);\n";
}

sub return {
Expand Down
73 changes: 28 additions & 45 deletions src/RxOp.pm
Expand Up @@ -172,14 +172,12 @@ use CgOp;
my $n = @{ $self->zyg };

for (my $i = 0; $i < $n; $i++) {
push @code, CgOp::rxpushb("SEQALT",
($i == $n - 1) ? undef : $ends[$i]);
push @code, CgOp::rxpushb("SEQALT", $ends[$i]) unless $i == $n - 1;
push @code, $self->zyg->[$i]->code($body);
push @code, CgOp::goto($ends[$n-1]) unless $i == $n-1;
push @code, CgOp::label($ends[$i]);
}

push @code, CgOp::rxpushb("ENDSEQALT");
@code;
}

Expand All @@ -198,9 +196,9 @@ use CgOp;
sub code {
my ($self, $body) = @_;
my @code;
push @code, CgOp::rxpushb("BRACK");
push @code, CgOp::pushcut("BRACK");
push @code, $self->zyg->[0]->code($body);
push @code, CgOp::rxpushb("ENDBRACK");
push @code, CgOp::popcut();
@code;
}

Expand All @@ -222,11 +220,11 @@ use CgOp;
my ($self, $body) = @_;

my @code;
push @code, CgOp::rxpushb("CUTGRP");
push @code, CgOp::pushcut("CUTGRP");
push @code, $self->zyg->[0]->code($body);
push @code, CgOp::rawcall(CgOp::rxframe, 'CommitGroup',
CgOp::clr_string("CUTGRP"), CgOp::clr_string("ENDCUTGRP"));
push @code, CgOp::rxpushb("ENDCUTGRP");
CgOp::clr_string("CUTGRP"));
push @code, CgOp::popcut();

@code;
}
Expand All @@ -248,22 +246,8 @@ use CgOp;
sub code {
my ($self, $body) = @_;

my $fail = $self->label;
my $pass = $self->label;
my @code;
push @code, CgOp::rxpushb("CUTGRP", $pass);
push @code, CgOp::rxpushb("CUTGRP", $fail);
push @code, $self->zyg->[0]->code($body);
push @code, CgOp::rawcall(CgOp::rxframe, 'CommitGroup',
CgOp::clr_string("CUTGRP"), CgOp::clr_string("ENDCUTGRP"));
push @code, CgOp::goto('backtrack');
push @code, CgOp::label($fail);
push @code, CgOp::rawcall(CgOp::rxframe, 'CommitGroup',
CgOp::clr_string("CUTGRP"), CgOp::clr_string("ENDCUTGRP"));
push @code, CgOp::goto('backtrack');
push @code, CgOp::label($pass);

@code;
RxOp::NotBefore->new(zyg => [RxOp::NotBefore->new(zyg => $self->zyg)])
->code($body);
}

sub lad {
Expand All @@ -285,12 +269,13 @@ use CgOp;

my $pass = $self->label;
my @code;
push @code, CgOp::pushcut("CUTGRP");
push @code, CgOp::rxpushb("CUTGRP", $pass);
push @code, $self->zyg->[0]->code($body);
push @code, CgOp::rawcall(CgOp::rxframe, 'CommitGroup',
CgOp::clr_string("CUTGRP"), CgOp::clr_string("ENDCUTGRP"));
push @code, CgOp::rxcall('CommitGroup', CgOp::clr_string("CUTGRP"));
push @code, CgOp::goto('backtrack');
push @code, CgOp::label($pass);
push @code, CgOp::popcut;

@code;
}
Expand Down Expand Up @@ -344,17 +329,16 @@ use CgOp;

my $namesf = CgOp::const(CgOp::rawnewarr('String',
map { CgOp::clr_string($_) } @{ $self->captures }));
my $callf = CgOp::methodcall(CgOp::newscalar(CgOp::rawcall(
CgOp::rxframe, "MakeCursor")), $self->name);
my $callf = CgOp::methodcall(CgOp::newscalar(
CgOp::rxcall("MakeCursor")), $self->name);
my @pushcapf = (@{ $self->captures } == 0) ? () : (
CgOp::rawcall(CgOp::rxframe, "PushCapture",
$namesf, CgOp::cast('Cursor', CgOp::letvar("k"))));
CgOp::rxcall("PushCapture", $namesf,
CgOp::cast('Cursor', CgOp::letvar("k"))));
my $updatef = CgOp::prog(
CgOp::ncgoto('backtrack', CgOp::rawcall(CgOp::letvar("k"),
'IsDefined')),
@pushcapf,
CgOp::rawcall(CgOp::rxframe, "SetPos",
CgOp::getfield("pos", CgOp::cast("Cursor",
CgOp::rxcall("SetPos", CgOp::getfield("pos", CgOp::cast("Cursor",
CgOp::letvar("k")))));

my @code;
Expand All @@ -365,19 +349,18 @@ use CgOp;
CgOp::fetch($callf))),
$updatef);
} else {
push @code, CgOp::rawcall(CgOp::rxframe, "SetCursorList", $callf);
push @code, CgOp::rxcall("SetCursorList", $callf);
push @code, CgOp::goto($sk);
push @code, CgOp::label($bt);
push @code, CgOp::sink(CgOp::methodcall(CgOp::rawcall(CgOp::rxframe,
push @code, CgOp::sink(CgOp::methodcall(CgOp::rxcall(
"GetCursorList"), "shift"));
push @code, CgOp::label($sk);
push @code, CgOp::letn(
"k", CgOp::fetch(CgOp::rawsccall('Kernel.GetFirst:c,Variable',
CgOp::fetch(CgOp::rawcall(CgOp::rxframe, "GetCursorList")))),
CgOp::fetch(CgOp::rxcall("GetCursorList")))),
$updatef);
push @code, CgOp::rxpushb("SUBRULE", $bt);
push @code, CgOp::rawcall(CgOp::rxframe, "SetCursorList",
CgOp::null("Variable"));
push @code, CgOp::rxcall("SetCursorList", CgOp::null("Variable"));
}

@code;
Expand Down Expand Up @@ -423,8 +406,7 @@ use CgOp;

sub code {
my ($self, $body) = @_;
CgOp::rawcall(CgOp::rxframe, 'CommitGroup',
CgOp::clr_string("LTM"), CgOp::clr_string("ENDLTM"));
CgOp::rxcall('CommitGroup', CgOp::clr_string("LTM"))
}

sub lad {
Expand All @@ -443,7 +425,7 @@ use CgOp;

sub code {
my ($self, $body) = @_;
CgOp::rawcall(CgOp::rxframe, 'CommitRule');
CgOp::rxcall('CommitRule');
}

sub lad {
Expand Down Expand Up @@ -480,7 +462,7 @@ use CgOp;
my $end = $self->label;

my @code;
push @code, CgOp::rawcall(CgOp::rxframe, "LTMPushAlts",
push @code, CgOp::rxcall("LTMPushAlts",
CgOp::rawscall('Lexer.GetLexer',
CgOp::rawcall(CgOp::rxframe, 'MakeCursor'),
CgOp::const(RxOp::lad2cgop($self->lads)),
Expand All @@ -493,7 +475,7 @@ use CgOp;
push @code, CgOp::goto($end) unless $i == @ls - 1;
}
push @code, CgOp::label($end);
push @code, CgOp::rxpushb('ENDLTM');
push @code, CgOp::popcut;
@code;
}

Expand All @@ -517,7 +499,7 @@ use CgOp;
sub code {
my ($self, $body) = @_;
CgOp::subcall(CgOp::fetch($self->block->cgop($body)),
CgOp::newscalar(CgOp::rawcall(CgOp::rxframe, "MakeCursor")));
CgOp::newscalar(CgOp::rxcall("MakeCursor")));
}

sub lad {
Expand Down Expand Up @@ -547,14 +529,15 @@ use CgOp;
"i", CgOp::int(0),
"ks", CgOp::null('Variable'),
"k", CgOp::null('IP6'),
CgOp::pushcut('LTM'),
CgOp::label('nextfn'),
CgOp::cgoto('backtrack',
CgOp::compare('>=', CgOp::letvar("i"),
CgOp::getfield("Length", CgOp::letvar("fns")))),
CgOp::rxpushb('LTM', 'nextfn'),
CgOp::letvar("ks", CgOp::subcall(CgOp::getindex(CgOp::letvar("i"),
CgOp::letvar("fns")), CgOp::newscalar(CgOp::rawcall(
CgOp::rxframe, 'MakeCursor')))),
CgOp::letvar("fns")), CgOp::newscalar(CgOp::rxcall(
'MakeCursor')))),
CgOp::letvar("i", CgOp::arith('+', CgOp::letvar("i"), CgOp::int(1))),
CgOp::letvar("k", CgOp::fetch(CgOp::rawsccall('Kernel.GetFirst:c,Variable',
CgOp::fetch(CgOp::letvar("ks"))))),
Expand Down

0 comments on commit 65081a4

Please sign in to comment.