2 Copyright (C) 2005-2010, Parrot Foundation.
7 src/pmc/namespace.pmc - NameSpace PMC
11 These are the vtable functions for the namespace PMC.
21 #include "pmc/pmc_sub.h"
23 /* HEADERIZER HFILE: none */
24 /* HEADERIZER BEGIN: static */
25 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
27 static void add_multi_to_namespace(PARROT_INTERP,
30 ARGIN_NULLOK(PMC *value))
31 __attribute__nonnull__(1)
32 __attribute__nonnull__(2)
33 __attribute__nonnull__(3);
35 static void add_native_to_namespace(PARROT_INTERP,
38 ARGIN_NULLOK(PMC *value))
39 __attribute__nonnull__(1)
40 __attribute__nonnull__(2)
41 __attribute__nonnull__(3);
43 static void add_to_class(PARROT_INTERP,
44 ARGMOD(Parrot_NameSpace_attributes *nsinfo),
45 ARGMOD_NULLOK(PMC *classobj),
48 __attribute__nonnull__(1)
49 __attribute__nonnull__(2)
50 __attribute__nonnull__(4)
51 __attribute__nonnull__(5)
52 FUNC_MODIFIES(*nsinfo)
53 FUNC_MODIFIES(*classobj);
55 PARROT_WARN_UNUSED_RESULT
56 static int maybe_add_sub_to_namespace(PARROT_INTERP,
60 __attribute__nonnull__(1)
61 __attribute__nonnull__(2)
62 __attribute__nonnull__(3)
63 __attribute__nonnull__(4);
65 PARROT_WARN_UNUSED_RESULT
66 static int ns_insert_sub_keyed_str(PARROT_INTERP,
70 __attribute__nonnull__(1)
71 __attribute__nonnull__(2)
72 __attribute__nonnull__(3)
73 __attribute__nonnull__(4);
75 #define ASSERT_ARGS_add_multi_to_namespace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
76 PARROT_ASSERT_ARG(interp) \
77 , PARROT_ASSERT_ARG(SELF) \
78 , PARROT_ASSERT_ARG(key))
79 #define ASSERT_ARGS_add_native_to_namespace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
80 PARROT_ASSERT_ARG(interp) \
81 , PARROT_ASSERT_ARG(SELF) \
82 , PARROT_ASSERT_ARG(key))
83 #define ASSERT_ARGS_add_to_class __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
84 PARROT_ASSERT_ARG(interp) \
85 , PARROT_ASSERT_ARG(nsinfo) \
86 , PARROT_ASSERT_ARG(key) \
87 , PARROT_ASSERT_ARG(value))
88 #define ASSERT_ARGS_maybe_add_sub_to_namespace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
89 PARROT_ASSERT_ARG(interp) \
90 , PARROT_ASSERT_ARG(SELF) \
91 , PARROT_ASSERT_ARG(key) \
92 , PARROT_ASSERT_ARG(value))
93 #define ASSERT_ARGS_ns_insert_sub_keyed_str __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
94 PARROT_ASSERT_ARG(interp) \
95 , PARROT_ASSERT_ARG(self) \
96 , PARROT_ASSERT_ARG(key) \
97 , PARROT_ASSERT_ARG(value))
98 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
99 /* HEADERIZER END: static */
103 =item C<static void add_to_class(PARROT_INTERP, Parrot_NameSpace_attributes
104 *nsinfo, PMC *classobj, STRING *key, PMC *value)>
111 add_to_class(PARROT_INTERP, ARGMOD(Parrot_NameSpace_attributes *nsinfo),
112 ARGMOD_NULLOK(PMC *classobj), ARGIN(STRING *key), ARGIN(PMC *value))
114 ASSERT_ARGS(add_to_class)
116 /* Insert it in class, if there is a class */
117 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
118 VTABLE_add_method(interp, classobj, key, value);
120 /* Otherwise, store it in the namespace for the class to
123 /* If we don't have a place to hang methods, make one. */
124 if (PMC_IS_NULL(nsinfo->methods))
125 nsinfo->methods = Parrot_pmc_new(interp, enum_class_Hash);
128 VTABLE_set_pmc_keyed_str(interp, nsinfo->methods, key, value);
134 =item C<static int ns_insert_sub_keyed_str(PARROT_INTERP, PMC *self, STRING
141 PARROT_WARN_UNUSED_RESULT
143 ns_insert_sub_keyed_str(PARROT_INTERP, ARGIN(PMC *self), ARGIN(STRING *key),
146 ASSERT_ARGS(ns_insert_sub_keyed_str)
148 Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(self);
149 PMC * vtable = nsinfo->vtable;
150 PMC * const classobj = VTABLE_get_class(interp, self);
151 STRING * vtable_key = STRINGNULL;
152 Parrot_Sub_attributes *sub;
155 PMC_get_sub(interp, value, sub);
157 if (sub->vtable_index != -1) {
158 /* Insert it in class, if there is a class */
159 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj)) {
160 const char * const vtable_key_c =
161 Parrot_get_vtable_name(interp, sub->vtable_index);
162 PARROT_ASSERT(vtable_key_c);
163 vtable_key = Parrot_str_new(interp, vtable_key_c,
164 strlen(vtable_key_c));
165 VTABLE_add_vtable_override(interp, classobj, vtable_key, value);
168 /* Otherwise, store it in the namespace for the class to
171 /* If we don't have a place to hang vtables, make one. */
172 if (PMC_IS_NULL(vtable))
173 nsinfo->vtable = vtable = Parrot_pmc_new(interp, enum_class_Hash);
176 VTABLE_set_pmc_keyed_int(interp, vtable, sub->vtable_index, value);
178 if (!(sub->comp_flags & SUB_COMP_FLAG_NSENTRY))
182 if (sub->comp_flags & SUB_COMP_FLAG_METHOD) {
183 STRING *method_name = key;
185 if (Parrot_str_equal(interp, sub->method_name, CONST_STRING(interp, ""))) {
186 if (sub->vtable_index != -1 && !STRING_IS_NULL(vtable_key)) {
187 method_name = vtable_key;
191 method_name = sub->method_name;
193 add_to_class(interp, nsinfo, classobj, method_name, value);
195 if (!(sub->comp_flags & SUB_COMP_FLAG_NSENTRY))
204 =item C<static int maybe_add_sub_to_namespace(PARROT_INTERP, PMC *SELF, STRING
211 PARROT_WARN_UNUSED_RESULT
213 maybe_add_sub_to_namespace(PARROT_INTERP, ARGIN(PMC *SELF), ARGIN(STRING *key),
216 ASSERT_ARGS(maybe_add_sub_to_namespace)
218 STRING * const sub_str = CONST_STRING(interp, "Sub");
220 if (!PMC_IS_NULL(value)
221 && VTABLE_isa(interp, value, sub_str)
222 && value->vtable->base_type != enum_class_Object)
223 return ns_insert_sub_keyed_str(interp, SELF, key, value);
230 =item C<static void add_nci_to_namespace(PARROT_INTERP, PMC *SELF, STRING *key,
238 add_native_to_namespace(PARROT_INTERP, ARGIN(PMC *SELF), ARGIN(STRING *key),
239 ARGIN_NULLOK(PMC *value))
241 ASSERT_ARGS(add_native_to_namespace)
243 if (!PMC_IS_NULL(value)
244 && (value->vtable->base_type == enum_class_NativePCCMethod ||
245 value->vtable->base_type == enum_class_NCI)) {
246 Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
247 PMC * const classobj = VTABLE_get_class(interp, SELF);
249 /* Insert it in class, if there is a class */
250 add_to_class(interp, nsinfo, classobj, key, value);
256 =item C<static void add_multi_to_namespace(PARROT_INTERP, PMC *SELF, STRING
264 add_multi_to_namespace(PARROT_INTERP, ARGIN(PMC *SELF), ARGIN(STRING *key),
265 ARGIN_NULLOK(PMC *value))
267 ASSERT_ARGS(add_multi_to_namespace)
269 STRING * const multi_str = CONST_STRING(interp, "MultiSub");
271 if (!PMC_IS_NULL(value)
272 && VTABLE_isa(interp, value, multi_str)) {
274 /* TT #10; work around that Sub doesn't use PMC ATTRs */
275 if (value->vtable->base_type != enum_class_Object
276 && VTABLE_elements(interp, value) > 0) {
277 Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
278 PMC * const classobj = VTABLE_get_class(interp, SELF);
280 /* Extract the first alternate and check if it is a method */
281 PMC * const pmc_sub = VTABLE_get_pmc_keyed_int(interp, value, 0);
282 Parrot_Sub_attributes *sub;
283 PMC_get_sub(interp, pmc_sub, sub);
285 if (sub->comp_flags & SUB_COMP_FLAG_METHOD) {
286 STRING * const empty_str = CONST_STRING(interp, "");
287 STRING *method_name = key;
290 if (Parrot_str_not_equal(interp, sub->method_name, empty_str))
291 method_name = sub->method_name;
293 add_to_class(interp, nsinfo, classobj, method_name, value);
295 GETATTR_NameSpace_hash(interp, SELF, hash);
297 parrot_hash_put(interp, hash,
298 hash_key_from_string(interp, hash, key),
299 hash_value_from_pmc(interp, hash, value));
307 * Typically a named slot contains either another namespace or a
308 * var/sub (not both).
309 * In case that the bucket->value is occupied, a FixedPMCArray is
310 * created, and the items are moved over to that extra storage.
311 * The array is flagged with FPA_is_ns_ext to distinguish it from a
312 * plain array variable.
314 * This could easily expand to a full-fledged typed namespace if needed.
319 NS_slot_var_sub, /* unspecified ~half-raw slot */
323 #define FPA_is_ns_ext PObj_private0_FLAG
325 pmclass NameSpace extends Hash provides hash no_ro auto_attrs {
327 ATTR STRING *name; /* Name of this namespace part. */
328 ATTR PMC *_class; /* The class or role attached to this namespace. */
329 ATTR PMC *methods; /* A Hash of methods, keyed on the method name. This
330 * goes away when the methods are sucked in by a
332 ATTR PMC *vtable; /* A Hash of vtable subs, keyed on the vtable index */
333 ATTR PMC *parent; /* This NameSpace's parent NameSpace */
339 Initialize a C<NameSpace> PMC.
346 PARROT_NAMESPACE(SELF)->vtable = PMCNULL;
347 PARROT_NAMESPACE(SELF)->methods = PMCNULL;
348 PARROT_NAMESPACE(SELF)->_class = PMCNULL;
349 SELF.set_pointer(parrot_new_hash(INTERP));
350 PObj_custom_mark_destroy_SETALL(SELF);
357 Marks the namespace as live.
363 Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
366 parrot_mark_hash(INTERP, nsinfo->hash);
368 Parrot_gc_mark_PMC_alive(INTERP, nsinfo->parent);
369 Parrot_gc_mark_PMC_alive(INTERP, nsinfo->_class);
370 Parrot_gc_mark_PMC_alive(INTERP, nsinfo->vtable);
371 Parrot_gc_mark_PMC_alive(INTERP, nsinfo->methods);
372 Parrot_gc_mark_STRING_alive(INTERP, nsinfo->name);
377 =item C<PMC *get_class()>
379 Returns the class or role PMC that is associated with this namespace.
386 return PARROT_NAMESPACE(SELF)->_class;
391 =item C<void set_pmc_keyed_str(STRING *key, PMC *value)>
393 Sets C<*value> as the namespace item for C<*key>. This is part of the
394 raw interface. If the PMC C<value> is exactly a NameSpace, C<SELF>
395 will be set as the parent of that namespace and the name C<key> of
396 C<value> is stored too.
398 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
400 If C<key> is a simple key, it works like above. If C<key> is an array
401 of strings or a chained key, add all components to the namespace.
403 =item C<PMC *get_pmc_keyed(PMC *key)>
405 Return the given namespace or PMCNULL. C<key> is either an array of
406 strings, or a possibly nested key.
408 =item C<PMC *get_pmc_keyed_str(STRING *key)>
410 Return the given namespace item or PMCNULL. If the named item is either
411 a NameSpace or a var, the NameSpace is returned.
413 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
415 Return a Sub representing an overridden vtable entry or PMCNULL. This is not
422 VTABLE void set_pmc_keyed_str(STRING *key, PMC *value) {
423 PMC *new_tuple = NULL;
424 const int val_is_NS = PMC_IS_NULL(value)
426 :value->vtable->base_type == enum_class_NameSpace;
428 /* don't need this everywhere yet */
431 /* If it's a sub... */
432 if (maybe_add_sub_to_namespace(INTERP, SELF, key, value))
435 /* If it's an native method */
436 add_native_to_namespace(INTERP, SELF, key, value);
438 /* If it's a multi-sub and the first in this NS... */
439 add_multi_to_namespace(INTERP, SELF, key, value);
441 old = (PMC *)parrot_hash_get(INTERP, (Hash *)SELF.get_pointer(), key);
446 if ((old->vtable->base_type == enum_class_NameSpace) == val_is_NS) {
447 /* simple ns or simple var/sub changed */
450 else if ((PObj_get_FLAGS(old) & FPA_is_ns_ext) &&
451 old->vtable->base_type == enum_class_FixedPMCArray) {
452 /* we have a tuple extension already */
453 VTABLE_set_pmc_keyed_int(INTERP, old,
454 val_is_NS ? NS_slot_ns : NS_slot_var_sub,
458 /* create new tuple */
459 /* for a fully typed namespace, we'd need 3 or 4 */
460 new_tuple = Parrot_pmc_new_init_int(INTERP,
461 enum_class_FixedPMCArray, NS_max_slots);
463 /* flag it as special */
464 PObj_get_FLAGS(new_tuple) |= FPA_is_ns_ext;
469 /* TODO - this hack needs to go */
470 Parrot_NameSpace_attributes *nsinfo = PARROT_NAMESPACE(value);
471 nsinfo->parent = SELF; /* set parent */
472 nsinfo->name = key; /* and name */
475 VTABLE_set_pmc_keyed_int(INTERP, new_tuple, NS_slot_ns, value);
476 VTABLE_set_pmc_keyed_int(INTERP, new_tuple, NS_slot_var_sub,
479 parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), key, new_tuple);
480 /* distinction from a plain FPA, which doesn't extend the
481 * namespace storage */
484 else if (new_tuple) {
485 VTABLE_set_pmc_keyed_int(INTERP, new_tuple, NS_slot_ns, old);
486 VTABLE_set_pmc_keyed_int(INTERP, new_tuple, NS_slot_var_sub, value);
487 parrot_hash_put(INTERP, (Hash *)SELF.get_pointer(), key, new_tuple);
491 VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
494 if (key->vtable->base_type == enum_class_String) {
495 SELF.set_pmc_keyed_str(VTABLE_get_string(INTERP, key), value);
499 if (key->vtable->base_type == enum_class_Key) {
501 STRING * const part = VTABLE_get_string(INTERP, key);
502 key = VTABLE_shift_pmc(INTERP, key);
505 Parrot_ns_set_global(INTERP, ns, part, value);
509 ns = Parrot_ns_make_namespace_keyed_str(INTERP, ns, part);
513 if (key->vtable->base_type == enum_class_ResizableStringArray) {
514 const INTVAL elements = VTABLE_elements(INTERP, key);
516 for (i = 0; i < elements; ++i) {
517 STRING * const part = VTABLE_get_string_keyed_int(INTERP, key, i);
519 if ((i + 1) >= elements) { /* Last entry in the array */
520 Parrot_ns_set_global(INTERP, ns, part, value);
524 ns = Parrot_ns_make_namespace_keyed_str(INTERP, ns, part);
528 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_GLOBAL_NOT_FOUND,
529 "Invalid namespace key in set_pmc_keyed");
532 VTABLE PMC *get_pmc_keyed_str(STRING *key) {
533 Hash * const hash = (Hash *)SELF.get_pointer();
534 PMC *ns = (PMC *)parrot_hash_get(INTERP, hash, key);
539 if ((PObj_get_FLAGS(ns) & FPA_is_ns_ext) &&
540 ns->vtable->base_type == enum_class_FixedPMCArray)
541 ns = VTABLE_get_pmc_keyed_int(INTERP, ns, NS_slot_ns);
546 VTABLE PMC *get_pmc_keyed(PMC *key) {
547 PMC *ns = SUPER(key);
548 /* Is this equivalent?
549 PMC *ns = INTERP->vtables[enum_class_Hash]->get_pmc_keyed(INTERP, SELF, key);
552 if (!PMC_IS_NULL(ns))
557 if (key->vtable->base_type == enum_class_Key) {
558 STRING * const part = VTABLE_get_string(INTERP, key);
559 key = VTABLE_shift_pmc(INTERP, key);
562 return VTABLE_get_pmc_keyed_str(INTERP, ns, part);
564 ns = Parrot_ns_get_namespace_keyed_str(INTERP, ns, part);
569 return VTABLE_get_pmc_keyed(INTERP, ns, key);
571 else if (VTABLE_does(INTERP, key, CONST_STRING(INTERP, "array"))) {
573 while (!PMC_IS_NULL(ns) && VTABLE_elements(INTERP, key)) {
574 STRING * const name = VTABLE_get_string_keyed_int(INTERP, key, i);
575 if (STRING_IS_NULL(name)) {
577 /* What to do here? Throw an exception or something? */
580 ns = Parrot_ns_get_namespace_keyed_str(INTERP, ns, name);
586 STRING * const name = VTABLE_get_string(INTERP, key);
587 ns = Parrot_ns_get_namespace_keyed_str(INTERP, ns, name);
590 /* If we get the wrong type, should we throw an exception?
591 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_GLOBAL_NOT_FOUND,
592 "Invalid namespace key in get_pmc_keyed_str");
596 VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
597 Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
598 PMC * const vtable = nsinfo->vtable;
600 if (PMC_IS_NULL(vtable))
603 return VTABLE_get_pmc_keyed_int(INTERP, vtable, key);
608 =item C<void *get_pointer_keyed_str(STRING *key)>
610 =item C<void *get_pointer_keyed(PMC *key)>
612 Return the given namespace item or PMCNULL. If the named item is either
613 a NameSpace or a var, the var is returned.
616 TOTAL KLUDGE. ON THE CHOPPING BLOCK.
622 VTABLE void *get_pointer_keyed_str(STRING *key) {
623 PMC *ns = (PMC *)parrot_hash_get(INTERP, (Hash *)SELF.get_pointer(), key);
625 /* Be extra careful about returning PMCNULL */
626 if (! PMC_IS_NULL(ns)) {
627 if ((PObj_get_FLAGS(ns) & FPA_is_ns_ext) &&
628 ns->vtable->base_type == enum_class_FixedPMCArray)
629 ns = VTABLE_get_pmc_keyed_int(INTERP, ns, NS_slot_var_sub);
636 VTABLE void *get_pointer_keyed(PMC *key) {
639 if (PMC_IS_NULL(key))
642 switch (key->vtable->base_type) {
643 case enum_class_String:
644 return SELF.get_pointer_keyed_str(VTABLE_get_string(INTERP, key));
645 case enum_class_Key: {
646 /* this loop (and function) could use a rewrite for clarity */
648 STRING * const part = VTABLE_get_string(INTERP, key);
649 key = VTABLE_shift_pmc(INTERP, key);
652 return VTABLE_get_pointer_keyed_str(INTERP, ns, part);
654 ns = Parrot_ns_get_namespace_keyed_str(INTERP, ns, part);
660 case enum_class_ResizableStringArray: {
661 const INTVAL elements = VTABLE_elements(INTERP, key);
663 for (i = 0; i < elements; ++i) {
664 STRING * const part = VTABLE_get_string_keyed_int(INTERP, key, i);
666 /* Last entry in the array */
667 if ((i + 1) >= elements)
668 return VTABLE_get_pointer_keyed_str(INTERP, ns, part);
670 ns = Parrot_ns_get_namespace_keyed_str(INTERP, ns, part);
678 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_GLOBAL_NOT_FOUND,
679 "Invalid namespace key of type '%S' in get_pointer_keyed",
680 key->vtable->whoami);
686 =item C<STRING *get_string()>
688 Return the name of this namespace part.
694 VTABLE STRING *get_string() {
695 const Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
701 =item C<PMC *inspect_str(STRING *what)>
703 Provides introspection of a specific piece of information about the
704 namespace. The available information is:
710 The class object associated with the namespace, if any.
714 A temporary cache of methods (destroyed when class object is created).
715 Hash keyed on method name, value is an invokable PMC. Includes methods
716 composed in from roles.
718 =item vtable_overrides
720 A temporary cache of vtable overrides (destroyed when class object is
721 created). Hash keyed on vtable name, value is an invokable PMC.
722 Includes vtable overrides composed in from roles.
730 VTABLE PMC *inspect_str(STRING *what) {
731 const Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
734 if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "methods"))) {
735 found = nsinfo->methods;
737 else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "vtable_overrides"))) {
738 found = nsinfo->vtable;
740 else if (Parrot_str_equal(INTERP, what, CONST_STRING(INTERP, "class"))) {
741 found = nsinfo->_class;
744 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
745 "Unknown introspection value '%S'", what);
747 /* return found value */
748 if (PMC_IS_NULL(found))
768 =item C<METHOD make_namespace(PMC* key)>
770 Create and retrieve the namespace given by C<key>. If the namespace
771 already exists, only retrieve it.
777 METHOD make_namespace(PMC *key) {
778 PMC *ns = Parrot_ns_get_namespace_keyed(INTERP, SELF, key);
779 if (PMC_IS_NULL(ns)) {
780 ns = Parrot_ns_make_namespace_keyed(INTERP, SELF, key);
787 =item C<METHOD add_namespace(STRING *name, PMC *namespace)>
789 Stores the given namespace under this namespace, with the given name. Throws
790 an invalid type exception if C<namespace> is not a NameSpace PMC or subclass.
796 METHOD add_namespace(STRING *name, PMC *_namespace) {
797 STRING * const s_ns = CONST_STRING(INTERP, "NameSpace");
799 if (!VTABLE_isa(INTERP, _namespace, s_ns))
800 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
801 "Invalid type %d in add_namespace()",
802 _namespace->vtable->base_type);
804 VTABLE_set_pmc_keyed_str(INTERP, SELF, name, _namespace);
809 =item C<METHOD add_sub(STRING *name, PMC *sub)>
811 Stores the given sub under this namespace, with the given name. Throws an
812 invalid type exception if C<sub> is not a Sub PMC or subclass.
818 METHOD add_sub(STRING *name, PMC *sub) {
819 STRING * const s_sub = CONST_STRING(INTERP, "Sub");
820 STRING * const s_multisub = CONST_STRING(INTERP, "MultiSub");
822 if (!VTABLE_isa(INTERP, sub, s_sub)
823 && !VTABLE_isa(INTERP, sub, s_multisub))
824 Parrot_ex_throw_from_c_args(INTERP, NULL,
825 EXCEPTION_INVALID_OPERATION,
826 "Invalid type %d in add_sub()", sub->vtable->base_type);
828 VTABLE_set_pmc_keyed_str(INTERP, SELF, name, sub);
833 =item C<METHOD add_var(STRING *name, PMC *var)>
835 Stores the given variable under this namespace, with the given name.
841 METHOD add_var(STRING *name, PMC *var) {
842 VTABLE_set_pmc_keyed_str(INTERP, SELF, name, var);
847 =item C<METHOD get_name()>
849 Returns the name of the namespace as an array of strings.
851 $P2 = $P3.'get_name'()
852 $S0 = join '::', $P2 # '::Foo::Bar'
859 PMC * const ar = Parrot_pmc_new(INTERP, enum_class_ResizableStringArray);
864 Parrot_NameSpace_attributes *nsinfo = PARROT_NAMESPACE(ns);
865 VTABLE_unshift_string(INTERP, ar, nsinfo->name);
870 /* remove the NULL string of the namespace root */
872 VTABLE_shift_string(INTERP, ar);
878 =item C<METHOD find_namespace(STRING *name)>
880 Return the namespace with the given name.
886 METHOD find_namespace(STRING *key) {
887 STRING * const s_ns = CONST_STRING(INTERP, "NameSpace");
888 PMC * const ns = (PMC *)parrot_hash_get(INTERP, (Hash *)SELF.get_pointer(),
892 RETURN(PMC *PMCNULL);
894 /* it's a NameSpace */
895 if (VTABLE_isa(INTERP, ns, s_ns))
898 RETURN(PMC *PMCNULL);
903 =item C<METHOD find_sub(STRING *name)>
905 Return the Sub PMC with the given name.
911 METHOD find_sub(STRING *key) {
912 STRING * const s_sub = CONST_STRING(INTERP, "Sub");
913 PMC * const sub = (PMC *)parrot_hash_get(INTERP, (Hash *)SELF.get_pointer(),
917 RETURN(PMC *PMCNULL);
920 if (VTABLE_isa(INTERP, sub, s_sub))
923 RETURN(PMC *PMCNULL);
928 =item C<METHOD find_var(STRING *name)>
930 Return the PMC with the given name.
936 METHOD find_var(STRING *key) {
937 PMC * const val = (PMC *)parrot_hash_get(INTERP, (Hash *)SELF.get_pointer(), key);
940 RETURN(PMC *PMCNULL);
947 =item C<METHOD del_namespace(STRING *name)>
949 Deletes the contained NameSpace PMC with the given name. Throws an invalid
950 type exception if the item to delete is not a NameSpace PMC or subclass, and
951 does not delete the PMC.
957 METHOD del_namespace(STRING *name) {
958 Hash * const hash = (Hash *)SELF.get_pointer();
959 PMC * const ns = (PMC *)parrot_hash_get(INTERP, hash, name);
960 STRING * const s_ns = CONST_STRING(INTERP, "NameSpace");
965 if (!VTABLE_isa(INTERP, ns, s_ns))
966 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
967 "Invalid type %d for '%Ss' in del_namespace()",
968 ns->vtable->base_type, name);
970 parrot_hash_delete(INTERP, hash, name);
975 =item C<METHOD del_sub(STRING *name)>
977 Deletes the contained Sub PMC with the given name. Throws an invalid type
978 exception if the item to delete is not a Sub PMC or subclass, and does not
985 METHOD del_sub(STRING *name) {
986 Hash * const hash = (Hash *)SELF.get_pointer();
987 PMC * const sub = (PMC *)parrot_hash_get(INTERP, hash, name);
988 STRING * const s_sub = CONST_STRING(INTERP, "Sub");
990 if (PMC_IS_NULL(sub))
993 if (!VTABLE_isa(INTERP, sub, s_sub))
994 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
995 "Invalid type %d for '%Ss' in del_sub()",
996 sub->vtable->base_type, name);
998 parrot_hash_delete(INTERP, hash, name);
1003 =item C<METHOD del_var(STRING *name)>
1005 Deletes the contained variable-like PMC with the given name.
1011 METHOD del_var(STRING *name) {
1012 parrot_hash_delete(INTERP, (Hash *)SELF.get_pointer(), name);
1017 =item C<METHOD get_sym(STRING *name)>
1019 Return the symbol (var or sub) with the given name. This can be used
1020 to retrieve symbols, if a NameSpace with the same name exists.
1026 METHOD get_sym(STRING *key) {
1027 PMC *ns = (PMC *)parrot_hash_get(INTERP, (Hash *)SELF.get_pointer(), key);
1030 RETURN(PMC *PMCNULL);
1032 /* it's a NameSpace */
1033 if (ns->vtable == SELF->vtable)
1034 RETURN(PMC *PMCNULL);
1036 if ((PObj_get_FLAGS(ns) & FPA_is_ns_ext)
1037 && ns->vtable->base_type == enum_class_FixedPMCArray)
1038 ns = VTABLE_get_pmc_keyed_int(INTERP, ns, NS_slot_var_sub);
1045 =item C<METHOD export_to(PMC *dest, PMC *what)>
1047 Export items from this NameSpace into the C<dest> NameSpace. The items to
1048 export are named in C<what>, which may be an array of strings, a hash, or null.
1049 If C<what> is an array of strings, interpretation of items in an array follows
1050 the conventions of the source (exporting) namespace.
1051 If C<what> is a hash, the keys correspond to the names in the source namespace,
1052 and the values correspond to the names in the destination namespace.
1053 if a hash value is null or an empty string, the name in the hash key is used.
1054 A null C<what> requests the 'default' set of items.
1055 Any other type passed in C<what> throws an exception.
1057 NOTE: exporting 'default' set of items is not yet implemented.
1063 METHOD export_to(PMC *dest, PMC *what) {
1064 STRING * const s_hash = CONST_STRING(INTERP, "hash");
1065 STRING * const s_array = CONST_STRING(INTERP, "array");
1067 if (PMC_IS_NULL(dest))
1068 Parrot_ex_throw_from_c_args(INTERP, NULL, 0,
1069 "destination namespace not specified");
1071 if (PMC_IS_NULL(what) || !VTABLE_elements(INTERP, what))
1072 Parrot_ex_throw_from_c_args(INTERP, NULL, 0,
1073 "exporting default object set not yet implemented");
1075 /* if "what" does "hash", we extract string key/value pairs,
1076 * lookup the object with the name specified in the key,
1077 * and export it with the name specified as value. */
1078 if (VTABLE_does(INTERP, what, s_hash)) {
1079 PMC * const iter = VTABLE_get_iter(INTERP, what);
1080 const INTVAL n = VTABLE_elements(INTERP, what);
1083 for (i = 0; i < n; ++i) {
1086 STRING * const src_name = VTABLE_shift_string(INTERP, iter);
1088 if (STRING_IS_NULL(src_name) || STRING_IS_EMPTY(src_name))
1089 Parrot_ex_throw_from_c_args(INTERP, NULL, 0,
1090 "source object name not specified");
1092 if (PMC_IS_NULL(VTABLE_get_pmc_keyed_str(INTERP, what, src_name))) {
1093 dest_name = src_name;
1096 dest_name = VTABLE_get_string_keyed_str(INTERP, what, src_name);
1097 if (STRING_IS_NULL(dest_name) || STRING_IS_EMPTY(dest_name))
1098 dest_name = src_name;
1101 object = VTABLE_get_pmc_keyed_str(INTERP, SELF, src_name);
1103 if (PMC_IS_NULL(object))
1104 Parrot_ex_throw_from_c_args(INTERP, NULL, 0,
1105 "object '%Ss' not found in current namespace", src_name);
1107 VTABLE_set_pmc_keyed_str(INTERP, dest, dest_name, object);
1110 else if (VTABLE_does(INTERP, what, s_array)) {
1111 const INTVAL n = VTABLE_elements(INTERP, what);
1114 for (i = 0; i < n; ++i) {
1116 STRING * const name = VTABLE_get_string_keyed_int(INTERP, what, i);
1118 if (STRING_IS_NULL(name) || STRING_IS_EMPTY(name))
1119 Parrot_ex_throw_from_c_args(INTERP, NULL, 0,
1120 "object name not specified");
1122 object = VTABLE_get_pmc_keyed_str(INTERP, SELF, name);
1124 if (PMC_IS_NULL(object))
1125 Parrot_ex_throw_from_c_args(INTERP, NULL, 0,
1126 "object '%Ss' not found in current namespace", name);
1128 VTABLE_set_pmc_keyed_str(INTERP, dest, name, object);
1132 Parrot_ex_throw_from_c_args(INTERP, NULL, 0,
1133 "can't handle argument of type %s", what->vtable->base_type);
1138 =item C<METHOD get_parent()>
1140 Return the parent NameSpace or PMCNULL, if none.
1146 METHOD get_parent() {
1147 PMC *parent = PARROT_NAMESPACE(SELF)->parent ? PARROT_NAMESPACE(SELF)->parent : PMCNULL;
1148 RETURN(PMC *parent);
1153 =item C<METHOD get_class()>
1155 Returns the class or role PMC that is associated with this namespace.
1161 METHOD get_class() {
1162 Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
1163 PMC *ret_class = nsinfo->_class;
1165 if (PMC_IS_NULL(ret_class))
1166 ret_class = PMCNULL;
1168 RETURN(PMC *ret_class);
1173 =item C<METHOD set_class(PMC *class_or_role)>
1175 Sets the class or role PMC that is associated with this namespace.
1181 METHOD set_class(PMC *class_or_role) {
1182 PARROT_NAMESPACE(SELF)->_class = class_or_role;
1187 =item C<METHOD get_associated_methods()>
1189 Gets the Hash of methods associated with this namespace and removes it from
1196 METHOD get_associated_methods() {
1197 Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
1198 PMC * const ret_methods = nsinfo->methods;
1200 nsinfo->methods = PMCNULL;
1202 RETURN(PMC *ret_methods);
1207 =item C<METHOD get_associated_vtable_methods()>
1209 Gets the Hash of vtables associated with this namespace and removes it
1216 METHOD get_associated_vtable_methods() {
1217 Parrot_NameSpace_attributes * const nsinfo = PARROT_NAMESPACE(SELF);
1218 PMC * const ret_methods = nsinfo->vtable;
1220 nsinfo->vtable = PMCNULL;
1222 RETURN(PMC *ret_methods);
1233 F<docs/pdds/pdd21_namespaces.pod>
1241 * c-file-style: "parrot"
1243 * vim: expandtab shiftwidth=4: