Skip to content

Commit

Permalink
Implement Match.hash and Match.list
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Oct 20, 2010
1 parent eb27fd4 commit 6344d14
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 22 deletions.
80 changes: 59 additions & 21 deletions lib/Cursor.cs
Expand Up @@ -388,45 +388,83 @@ public Cursor(IP6 proto, string text)
}

public Cursor At(int npos) {
return new Cursor(global, mo, nstate, xact, npos, captures);
return new Cursor(global, mo, nstate, xact, npos, null);
}

public Cursor StripCaps() {
return new Cursor(global, save_klass, from, pos, null);
}

private Variable FixupList(VarDeque caps) {
if (caps.Count() != 0 && caps[caps.Count() - 1] == null) {
caps.Pop();
DynObject l = new DynObject(RxFrame.ListMO);
l.slots[0 /*items*/] = caps;
l.slots[1 /*rest*/ ] = new VarDeque();
l.slots[2 /*flat*/ ] = false;
return Kernel.NewRWListVar(l);
} else {
return caps.Count() != 0 ? caps[0] :
Kernel.NewROScalar(Kernel.AnyP);
}
}

// TODO: cache generated lists
public Variable GetKey(string str) {
CapInfo it = captures;
VarDeque caps = new VarDeque();
bool list = false;

while (it != null) {
foreach (string cn in it.names) {
if (cn == str)
goto yes;
}
goto no;
yes:
if (it.cap == null) {
list = true;
} else {
caps.Unshift(it.cap);
if (cn == str) {
caps.Unshift(it.cap);
break;
}
}
no:
it = it.prev;
}

if (list) {
DynObject l = new DynObject(RxFrame.ListMO);
l.slots[0 /*items*/] = caps;
l.slots[1 /*rest*/ ] = new VarDeque();
l.slots[2 /*flat*/ ] = false;
return Kernel.NewRWListVar(l);
} else {
return caps.Count() != 0 ? caps[0] :
Kernel.NewROScalar(Kernel.AnyP);
return FixupList(caps);
}

public void UnpackCaps(IP6 into) {
List<VarDeque> posr = new List<VarDeque>();
Dictionary<string,VarDeque> namr = new Dictionary<string,VarDeque>();
CapInfo it = captures;

while (it != null) {
foreach (string name in it.names) {
int nami;
VarDeque t;
if (int.TryParse(name, out nami) && nami >= 0) {
while(posr.Count <= nami) posr.Add(new VarDeque());
t = posr[nami];
} else {
if (!namr.TryGetValue(name, out t))
namr[name] = t = new VarDeque();
}
t.Unshift(it.cap);
}
it = it.prev;
}

Dictionary<string,Variable> nam = new Dictionary<string,Variable>();
Variable[] pos = new Variable[posr.Count];

foreach (KeyValuePair<string, VarDeque> kv in namr)
nam[kv.Key] = FixupList(kv.Value);
for (int i = 0; i < pos.Length; i++)
pos[i] = FixupList(posr[i]);

into.SetSlot("positionals", pos);
into.SetSlot("named", nam);
}

public Cursor O(Dictionary<string,Variable> caps) {
Cursor nw = At(pos);
foreach (KeyValuePair<string,Variable> kv in caps)
nw.captures = new CapInfo(nw.captures, new string[] { kv.Key }, kv.Value);
return nw;
}

public Variable SimpleWS() {
Expand Down
4 changes: 3 additions & 1 deletion src/CgOp.pm
Expand Up @@ -210,7 +210,9 @@ use warnings;
sub cursor_backing { rawcall($_[0], 'GetBacking:m,String') }
sub cursor_dows { rawcall($_[0], 'SimpleWS') }
sub cursor_item { rawcall($_[0], 'GetKey', $_[1]) }
sub rxstripcaps { rawcall($_[0], 'StripCaps:m,Cursor') }
sub cursor_unpackcaps { rawcall($_[0], 'UnpackCaps:m,Void', $_[1]) }
sub cursor_O { rawcall($_[0], 'O:m,Cursor', $_[1]) }
sub rxstripcaps { rawcall($_[0], 'StripCaps:m,Cursor') }

sub bget { getfield('v', $_[0]) }
sub bset { setfield('v', $_[0], $_[1]) }
Expand Down
58 changes: 58 additions & 0 deletions test2.pl
Expand Up @@ -2,6 +2,64 @@
use Test;
use MONKEY_TYPING;

augment class Regex {
method ACCEPTS($str) {
my $i = 0;
my $mat;
my $C = Cursor.new($str);
while !$mat && ($i <= $str.chars) {
$mat = (self)($C.cursor($i++));
}
unitem($mat.head);
}
}

augment class Cursor {
method O (*%hash) {
Q:CgOp { (newscalar (cursor_O (cast cursor (@ {self}))
(unbox varhash (@ {%hash})))) }
}
method list () { @( self.Capture ) }
method flat () { @( self.Capture ) }
method iterator () { self.flat.iterator }
method hash () { %( self.Capture ) }
method Capture () { Q:CgOp {
(letn cap (obj_newblank (obj_llhow (@ {Capture})))
(cursor_unpackcaps (cast cursor (@ {self})) (l cap))
(newscalar (l cap)))
} }
}

augment class Capture {
method list () { @( Q:CgOp { (box Parcel (getslot positionals fvarlist
(@ {self}))) } ) }
method hash () { unitem( Q:CgOp { (box Hash (getslot named varhash
(@ {self}))) } // {} ) }
}

augment class Match {
method list () { @( self.Capture ) }
method hash () { %( self.Capture ) }
method flat () { @( self.Capture ) }
method iterator () { self.flat.iterator }
method Capture () { Q:CgOp {
(letn cap (obj_newblank (obj_llhow (@ {Capture})))
(cursor_unpackcaps (cast cursor (@ {self})) (l cap))
(newscalar (l cap)))
} }
}
{
my $m = "ab" ~~ / (.) <alpha> /;
is (@$m)[0], "a", "Match.list returns positional captures";
is (%$m)<alpha>, "b", "Match.hash returns named";
is ((-> $p, :$alpha { $p, $alpha })(|$m)).join("|"), "a|b", "Match.Capture returns both";
my @arr = "abc" ~~ / (.) (.) (.) /;
is @arr.join("|"), "a|b|c", "Regex.ACCEPTS in list context returns captures";
$m = "" ~~ / <O( foo => 2 )> /;
is $m<O><foo>, 2, "<O> is functional";
}

# {
# our role Stop4717[$a] {
# token foo { $a }
Expand Down

0 comments on commit 6344d14

Please sign in to comment.