2 Copyright (C) 2004-2008, The Perl Foundation.
7 src/global.c - Access to global PMCs
19 #include "parrot/parrot.h"
22 /* HEADERIZER HFILE: include/parrot/global.h */
23 /* HEADERIZER BEGIN: static */
24 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
26 PARROT_WARN_UNUSED_RESULT
27 PARROT_CAN_RETURN_NULL
28 static PMC
* get_namespace_pmc(PARROT_INTERP
, ARGIN(PMC
*sub
))
29 __attribute__nonnull__(1)
30 __attribute__nonnull__(2);
32 PARROT_WARN_UNUSED_RESULT
33 PARROT_CAN_RETURN_NULL
34 static PMC
* internal_ns_keyed(PARROT_INTERP
,
36 ARGIN_NULLOK(PMC
*pmc_key
),
37 ARGIN_NULLOK(STRING
*str_key
),
39 __attribute__nonnull__(1)
40 __attribute__nonnull__(2);
42 static void store_sub_in_multi(PARROT_INTERP
,
45 __attribute__nonnull__(1)
46 __attribute__nonnull__(2)
47 __attribute__nonnull__(3);
49 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
50 /* HEADERIZER END: static */
52 #define DEBUG_GLOBAL 0
54 /* flags for internal_ns_keyed */
55 #define INTERN_NS_CREAT 1 /* I'm a fan of the classics */
59 =item C<static PMC * internal_ns_keyed>
61 internal_ns_keyed: Internal function to do keyed namespace lookup
62 relative to a given namespace PMC. Understands STRINGs, String PMCs,
63 Key pmcs, and array PMCs containing strings.
69 PARROT_WARN_UNUSED_RESULT
70 PARROT_CAN_RETURN_NULL
72 internal_ns_keyed(PARROT_INTERP
, ARGIN(PMC
*base_ns
), ARGIN_NULLOK(PMC
*pmc_key
),
73 ARGIN_NULLOK(STRING
*str_key
), int flags
)
77 static const INTVAL max_intval
= (INTVAL
)((~(UINTVAL
)0) >> 1); /*2s comp*/
83 else if (pmc_key
->vtable
->base_type
== enum_class_String
) {
84 str_key
= VTABLE_get_string(interp
, pmc_key
);
87 else if (pmc_key
->vtable
->base_type
== enum_class_Key
)
88 n
= max_intval
; /* we don't yet know how big the key is */
90 n
= VTABLE_elements(interp
, pmc_key
); /* array of strings */
92 for (i
= 0; i
< n
; ++i
) {
97 else if (n
== max_intval
) {
99 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
100 "Trying to use a NULL PMC as a key");
102 part
= VTABLE_get_string(interp
, pmc_key
);
103 pmc_key
= key_next(interp
, pmc_key
);
106 n
= i
+ 1; /* now we know how big the key is */
110 Parrot_ex_throw_from_c_args(interp
, NULL
, 1,
111 "Passed a NULL pmc_key into VTABLE_get_string_keyed_int");
113 part
= VTABLE_get_string_keyed_int(interp
, pmc_key
, i
);
116 sub_ns
= VTABLE_get_pmc_keyed_str(interp
, ns
, part
);
118 if (PMC_IS_NULL(sub_ns
)
119 /* RT#46157 - stop depending on typed namespace */
120 || sub_ns
->vtable
->base_type
!= enum_class_NameSpace
)
122 if (!(flags
& INTERN_NS_CREAT
))
125 /* RT#46159 - match HLL of enclosing namespace? */
126 sub_ns
= pmc_new(interp
,
127 Parrot_get_ctx_HLL_type(interp
,
128 enum_class_NameSpace
));
129 if (PMC_IS_NULL(sub_ns
))
131 VTABLE_set_pmc_keyed_str(interp
, ns
, part
, sub_ns
);
141 =item C<PMC * Parrot_get_namespace_keyed>
143 Find the namespace relative to the namespace C<base_ns> with the key
144 C<pmc_key>, which may be a String, a Key, or an array of strings. Return
145 the namespace, or NULL if not found.
152 PARROT_WARN_UNUSED_RESULT
153 PARROT_CAN_RETURN_NULL
155 Parrot_get_namespace_keyed(PARROT_INTERP
, ARGIN(PMC
*base_ns
), ARGIN_NULLOK(PMC
*pmc_key
))
157 return internal_ns_keyed(interp
, base_ns
, pmc_key
, NULL
, 0);
162 =item C<PMC * Parrot_get_namespace_keyed_str>
164 Find the namespace relative to the namespace C<base_ns> with the string key
165 C<str_key>. Return the namespace, or NULL if not found.
172 PARROT_WARN_UNUSED_RESULT
173 PARROT_CAN_RETURN_NULL
175 Parrot_get_namespace_keyed_str(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
176 ARGIN_NULLOK(STRING
*str_key
))
178 return internal_ns_keyed(interp
, base_ns
, PMCNULL
, str_key
, 0);
183 =item C<PMC * Parrot_make_namespace_keyed>
185 Find, or create if necessary, the namespace relative to the namespace
186 C<base_ns> with the key C<pmc_key>, which may be a String, a Key, or an
187 array of strings. Return the namespace. Errors will result in exceptions.
194 PARROT_WARN_UNUSED_RESULT
195 PARROT_CAN_RETURN_NULL
197 Parrot_make_namespace_keyed(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
198 ARGIN_NULLOK(PMC
*pmc_key
))
200 return internal_ns_keyed(interp
, base_ns
, pmc_key
, NULL
, INTERN_NS_CREAT
);
205 =item C<PMC * Parrot_make_namespace_keyed_str>
207 Find, or create if necessary, the namespace relative to the namespace
208 C<base_ns> with the string key C<str_key>. Return the namespace. Errors
209 will result in exceptions.
216 PARROT_WARN_UNUSED_RESULT
217 PARROT_CAN_RETURN_NULL
219 Parrot_make_namespace_keyed_str(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
220 ARGIN_NULLOK(STRING
*str_key
))
222 return internal_ns_keyed(interp
, base_ns
, NULL
, str_key
, INTERN_NS_CREAT
);
228 =item C<PMC * Parrot_make_namespace_autobase>
230 Find, or create if necessary, a namespace with the key C<key>, which may be a
231 String, a Key, or an array of strings. If it is a String, then the lookup is
232 relative to the current namespace. Otherwise, it is relative to the current HLL
233 root namespace. Return the namespace. Errors will result in exceptions.
240 PARROT_WARN_UNUSED_RESULT
241 PARROT_CAN_RETURN_NULL
243 Parrot_make_namespace_autobase(PARROT_INTERP
, ARGIN_NULLOK(PMC
*key
))
246 if (VTABLE_isa(interp
, key
, CONST_STRING(interp
, "String")))
247 base_ns
= CONTEXT(interp
)->current_namespace
;
249 base_ns
= VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
,
250 CONTEXT(interp
)->current_HLL
);
251 return Parrot_make_namespace_keyed(interp
, base_ns
, key
);
256 =item C<PMC * Parrot_get_namespace_autobase>
258 Find a namespace with the key C<key>, which may be a String, a Key, or an
259 array of strings. If it is a String, then the lookup is relative to the
260 current namespace. Otherwise, it is relative to the current HLL root
261 namespace. Return the namespace, or NULL if not found.
268 PARROT_WARN_UNUSED_RESULT
269 PARROT_CAN_RETURN_NULL
271 Parrot_get_namespace_autobase(PARROT_INTERP
, ARGIN_NULLOK(PMC
*key
))
274 if (VTABLE_isa(interp
, key
, CONST_STRING(interp
, "String")))
275 base_ns
= CONTEXT(interp
)->current_namespace
;
277 base_ns
= VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
,
278 CONTEXT(interp
)->current_HLL
);
279 return Parrot_get_namespace_keyed(interp
, base_ns
, key
);
284 =item C<PMC * Parrot_ns_get_name>
286 Retrieve an array of names from a namespace object.
293 PARROT_WARN_UNUSED_RESULT
294 PARROT_CAN_RETURN_NULL
296 Parrot_ns_get_name(PARROT_INTERP
, ARGIN(PMC
*_namespace
))
299 Parrot_PCCINVOKE(interp
, _namespace
,
300 CONST_STRING(interp
, "get_name"), "->P", &names
);
306 =item C<PMC * Parrot_get_global>
308 Parrot_get_global allows a null namespace without throwing an exception; it
309 simply returns PMCNULL in that case.
311 NOTE: At present the use of the {get, set}_global functions is mandatory due to the
312 wacky namespace typing of the default Parrot namespace. Eventually it will be
313 safe to just use the standard hash interface (if desired).
315 Look up the global named C<globalname> in the namespace C<ns>. Return the
316 global, or return PMCNULL if C<ns> is null or if the global is not found.
318 KLUDGE ALERT: Currently prefers non-namespaces in case of collision.
328 * Parrot_get_global allows a null namespace without throwing an exception; it
329 * simply returns PMCNULL in that case.
331 * NOTE: At present the use of the {get, set}_global functions is mandatory due to the
332 * wacky namespace typing of the default Parrot namespace. Eventually it will be
333 * safe to just use the standard hash interface (if desired).
337 PARROT_WARN_UNUSED_RESULT
338 PARROT_CAN_RETURN_NULL
340 Parrot_get_global(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
), ARGIN_NULLOK(STRING
*globalname
))
345 return (PMC
*)VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
350 =item C<void Parrot_set_global>
352 Set the global named C<globalname> in the namespace C<ns> to the value C<val>.
360 Parrot_set_global(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
),
361 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
363 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
369 =item C<PMC * Parrot_find_global_n>
371 Search the namespace PMC C<ns> for an object with name C<globalname>.
372 Return the object, or NULL if not found.
374 RT#46161 - For now this function prefers non-namespaces, it will eventually
375 entirely use the untyped interface.
382 PARROT_WARN_UNUSED_RESULT
383 PARROT_CAN_RETURN_NULL
385 Parrot_find_global_n(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
), ARGIN_NULLOK(STRING
*globalname
))
391 PIO_printf(interp
, "find_global name '%Ss'\n", globalname
);
398 * RT#46163 - we should be able to use 'get_pmc_keyed' here,
399 * but we can't because Parrot's default namespaces are not
400 * fully typed and there's a pseudo-typed interface that
401 * distinguishes 'get_pmc_keyed' from 'get_pointer_keyed';
402 * the former is for NS and the latter is for non-NS.
404 res
= (PMC
*)VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
407 return PMC_IS_NULL(res
) ? NULL
: res
;
412 =item C<PMC * Parrot_find_global_cur>
414 Finds and returns the data time named C<globalname> in the current namespace.
421 PARROT_WARN_UNUSED_RESULT
422 PARROT_CAN_RETURN_NULL
424 Parrot_find_global_cur(PARROT_INTERP
, ARGIN_NULLOK(STRING
*globalname
))
426 PMC
* const ns
= CONTEXT(interp
)->current_namespace
;
427 return Parrot_find_global_n(interp
, ns
, globalname
);
432 =item C<PMC * Parrot_find_global_k>
434 Search the namespace designated by C<pmc_key>, which may be a key PMC,
435 an array of namespace name strings, or a string PMC, for an object
436 with name C<globalname>. Return the object, or NULL if not found.
438 RT#46161 - For now this function prefers non-namespaces, it will eventually
439 entirely use the untyped interface.
446 PARROT_WARN_UNUSED_RESULT
447 PARROT_CAN_RETURN_NULL
449 Parrot_find_global_k(PARROT_INTERP
, ARGIN_NULLOK(PMC
*pmc_key
), ARGIN(STRING
*globalname
))
452 Parrot_get_namespace_keyed(interp
,
453 Parrot_get_ctx_HLL_namespace(interp
),
455 return Parrot_find_global_n(interp
, ns
, globalname
);
460 =item C<PMC * Parrot_find_global_s>
462 Search the namespace designated by C<str_key>, or the HLL root if
463 C<str_key> is NULL, for an object with name C<globalname>. Return the
464 object, or NULL if not found.
466 RT#46161 - For now this function prefers non-namespaces, it will eventually
467 entirely use the untyped interface.
474 PARROT_WARN_UNUSED_RESULT
475 PARROT_CAN_RETURN_NULL
477 Parrot_find_global_s(PARROT_INTERP
, ARGIN_NULLOK(STRING
*str_key
),
478 ARGIN_NULLOK(STRING
*globalname
))
481 Parrot_get_namespace_keyed_str(interp
,
482 Parrot_get_ctx_HLL_namespace(interp
),
484 return Parrot_find_global_n(interp
, ns
, globalname
);
489 =item C<void Parrot_store_global_n>
491 Store the PMC C<val> into the namespace PMC C<ns> with name C<globalname>.
499 Parrot_store_global_n(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
),
500 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
504 PIO_printf(interp
, "store_global name '%Ss'\n", globalname
);
510 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
515 =item C<void Parrot_store_global_cur>
517 Store the value C<val> with name C<globalname> in the current namespace.
525 Parrot_store_global_cur(PARROT_INTERP
, ARGIN_NULLOK(STRING
*globalname
),
526 ARGIN_NULLOK(PMC
*val
))
528 Parrot_store_global_n(interp
,
529 CONTEXT(interp
)->current_namespace
,
532 /* RT#46165 - method cache invalidation should occur */
537 =item C<void Parrot_store_global_k>
539 Store the PMC C<val> into the namespace designated by C<pmc_key>,
540 which may be a key PMC, an array of namespace name strings, or a
541 string PMC, with name C<globalname>.
543 RT#46161 - For now this function prefers non-namespaces, it will eventually
544 entirely use the untyped interface.
552 Parrot_store_global_k(PARROT_INTERP
, ARGIN(PMC
*pmc_key
),
553 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
558 * RT#46167 - temporary hack to notice when key is actually a string, so that
559 * the legacy logic for invalidating method cache will be called; this is
560 * not good enough but it avoids regressesions for now
562 if (pmc_key
->vtable
->base_type
== enum_class_String
) {
563 Parrot_store_global_s(interp
, PMC_str_val(pmc_key
),
568 ns
= Parrot_make_namespace_keyed(interp
,
569 Parrot_get_ctx_HLL_namespace(interp
),
572 Parrot_store_global_n(interp
, ns
, globalname
, val
);
574 /* RT#46165 - method cache invalidation should occur */
579 =item C<void Parrot_store_global_s>
581 Store the PMC C<val> into the namespace designated by C<str_key>, or
582 the HLL root if C<str_key> is NULL, with the name C<globalname>.
590 Parrot_store_global_s(PARROT_INTERP
, ARGIN_NULLOK(STRING
*str_key
),
591 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
593 PMC
* const ns
= Parrot_make_namespace_keyed_str(interp
,
594 Parrot_get_ctx_HLL_namespace(interp
),
597 Parrot_store_global_n(interp
, ns
, globalname
, val
);
599 /* RT#46169 - method cache invalidation should be a namespace function */
600 Parrot_invalidate_method_cache(interp
, str_key
, globalname
);
606 =item C<PMC * Parrot_find_global_op>
608 If the global exists in the given namespace PMC, return it. If not, return
616 PARROT_WARN_UNUSED_RESULT
617 PARROT_CANNOT_RETURN_NULL
619 Parrot_find_global_op(PARROT_INTERP
, ARGIN(PMC
*ns
),
620 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(void *next
))
625 Parrot_ex_throw_from_c_args(interp
, next
, EXCEPTION_GLOBAL_NOT_FOUND
,
626 "Tried to get null global");
628 res
= Parrot_find_global_n(interp
, ns
, globalname
);
638 =item C<PMC * Parrot_find_name_op>
640 RT#46171 - THIS IS BROKEN - it doesn't walk up the scopes yet
642 Find the given C<name> in lexicals, then the current namespace, then the HLL
643 root namespace, and finally Parrot builtins. If the name isn't found
644 anywhere, return PMCNULL.
651 PARROT_WARN_UNUSED_RESULT
652 PARROT_CAN_RETURN_NULL
654 Parrot_find_name_op(PARROT_INTERP
, ARGIN(STRING
*name
), SHIM(void *next
))
656 parrot_context_t
* const ctx
= CONTEXT(interp
);
657 PMC
* const lex_pad
= Parrot_find_pad(interp
, name
, ctx
);
660 if (PMC_IS_NULL(lex_pad
))
663 g
= VTABLE_get_pmc_keyed_str(interp
, lex_pad
, name
);
665 /* RT#46171 - walk up the scopes! duh!! */
668 g
= Parrot_find_global_cur(interp
, name
);
671 g
= Parrot_find_global_n(interp
, Parrot_get_ctx_HLL_namespace(interp
), name
);
681 =item C<static PMC * get_namespace_pmc>
683 Return the namespace PMC associated with the PMC C<sub>. If C<sub> is NULL,
684 return the Associated HLL namespace PMC instead.
690 PARROT_WARN_UNUSED_RESULT
691 PARROT_CAN_RETURN_NULL
693 get_namespace_pmc(PARROT_INTERP
, ARGIN(PMC
*sub
))
695 PMC
* const nsname
= PMC_sub(sub
)->namespace_name
;
696 PMC
* const nsroot
= Parrot_get_HLL_namespace(interp
, PMC_sub(sub
)->HLL_id
);
698 /* If we have a NULL, return the HLL namespace */
699 if (PMC_IS_NULL(nsname
))
701 /* If we have a String, do a string lookup */
702 else if (nsname
->vtable
->base_type
== enum_class_String
)
703 return Parrot_make_namespace_keyed_str(interp
, nsroot
, PMC_str_val(nsname
));
704 /* Otherwise, do a PMC lookup */
706 return Parrot_make_namespace_keyed(interp
, nsroot
, nsname
);
711 =item C<static void store_sub_in_multi>
713 Adds the sub C<sub> into a mulisub of the same name in the namespace C<ns>.
714 If no multisub by that name currently exists, we create one.
721 store_sub_in_multi(PARROT_INTERP
, ARGIN(PMC
*sub
), ARGIN(PMC
*ns
))
725 STRING
* const subname
= PMC_sub(sub
)->name
;
726 PMC
*multisub
= VTABLE_get_pmc_keyed_str(interp
, ns
, subname
);
728 /* is there an existing MultiSub PMC? or do we need to create one? */
729 if (PMC_IS_NULL(multisub
)) {
730 multisub
= pmc_new(interp
, enum_class_MultiSub
);
731 /* we have to push the sub onto the MultiSub before we try to store
732 it because storing requires information from the sub */
733 VTABLE_push_pmc(interp
, multisub
, sub
);
734 VTABLE_set_pmc_keyed_str(interp
, ns
, subname
, multisub
);
737 VTABLE_push_pmc(interp
, multisub
, sub
);
739 c_meth
= string_to_cstring(interp
, subname
);
740 func_nr
= Parrot_MMD_method_idx(interp
, c_meth
);
742 Parrot_mmd_rebuild_table(interp
, -1, func_nr
);
743 string_cstring_free(c_meth
);
748 =item C<void Parrot_store_sub_in_namespace>
750 Adds the PMC C<sub> into the current namespace. Adds the sub to a multi of the
751 same name if it's defined as a multi.
759 Parrot_store_sub_in_namespace(PARROT_INTERP
, ARGIN(PMC
*sub
))
761 const INTVAL cur_id
= CONTEXT(interp
)->current_HLL
;
764 /* PF structures aren't fully constructed yet */
765 Parrot_block_GC_mark(interp
);
766 /* store relative to HLL namespace */
767 CONTEXT(interp
)->current_HLL
= PMC_sub(sub
)->HLL_id
;
769 ns
= get_namespace_pmc(interp
, sub
);
771 /* attach a namespace to the sub for lookups */
772 PMC_sub(sub
)->namespace_stash
= ns
;
774 /* store a :multi sub */
775 if (!PMC_IS_NULL(PMC_sub(sub
)->multi_signature
))
776 store_sub_in_multi(interp
, sub
, ns
);
777 /* store other subs (as long as they're not :anon) */
778 else if (!(PObj_get_FLAGS(sub
) & SUB_FLAG_PF_ANON
)) {
779 STRING
* const name
= PMC_sub(sub
)->name
;
780 PMC
* const nsname
= PMC_sub(sub
)->namespace_name
;
782 Parrot_store_global_n(interp
, ns
, name
, sub
);
784 /* TEMPORARY HACK - cache invalidation should be a namespace function */
785 if (!PMC_IS_NULL(nsname
)) {
786 STRING
* const nsname_s
= VTABLE_get_string(interp
, nsname
);
787 Parrot_invalidate_method_cache(interp
, nsname_s
, name
);
792 CONTEXT(interp
)->current_HLL
= cur_id
;
793 Parrot_unblock_GC_mark(interp
);
802 F<include/parrot/global.h>
811 * c-file-style: "parrot"
813 * vim: expandtab shiftwidth=4: