Author: leo
Date: Wed Mar  8 07:52:15 2006
New Revision: 11824

Modified:
   trunk/src/ops/experimental.ops
   trunk/src/pmc/namespace.pmc
   trunk/t/pmc/namespace.t

Log:
Namespaces 11 - get_namespace Px, Py

* implement get_namespace opcode variants
* test


Modified: trunk/src/ops/experimental.ops
==============================================================================
--- trunk/src/ops/experimental.ops      (original)
+++ trunk/src/ops/experimental.ops      Wed Mar  8 07:52:15 2006
@@ -238,7 +238,8 @@
 
 =item B<get_namespace>(out PMC, in KEY)
 
-Get the specified currrent namespace.
+Get the specified namespace. $2 is either an array of names or a key.
+If the namespace doesn't exist, $1 is set to PMCNULL.
 
 =item B<find_global>(out PMC, in KEY, in STR)
 
@@ -253,6 +254,18 @@
     goto NEXT();
 }
 
+op get_namespace(out PMC, in PMC) {
+    PMC *ns_root = interpreter->stash_hash;
+    $1 = VTABLE_get_pmc_keyed(interpreter, ns_root, $2);
+    goto NEXT();
+}
+
+op get_namespace(out PMC, in KEY) {
+    PMC *ns_root = interpreter->stash_hash;
+    $1 = VTABLE_get_pmc_keyed(interpreter, ns_root, $2);
+    goto NEXT();
+}
+
 op find_global(out PMC, in KEY, in STR) {
     $1 = Parrot_find_global_p(interpreter, $2, $3);
     goto NEXT();

Modified: trunk/src/pmc/namespace.pmc
==============================================================================
--- trunk/src/pmc/namespace.pmc (original)
+++ trunk/src/pmc/namespace.pmc Wed Mar  8 07:52:15 2006
@@ -61,6 +61,11 @@
 If C<key> is a simple key, it works like above. If C<key> is an array
 of strings or a chained key, add all components to the namespace.
 
+=item C<PMC* get_pmc_keyed(PMC *key)> 
+
+Return the given namespace or PMCNULL. C<key> is either an array of 
+strings, or a possibly nested key.
+
 =cut
 
 */
@@ -84,6 +89,40 @@
         }
     }
 
+    /* XXX Hash would return Undef, which is probably wrong */
+    PMC* get_pmc_keyed_str (STRING* key) {
+        HashBucket *b = hash_get_bucket(INTERP, 
+                (Hash*) PMC_struct_val(SELF), key);
+        return b->value;
+    }
+    
+    PMC* get_pmc_keyed(PMC *key) {
+        PMC *ns = SELF;
+        STRING *part;
+        INTVAL i, n;
+        
+        if (key->vtable->base_type == enum_class_Key) {
+            while (key) {
+                part = key_string(INTERP, key);
+                ns = VTABLE_get_pmc_keyed_str(INTERP, ns, part);
+                if (!ns)
+                    return PMCNULL;
+                key = key_next(INTERP, key);
+            }
+            return ns;
+        }
+        n = VTABLE_elements(INTERP, key);
+        if (!n)
+            return PMCNULL;
+        for (i = 0; i < n; ++i) {
+            part = VTABLE_get_string_keyed_int(INTERP, key, i);
+            ns = VTABLE_get_pmc_keyed_str(INTERP, ns, part);
+            if (!ns)
+                return PMCNULL;
+        }
+        return ns;
+    }
+
 /*
 
 =item C<STRING* get_string()>

Modified: trunk/t/pmc/namespace.t
==============================================================================
--- trunk/t/pmc/namespace.t     (original)
+++ trunk/t/pmc/namespace.t     Wed Mar  8 07:52:15 2006
@@ -6,7 +6,7 @@
 use warnings;
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
-use Parrot::Test tests => 20;
+use Parrot::Test tests => 21;
 
 =head1 NAME
 
@@ -430,3 +430,42 @@
 3
 ::parrot::Foo
 OUTPUT
+
+pir_output_is(<<'CODE', <<'OUTPUT', "get_namespace_p_p, getnamespace_p_kc");
+.sub main :main
+    .include "interpinfo.pasm"
+    $P0 = interpinfo .INTERPINFO_NAMESPACE_ROOT
+    $P1 = $P0["parrot"]
+    $P3 = new .NameSpace
+    $P1["Foo"] = $P3
+    # fetch w array
+    $P1 = new .FixedStringArray
+    $P1 = 2
+    $P1[0] = 'parrot'
+    $P1[1] = 'Foo'
+    $P2 = get_namespace $P1
+    $P2 = $P2.'name'()
+    $I2 = elements $P2
+    print $I2
+    print "\n"
+    $S0 = join '::', $P2
+    print $S0
+    print "\n"
+    # fetch w key
+    $P2 = get_namespace ["parrot";"Foo"]
+    $P2 = $P2.'name'()
+    $I2 = elements $P2
+    print $I2
+    print "\n"
+    $S0 = join '::', $P2
+    print $S0
+    print "\n"
+.end
+# namespace root doesnt have a name
+# XXX should the root namespace be included?
+CODE
+3
+::parrot::Foo
+3
+::parrot::Foo
+OUTPUT

Reply via email to