Oh, and here's my test code for the Match PMC. This is really just a
copy of t/pmc/perlhash.t (since the Match PMC is supposed to behave
like a hash for the most part), but with one added test case at the
end showing how this would be used to store and retrieve
hypotheticals.
Index: t/pmc/match.t
===================================================================
RCS file: t/pmc/match.t
diff -N t/pmc/match.t
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ t/pmc/match.t       17 Aug 2004 17:28:17 -0000
@@ -0,0 +1,1256 @@
+#! perl
+
+# Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
+# $Id: match.t,v 1.44 2004/04/19 12:15:22 leo Exp $
+
+=head1 NAME
+
+t/pmc/match.t - Match Objects
+
+=head1 SYNOPSIS
+
+       % perl t/pmc/match.t
+
+=head1 DESCRIPTION
+
+Tests the C<Match> PMC. Does standard hashtable testing. Then tests
+various aspects of retrieving ranges of the input string.
+
+Probably ought to do nested match objects too.
+
+=cut
+
+use Parrot::Test tests => 34;
+use Test::More;
+
+output_is(<<CODE, <<OUTPUT, "Initial Match tests");
+       new     P0, .Match
+
+       set     P0["foo"], -7
+       set     P0["bar"], 3.5
+       set     P0["baz"], "value"
+
+       set     I0, P0["foo"]
+       set     N0, P0["bar"]
+       set     S0, P0["baz"]
+
+       eq      I0,-7,OK_1
+       print   "not "
+OK_1:  print   "ok 1\\n"
+       eq      N0,3.500000,OK_2
+       print   N0
+OK_2:  print   "ok 2\\n"
+       eq      S0,"value",OK_3
+       print   S0
+OK_3:  print   "ok 3\\n"
+
+        set     S1, "oof"
+        set     S2, "rab"
+        set     S3, "zab"
+
+       set     P0[S1], 7
+       set     P0[S2], -3.5
+       set     P0[S3], "VALUE"
+
+       set     I0, P0[S1]
+       set     N0, P0[S2]
+       set     S0, P0[S3]
+
+       eq      I0,7,OK_4
+       print   "not "
+OK_4:  print   "ok 4\\n"
+       eq      N0,-3.500000,OK_5
+       print   N0
+OK_5:  print   "ok 5\\n"
+       eq      S0,"VALUE",OK_6
+       print   S0
+OK_6:  print   "ok 6\\n"
+
+       end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+ok 6
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "more than one Match");
+       new P0, .Match
+       set S0, "key"
+       set P0[S0], 1
+
+        new P1, .Match
+        set S1, "another_key"
+        set P1[S1], 2
+
+       set I0, P0[S0]
+       set I1, P1[S1]
+
+       print I0
+       print "\n"
+       print I1
+       print "\n"
+        end
+CODE
+1
+2
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "hash keys with nulls in them");
+       new P0, .Match
+       set S0, "parp\0me"
+       set S1, "parp\0you"
+
+       set P0[S0], 1           # $P0{parp\0me} = 1
+       set P0[S1], 2           # $P0{parp\0you} = 2
+
+       set I0, P0[S0]
+       set I1, P0[S1]
+
+       print I0
+       print "\n"
+       print I1
+       print "\n"
+       end
+CODE
+1
+2
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "nearly the same hash keys");
+       new P0, .Match
+       set S0, "a\0"
+       set S1, "\0a"
+
+       set P0[S0], 1
+       set P0[S1], 2
+
+       set I0, P0[S0]
+       set I1, P0[S1]
+
+       print I0
+       print "\n"
+       print I1
+       print "\n"
+
+       end
+CODE
+1
+2
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "The same hash keys");
+       new P0, .Match
+       set S0, "Happy"
+       set S1, "Happy"
+
+       set P0[S0], 1
+       set I0, P0[S0]
+       print I0
+       print "\n"
+
+       set P0[S1], 2
+       set I1, P0[S1]
+
+       print I1
+       print "\n"
+
+       end
+CODE
+1
+2
+OUTPUT
+
+# NB Next test depends on "key2" hashing to zero, which it does with
+# the current algorithm; if the algorithm changes, change the test!
+
+output_is(<<'CODE', <<OUTPUT, "key that hashes to zero");
+        new P0, .Match
+        set S0, "key2"
+        set P0[S0], 1
+        set I0, P0[S0]
+       print I0
+       print "\n"
+       end
+CODE
+1
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "size of the hash");
+       new P0, .Match
+
+       set P0["0"], 1
+       set I0, P0
+       print I0
+       print "\n"
+
+       set P0["1"], 1
+       set I0, P0
+       print I0
+       print "\n"
+
+       set P0["0"], 1
+       set I0, P0
+       print I0
+       print "\n"
+
+       end
+CODE
+1
+2
+2
+OUTPUT
+
+output_is(<<CODE, <<OUTPUT, "stress test: loop(set, check)");
+       new     P0, .Match
+
+        set I0, 200
+        set S0, "mikey"
+        set P0[S0], "base"
+        concat S1, S0, "s"
+        set P0[S1], "bases"
+        set S2, I0
+        concat S1, S0, S2
+        set P0[S1], "start"
+        set S3, P0["mikey"]
+        print S3
+        print "\\n"
+        set S3, P0["mikeys"]
+        print S3
+        print "\\n"
+        set S3, P0["mikey200"]
+        print S3
+        print "\\n"
+LOOP:
+        eq I0, 0, DONE
+        sub I0, I0, 1
+        set S2, I0
+        concat S1, S0, S2
+        concat S4, S0, S2
+        eq S1, S4, L1
+        print "concat mismatch: "
+        print S1
+        print " vs "
+        print S4
+        print "\\n"
+L1:
+        set P0[S1], I0
+        set I1, P0[S1]
+        eq I0, I1, L2
+        print "lookup mismatch: "
+        print I0
+        print " vs "
+        print I1
+        print "\\n"
+L2:
+        branch LOOP
+DONE:
+        set I0, P0["mikey199"]
+        print I0
+        print "\\n"
+        set I0, P0["mikey117"]
+        print I0
+        print "\\n"
+        set I0, P0["mikey1"]
+        print I0
+        print "\\n"
+        set I0, P0["mikey23"]
+        print I0
+        print "\\n"
+        set I0, P0["mikey832"]
+        print I0
+        print "\\n"
+        end
+CODE
+base
+bases
+start
+199
+117
+1
+23
+0
+OUTPUT
+
+# Check all values after setting all of them
+output_is(<<CODE, <<OUTPUT, "stress test: loop(set), loop(check)");
+       new     P0, .Match
+
+        set I0, 200
+        set S0, "mikey"
+SETLOOP:
+        eq I0, 0, DONE
+        sub I0, I0, 1
+        set S2, I0
+        concat S1, S0, S2
+        set P0[S1], I0
+        branch SETLOOP
+
+        set I0, 200
+GETLOOP:
+        eq I0, 0, DONE
+        sub I0, I0, 1
+        set S2, I0
+        concat S1, S0, S2
+        set I1, P0[S1]
+        eq I0, I1, L2
+        print "lookup mismatch: "
+        print I0
+        print " vs "
+        print I1
+        print "\\n"
+L2:
+        branch GETLOOP
+
+DONE:
+        print "done\\n"
+        end
+CODE
+done
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Testing two hash indices with integers at a time");
+      new P0, .Match
+
+      set P0["foo"],37
+      set P0["bar"],-15
+
+      set I0,P0["foo"]
+      eq I0,37,OK_1
+      print "not "
+OK_1: print "ok 1\n"
+
+      set I0,P0["bar"]
+      eq I0,-15,OK_2
+      print "not "
+OK_2: print "ok 2\n"
+
+      set S1,"foo"
+      set I0,P0[S1]
+      eq I0,37,OK_3
+      print "not "
+OK_3: print "ok 3\n"
+
+      set S1,"bar"
+      set I0,P0[S1]
+      eq I0,-15,OK_4
+      print "not "
+OK_4: print "ok 4\n"
+
+      end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Testing two hash indices with numbers at a time");
+      new P0, .Match
+
+      set P0["foo"],37.100000
+      set P0["bar"],-15.100000
+
+      set N0,P0["foo"]
+      eq N0,37.100000,OK_1
+      print "not "
+OK_1: print "ok 1\n"
+
+      set N0,P0["bar"]
+      eq N0,-15.100000,OK_2
+      print "not "
+OK_2: print "ok 2\n"
+
+      set S1,"foo"
+      set N0,P0[S1]
+      eq N0,37.100000,OK_3
+      print "not "
+OK_3: print "ok 3\n"
+
+      set S1,"bar"
+      set N0,P0[S1]
+      eq N0,-15.100000,OK_4
+      print "not "
+OK_4: print "ok 4\n"
+
+      end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Testing two hash indices with strings at a time");
+      new P0, .Match
+
+      set P0["foo"],"baz"
+      set P0["bar"],"qux"
+
+      set S0,P0["foo"]
+      eq S0,"baz",OK_1
+      print "not "
+OK_1: print "ok 1\n"
+
+      set S0,P0["bar"]
+      eq S0,"qux",OK_2
+      print "not "
+OK_2: print "ok 2\n"
+
+      set S1,"foo"
+      set S0,P0[S1]
+      eq S0,"baz",OK_3
+      print "not "
+OK_3: print "ok 3\n"
+
+      set S1,"bar"
+      set S0,P0[S1]
+      eq S0,"qux",OK_4
+      print "not "
+OK_4: print "ok 4\n"
+
+      end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+OUTPUT
+
+
+# So far, we've only used INTVALs, FLOATVALs and STRINGs as values
+# and/or keys. Now we try PMCs.
+
+output_is(<<'CODE', <<OUTPUT, "Setting & getting scalar PMCs");
+      new P0, .Match
+      new P1, .PerlInt
+      new P2, .PerlInt
+
+      set S0, "non-PMC key"
+
+      set P1, 10
+      set P0[S0], P1
+      set P2, P0[S0]
+      eq P2, P1, OK1
+      print "not "
+OK1:  print "ok 1\n"
+
+      set P1, -1234.000000
+      set P0[S0], P1
+      set P2, P0[S0]
+      eq P2, P1, OK2
+      print "not "
+OK2:  print "ok 2\n"
+
+      set P1, "abcdefghijklmnopq"
+      set P0[S0], P1
+      set P2, P0[S0]
+      eq P2, P1, OK3
+      print "not "
+OK3:  print "ok 3\n"
+
+      new P1, .PerlUndef
+      set P0[S0], P1
+      set P2, P0[S0]
+      typeof S1, P2
+      eq S1, "PerlUndef", OK4
+      print "not "
+OK4:  print "ok 4\n"
+
+      end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Setting scalar PMCs & getting scalar values");
+      new P0, .Match
+      new P1, .PerlInt
+
+      set S0, "A rather large key"
+
+      set I0, 10
+      set P1, I0
+      set P0[S0], P1
+      set I1, P0[S0]
+      eq I1, I0, OK1
+      print "not "
+OK1:  print "ok 1\n"
+
+      set N0, -1234.000000
+      set P1, N0
+      set P0[S0], P1
+      set N1, P0[S0]
+      eq N1, N0, OK2
+      print "not "
+OK2:  print "ok 2\n"
+
+      set S1, "abcdefghijklmnopq"
+      set P1, S1
+      set P0[S0], P1
+      set S2, P0[S0]
+      eq S2, S1, OK3
+      print "not "
+OK3:  print "ok 3\n"
+
+      end
+CODE
+ok 1
+ok 2
+ok 3
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Getting values from undefined keys");
+      new P2, .Match
+
+      set I0, P2["qwerty"]
+      set N0, P2["asdfgh"]
+      set S0, P2["zxcvbn"]
+      set P0, P2["123456"]
+
+      eq I0, 0, OK1
+      print "not "
+OK1:  print "ok 1\n"
+
+      eq N0, 0.0, OK2
+      print "not "
+OK2:  print "ok 2\n"
+
+      eq S0, "", OK3
+      print "not "
+OK3:  print "ok 3\n"
+
+      typeof S1, P0
+      eq S1, "PerlUndef", OK4
+      print "not "
+OK4:  print "ok 4\n"
+      end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+OUTPUT
+
+output_is(<<CODE, <<OUTPUT, "Setting & getting non-scalar PMCs");
+        new P0,.Match
+        new P1,.PerlArray
+        new P2,.PerlArray
+        set P1[4],"string"
+        set P0["one"],P1
+        set P2,P0["one"]
+        set S0,P2[4]
+        print S0
+        print "\\n"
+        end
+CODE
+string
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Testing clone");
+    new P0, .Match
+    set S0, "a"
+    set P0[S0], S0
+    new P2, .PerlArray
+    set P2, 2
+    set P0["b"], P2
+
+    # P0 = { a => "a", b => [undef, undef] }
+
+    clone P1, P0
+    set P0["c"], 4
+    set P3, P0["b"]
+    set P3, 3
+    set P0["b"], P3
+    set P1["a"], "A"
+
+    # P0 = { a => "a", b => [undef, undef, undef], c => 4 }
+    # P1 = { a => "A", b => [undef, undef] }
+
+    set S0, P0["a"]
+    eq S0, "a", ok1
+    print "not "
+ok1:
+    print "ok 1\n"
+
+    set P5, P0["b"]
+    set I0, P5
+    eq I0, 3, ok2
+    print "not "
+ok2:
+    print "ok 2\n"
+
+    set I0, P0["c"]
+    eq I0, 4, ok3
+    print "not "
+ok3:
+    print "ok 3\n"
+
+    set S0, P1["a"]
+    eq S0, "A", ok4
+    print "not "
+ok4:
+    print "ok 4\n"
+
+    set P5, P1["b"]
+    set I0, P5
+    eq I0, 2, ok5
+    print "not ("
+    print I0
+    print ") "
+ok5:
+    print "ok 5\n"
+
+# XXX: this should return undef or something, but it dies instead.
+#     set P3, P0["c"]
+#     unless P3, ok6
+#     print "not "
+# ok6:
+#     print "ok 6\n"
+     end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Compound keys");
+    new P0, .Match
+    new P1, .Match
+    new P2, .PerlArray
+    set P1["b"], "ab"
+    set P0["a"], P1
+    set S0, P0["a";"b"]
+    eq S0, "ab", ok1
+    print "not "
+ok1:
+    print "ok 1\n"
+    set P2[20], 77
+    set P1["n"], P2
+    set I0, P0["a";"n";20]
+    eq I0, 77, ok2
+    print "not "
+ok2:
+    print "ok 2\n"
+    set S0, "a"
+    set S1, "n"
+    set I0, 20
+    set I0, P0[S0;S1;I0]
+    eq I0, 77, ok3
+    print "not "
+ok3:
+    print "ok 3\n"
+    set P0["c"], P2
+    set P2[33], P1
+    set S0, P0["c";33;"b"]
+    eq S0, "ab", ok4
+    print "not "
+ok4:
+    print "ok 4\n"
+    set S0, "c"
+    set I1, 33
+    set S2, "b"
+    set S0, P0[S0;I1;S2]
+    eq S0, "ab", ok5
+    print "not "
+ok5:
+    print "ok 5\n"
+    set P1["b"], 47.11
+    set N0, P0["c";I1;S2]
+    eq N0, 47.11, ok6
+    print "not "
+ok6:
+    print "ok 6\n"
+    end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+ok 6
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Getting PMCs from compound keys");
+    new P0, .Match
+    new P1, .Match
+    new P2, .PerlInt
+    set P2, 12
+    set P1["b"], P2
+    set P0["a"], P1
+    set P3, P0["a";"b"]
+    print P3
+    print "\n"
+    end
+CODE
+12
+OUTPUT
+
+# A hash is only false if it has size 0
+
+output_is(<<'CODE', <<OUTPUT, "if (Match)");
+      new P0, .Match
+
+      if P0, BAD1
+      print "ok 1\n"
+      branch OK1
+BAD1: print "not ok 1\n"
+OK1:
+
+      set P0["key"], "value"
+      if P0, OK2
+      print "not "
+OK2:  print "ok 2\n"
+
+      set P0["key"], ""
+      if P0, OK3
+      print "not "
+OK3:  print "ok 3\n"
+
+      new P1, .PerlUndef
+      set P0["key"], P1
+      if P0, OK4
+      print "not "
+OK4:  print "ok 4\n"
+
+      end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "unless (Match)");
+      new P0, .Match
+
+      unless P0, OK1
+      print "not "
+OK1:  print "ok 1\n"
+
+      set P0["key"], "value"
+      unless P0, BAD2
+      print "ok 2\n"
+      branch OK2
+BAD2: print "not ok 2"
+OK2:
+
+      set P0["key"], "\0"
+      unless P0, BAD3
+      print "ok 3\n"
+      branch OK3
+BAD3: print "not ok 3"
+OK3:
+
+      new P1, .PerlUndef
+      set P0["key"], P1
+      unless P0, BAD4
+      print "ok 4\n"
+      branch OK4
+BAD4: print "not ok 4"
+OK4:
+
+      end
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "defined");
+    new P0, .Match
+    defined I0, P0
+    print I0
+    print "\n"
+    defined I0, P1
+    print I0
+    print "\n"
+    set P0["a"], 1
+    defined I0, P0["a"]
+    print I0
+    print "\n"
+    defined I0, P0["b"]
+    print I0
+    print "\n"
+    new P1, .PerlUndef
+    set P0["c"], P1
+    defined I0, P0["c"]
+    print I0
+    print "\n"
+    end
+
+CODE
+1
+0
+1
+0
+0
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "exists");
+    new P0, .Match
+    set P0["a"], 1
+    exists I0, P0["a"]
+    print I0
+    print "\n"
+    exists I0, P0["b"]
+    print I0
+    print "\n"
+    new P1, .PerlUndef
+    set P0["c"], P1
+    exists I0, P0["c"]
+    print I0
+    print "\n"
+    end
+
+CODE
+1
+0
+1
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "delete");
+    new P0, .Match
+    set P0["a"], 1
+    exists I0, P0["a"]
+    print I0
+    print "\n"
+    delete P0["a"]
+    exists I0, P0["a"]
+    print I0
+    print "\n"
+    end
+CODE
+1
+0
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Cloning keys");
+    new P10, .Match
+    new P1, .Key
+
+    set P1, "Bar"
+    set P10[P1], "Food\n"
+    clone P2, P1
+    set S0, P10[P2]
+    print S0
+
+    set S1, "Baa"
+    set P10[S1], "Sheep\n"
+    clone S2, S1
+    set S0, P10[S2]
+    print S0
+
+    end
+CODE
+Food
+Sheep
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "Cloning PMC vals");
+    new P10, .Match
+    new P1, .PerlUndef
+    set P1, "value\n"
+    set P10["str"], P1
+    new P1, .PerlUndef
+    set P1, 42
+    set P10["int"], P1
+    clone P2, P10
+    set P0, P2["int"]
+    print P0
+    set P0, P2["str"]
+    print P0
+    end
+CODE
+42value
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "entry types - type_keyed");
+.include "pmctypes.pasm"
+    new P1, .Match
+    new P2, .PerlInt
+    set P1["pmc"], P2
+    typeof I0, P1["pmc"]
+    eq I0, .PerlInt, ok4
+    print "not "
+ok4:print "ok 4\n"
+    end
+CODE
+ok 4
+OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "delete and free_list");
+    set I2, 10
+    set I1, 1
+    new P0, .SArray
+    set P0, 1
+    new P1, .Match
+outer:
+    set P0[0], I1
+    sprintf S0, "ok %vd\n", P0
+    set P1[S0], S0
+    set I0, 100
+lp:
+    set P1["key"], 1
+    delete P1["key"]
+    dec I0
+    if I0, lp
+
+    set S1, P1[S0]
+    print S1
+    inc I1
+    le I1, I2, outer
+    set I0, P1
+    print I0
+    print "\n"
+    end
+
+CODE
+ok 1
+ok 2
+ok 3
+ok 4
+ok 5
+ok 6
+ok 7
+ok 8
+ok 9
+ok 10
+10
+OUTPUT
+
+output_is(<<'CODE', '', "reusing the undef");
+    new P0, .Match
+    set P1, P0["no"]
+    print P1
+    set P1, "one"
+    set P2, P0["nada"]
+    print P2
+    end
+CODE
+
+output_is(<<'CODE', <<OUTPUT, "exists with constant string key");
+    new P16, .Match
+    set P16["key1"], "value for key1\n"
+    set S16, P16["key1"]
+    print S16
+    set I16, 777777777
+    print I16
+    print "\n"
+    exists I17, P16["key1"]
+    print I17
+    print "\n"
+    exists I17, P16["no such"]
+    print I17
+    print "\n"
+    end
+
+CODE
+value for key1
+777777777
+1
+0
+OUTPUT
+
+output_is(<< 'CODE', << 'OUTPUT', "Match in PIR");
+##PIR##
+.sub _main
+    .local pmc hash1
+    hash1 = new Match
+    hash1['X'] = 'U'
+    .local string val1
+    val1 = hash1['X']
+    print val1
+    print "\n"
+    end
+.end
+CODE
+U
+OUTPUT
+
+output_is(<< 'CODE', << 'OUTPUT', "Setting with compound keys");
+##PIR##
+.sub _main
+    .local pmc outer_hash
+    outer_hash = new Match
+    .local pmc inner_hash
+    inner_hash = new Match
+    .local pmc inner_array
+    inner_array = new PerlArray
+    .local string elem_string
+    .local int    elem_int
+    .local pmc    elem_pmc
+    .local num    elem_num
+
+    # setting and retrieving strings in an inner PerlArray
+    inner_array[128] = 'inner_array:128'
+    outer_hash['inner_array'] = inner_array
+    elem_string = outer_hash['inner_array';128]
+    print elem_string
+    print "\n" 
+    outer_hash['inner_array';128] = 'changed inner_array:128'
+    elem_string = outer_hash['inner_array';128]
+    print elem_string
+    print "\n" 
+
+    # setting and retrieving strings in an inner Match
+    inner_hash['129'] = 'inner_hash:129'
+    outer_hash['inner_hash'] = inner_hash
+    elem_string = outer_hash['inner_hash';'129']
+    print elem_string
+    print "\n" 
+    outer_hash['inner_hash';'129'] = 'changed inner_hash:129'
+    elem_string = outer_hash['inner_hash';'129']
+    print elem_string
+    print "\n" 
+
+    # setting and retrieving integer in an inner PerlArray
+    inner_array[130] = 130
+    outer_hash['inner_array'] = inner_array
+    elem_int = outer_hash['inner_array';130]
+    print elem_int
+    print "\n" 
+    outer_hash['inner_array';130] = -130
+    elem_int = outer_hash['inner_array';130]
+    print elem_int
+    print "\n" 
+
+    # setting and retrieving integer in an inner Match
+    inner_hash['131'] = 131
+    outer_hash['inner_hash'] = inner_hash
+    elem_int = outer_hash['inner_hash';'131']
+    print elem_int
+    print "\n" 
+    outer_hash['inner_hash';'131'] = -131
+    elem_int = outer_hash['inner_hash';'131']
+    print elem_int
+    print "\n" 
+
+    # setting and retrieving a PMC in an inner PerlArray
+    .local pmc in_pmc
+    in_pmc = new PerlString
+    in_pmc = 'inner_array:132'
+    inner_array[132] = in_pmc
+    outer_hash['inner_array'] = inner_array
+    elem_pmc = outer_hash['inner_array';132]
+    print elem_pmc
+    print "\n" 
+    in_pmc = 'changed inner_array:132'
+    outer_hash['inner_array';132] = in_pmc
+    elem_pmc = outer_hash['inner_array';132]
+    print elem_pmc
+    print "\n" 
+
+    # setting and retrieving a PMC in an inner Match
+    in_pmc = 'inner_array:133'
+    inner_hash['133'] = in_pmc
+    outer_hash['inner_hash'] = inner_hash
+    elem_string = outer_hash['inner_hash';'133']
+    print elem_string
+    print "\n" 
+    in_pmc = 'changed inner_hash:133'
+    outer_hash['inner_hash';'133'] = in_pmc
+    elem_string = outer_hash['inner_hash';'133']
+    print elem_string
+    print "\n" 
+
+    # setting and retrieving a float in an inner PerlArray
+    inner_array[134] = 134.134
+    outer_hash['inner_array'] = inner_array
+    elem_num = outer_hash['inner_array';134]
+    print elem_num
+    print "\n" 
+    outer_hash['inner_array';134] = -134.134
+    elem_num = outer_hash['inner_array';134]
+    print elem_num
+    print "\n" 
+
+    # setting and retrieving a float in an inner Match
+    inner_hash['135'] = 135.135
+    outer_hash['inner_hash'] = inner_hash
+    elem_num = outer_hash['inner_hash';'135']
+    print elem_num
+    print "\n" 
+    outer_hash['inner_hash';'135'] = -135.135
+    elem_num = outer_hash['inner_hash';'135']
+    print elem_num
+    print "\n" 
+
+    end
+.end
+CODE
+inner_array:128
+changed inner_array:128
+inner_hash:129
+changed inner_hash:129
+130
+-130
+131
+-131
+inner_array:132
+changed inner_array:132
+inner_array:133
+changed inner_hash:133
+134.134000
+-134.134000
+135.135000
+-135.135000
+OUTPUT
+
+output_is(<< 'CODE', << 'OUTPUT', "mutating the lookup string");
+    new P0, .Match
+    set P0["a"], "one"
+    set P0["ab"], "two"
+    set P0["abc"], "three"
+
+       set S0, "a"
+    set S1, P0[S0]
+       print S1
+       print "\n"
+
+       concat S0, "b"
+    set S1, P0[S0]
+       print S1
+       print "\n"
+
+       concat S0, "c"
+    set S1, P0[S0]
+       print S1
+       print "\n"
+
+       end
+CODE
+one
+two
+three
+OUTPUT
+
+output_is(<< 'CODE', << 'OUTPUT', "empty and full-string matches");
+    new P0, .Match
+    set P0["!INPUT"], "the full input string"
+
+    new P1, .MatchRange
+    set P1[0], 0
+    set P1[1], -1
+    set P0["empty_at_start"], P1
+
+    new P1, .MatchRange
+    set P1[0], 5
+    set P1[1], 4
+    set P0["empty_at_middle"], P1
+
+    new P1, .MatchRange
+    set P1[0], 0
+    set P1[1], 20
+    set P0["whole"], P1
+
+    new P1, .MatchRange
+    set P1[0], 4
+    set P1[1], 7
+    set P0["full"], P1
+
+    new P1, .MatchRange
+    set P1[0], -2
+    set P1[1], 7
+    set P0["no_start"], P1
+
+    new P1, .MatchRange
+    set P1[0], 3
+    set P1[1], -2
+    set P0["no_end"], P1
+
+    set P0["regular_key"], "boring old value"
+
+    new P1, .Match
+    set P1["subrule"], P0
+
+    set S0, "empty_at_start"
+    bsr test
+    set S0, "empty_at_middle"
+    bsr test
+    set S0, "whole"
+    bsr test
+    set S0, "full"
+    bsr test
+    set S0, "no_start"
+    bsr test
+    set S0, "no_end"
+    bsr test
+    set S0, "regular_key"
+    bsr test
+
+    set S0, "empty_at_start"
+    bsr subtest
+    set S0, "empty_at_middle"
+    bsr subtest
+    set S0, "whole"
+    bsr subtest
+    set S0, "full"
+    bsr subtest
+    set S0, "no_start"
+    bsr subtest
+    set S0, "no_end"
+    bsr subtest
+    set S0, "regular_key"
+    bsr subtest
+
+    print "Direct access to start,end for 'full': "
+    set I0, P0["full";0]
+    print I0
+    print ","
+    set I0, P0["full";1]
+    print I0
+    print "\n"
+
+    end
+
+test:
+    print S0
+    print ":"
+    set S0, P0[S0]
+    isnull S0, report_null
+    print S0
+    print "\n"
+    ret
+report_null:
+    print "<null>\n"
+    ret
+
+subtest:
+    print "subrule/"
+    print S0
+    print ":"
+    set S0, P1["subrule";S0]
+    isnull S0, report_null
+    print S0
+    print "\n"
+    ret
+subreport_null:
+    print "<null>\n"
+    ret
+CODE
+empty_at_start:
+empty_at_middle:
+whole:the full input string
+full:full
+no_start:<null>
+no_end:<null>
+regular_key:boring old value
+subrule/empty_at_start:
+subrule/empty_at_middle:
+subrule/whole:the full input string
+subrule/full:full
+subrule/no_start:<null>
+subrule/no_end:<null>
+subrule/regular_key:boring old value
+Direct access to start,end for 'full': 4,7
+OUTPUT
+
+1;

Reply via email to