2 Copyright (C) 2004-2007, 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 real_exception(interp
, NULL
, 1,
100 "Passing a NULL pmc_key into key_string()");
102 part
= key_string(interp
, pmc_key
);
103 pmc_key
= key_next(interp
, pmc_key
);
105 n
= i
+ 1; /* now we know how big the key is */
109 real_exception(interp
, NULL
, 1,
110 "Passed a NULL pmc_key into VTABLE_get_string_keyed_int");
112 part
= VTABLE_get_string_keyed_int(interp
, pmc_key
, i
);
115 sub_ns
= VTABLE_get_pmc_keyed_str(interp
, ns
, part
);
117 if (PMC_IS_NULL(sub_ns
)
118 /* RT#46157 - stop depending on typed namespace */
119 || sub_ns
->vtable
->base_type
!= enum_class_NameSpace
)
121 if (!(flags
& INTERN_NS_CREAT
))
124 /* RT#46159 - match HLL of enclosing namespace? */
125 sub_ns
= pmc_new(interp
,
126 Parrot_get_ctx_HLL_type(interp
,
127 enum_class_NameSpace
));
128 if (PMC_IS_NULL(sub_ns
))
130 VTABLE_set_pmc_keyed_str(interp
, ns
, part
, sub_ns
);
140 =item C<PMC * Parrot_get_namespace_keyed>
142 Find the namespace relative to the namespace C<base_ns> with the key
143 C<pmc_key>, which may be a String, a Key, or an array of strings. Return
144 the namespace, or NULL if not found.
151 PARROT_WARN_UNUSED_RESULT
152 PARROT_CAN_RETURN_NULL
154 Parrot_get_namespace_keyed(PARROT_INTERP
, ARGIN(PMC
*base_ns
), ARGIN_NULLOK(PMC
*pmc_key
))
156 return internal_ns_keyed(interp
, base_ns
, pmc_key
, NULL
, 0);
161 =item C<PMC * Parrot_get_namespace_keyed_str>
163 Find the namespace relative to the namespace C<base_ns> with the string key
164 C<str_key>. Return the namespace, or NULL if not found.
171 PARROT_WARN_UNUSED_RESULT
172 PARROT_CAN_RETURN_NULL
174 Parrot_get_namespace_keyed_str(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
175 ARGIN_NULLOK(STRING
*str_key
))
177 return internal_ns_keyed(interp
, base_ns
, PMCNULL
, str_key
, 0);
182 =item C<PMC * Parrot_make_namespace_keyed>
184 Find, or create if necessary, the namespace relative to the namespace
185 C<base_ns> with the key C<pmc_key>, which may be a String, a Key, or an
186 array of strings. Return the namespace. Errors will result in exceptions.
193 PARROT_WARN_UNUSED_RESULT
194 PARROT_CAN_RETURN_NULL
196 Parrot_make_namespace_keyed(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
197 ARGIN_NULLOK(PMC
*pmc_key
))
199 return internal_ns_keyed(interp
, base_ns
, pmc_key
, NULL
, INTERN_NS_CREAT
);
204 =item C<PMC * Parrot_make_namespace_keyed_str>
206 Find, or create if necessary, the namespace relative to the namespace
207 C<base_ns> with the string key C<str_key>. Return the namespace. Errors
208 will result in exceptions.
215 PARROT_WARN_UNUSED_RESULT
216 PARROT_CAN_RETURN_NULL
218 Parrot_make_namespace_keyed_str(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
219 ARGIN_NULLOK(STRING
*str_key
))
221 return internal_ns_keyed(interp
, base_ns
, NULL
, str_key
, INTERN_NS_CREAT
);
227 =item C<PMC * Parrot_make_namespace_autobase>
229 Find, or create if necessary, a namespace with the key C<key>, which may be a
230 String, a Key, or an array of strings. If it is a String, then the lookup is
231 relative to the current namespace. Otherwise, it is relative to the current HLL
232 root namespace. Return the namespace. Errors will result in exceptions.
239 PARROT_WARN_UNUSED_RESULT
240 PARROT_CAN_RETURN_NULL
242 Parrot_make_namespace_autobase(PARROT_INTERP
, ARGIN_NULLOK(PMC
*key
))
245 if (VTABLE_isa(interp
, key
, CONST_STRING(interp
, "String")))
246 base_ns
= CONTEXT(interp
)->current_namespace
;
248 base_ns
= VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
,
249 CONTEXT(interp
)->current_HLL
);
250 return Parrot_make_namespace_keyed(interp
, base_ns
, key
);
255 =item C<PMC * Parrot_get_namespace_autobase>
257 Find a namespace with the key C<key>, which may be a String, a Key, or an
258 array of strings. If it is a String, then the lookup is relative to the
259 current namespace. Otherwise, it is relative to the current HLL root
260 namespace. Return the namespace, or NULL if not found.
267 PARROT_WARN_UNUSED_RESULT
268 PARROT_CAN_RETURN_NULL
270 Parrot_get_namespace_autobase(PARROT_INTERP
, ARGIN_NULLOK(PMC
*key
))
273 if (VTABLE_isa(interp
, key
, CONST_STRING(interp
, "String")))
274 base_ns
= CONTEXT(interp
)->current_namespace
;
276 base_ns
= VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
,
277 CONTEXT(interp
)->current_HLL
);
278 return Parrot_get_namespace_keyed(interp
, base_ns
, key
);
283 =item C<PMC * Parrot_ns_get_name>
285 Retrieve an array of names from a namespace object.
292 PARROT_WARN_UNUSED_RESULT
293 PARROT_CAN_RETURN_NULL
295 Parrot_ns_get_name(PARROT_INTERP
, ARGIN(PMC
*_namespace
))
298 Parrot_PCCINVOKE(interp
, _namespace
,
299 CONST_STRING(interp
, "get_name"), "->P", &names
);
305 =item C<PMC * Parrot_get_global>
307 Parrot_get_global allows a null namespace without throwing an exception; it
308 simply returns PMCNULL in that case.
310 NOTE: At present the use of the {get, set}_global functions is mandatory due to the
311 wacky namespace typing of the default Parrot namespace. Eventually it will be
312 safe to just use the standard hash interface (if desired).
314 Look up the global named C<globalname> in the namespace C<ns>. Return the
315 global, or return PMCNULL if C<ns> is null or if the global is not found.
317 KLUDGE ALERT: Currently prefers non-namespaces in case of collision.
327 * Parrot_get_global allows a null namespace without throwing an exception; it
328 * simply returns PMCNULL in that case.
330 * NOTE: At present the use of the {get, set}_global functions is mandatory due to the
331 * wacky namespace typing of the default Parrot namespace. Eventually it will be
332 * safe to just use the standard hash interface (if desired).
336 PARROT_WARN_UNUSED_RESULT
337 PARROT_CAN_RETURN_NULL
339 Parrot_get_global(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
), ARGIN_NULLOK(STRING
*globalname
))
344 return (PMC
*)VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
349 =item C<void Parrot_set_global>
351 Set the global named C<globalname> in the namespace C<ns> to the value C<val>.
359 Parrot_set_global(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
),
360 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
362 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
368 =item C<PMC * Parrot_find_global_n>
370 Search the namespace PMC C<ns> for an object with name C<globalname>.
371 Return the object, or NULL if not found.
373 RT#46161 - For now this function prefers non-namespaces, it will eventually
374 entirely use the untyped interface.
381 PARROT_WARN_UNUSED_RESULT
382 PARROT_CAN_RETURN_NULL
384 Parrot_find_global_n(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
), ARGIN_NULLOK(STRING
*globalname
))
390 PIO_printf(interp
, "find_global name '%Ss'\n", globalname
);
397 * RT#46163 - we should be able to use 'get_pmc_keyed' here,
398 * but we can't because Parrot's default namespaces are not
399 * fully typed and there's a pseudo-typed interface that
400 * distinguishes 'get_pmc_keyed' from 'get_pointer_keyed';
401 * the former is for NS and the latter is for non-NS.
403 res
= (PMC
*)VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
406 return PMC_IS_NULL(res
) ? NULL
: res
;
411 =item C<PMC * Parrot_find_global_cur>
413 RT#48260: Not yet documented!!!
420 PARROT_WARN_UNUSED_RESULT
421 PARROT_CAN_RETURN_NULL
423 Parrot_find_global_cur(PARROT_INTERP
, ARGIN_NULLOK(STRING
*globalname
))
425 PMC
* const ns
= CONTEXT(interp
)->current_namespace
;
426 return Parrot_find_global_n(interp
, ns
, globalname
);
431 =item C<PMC * Parrot_find_global_k>
433 Search the namespace designated by C<pmc_key>, which may be a key PMC,
434 an array of namespace name strings, or a string PMC, for an object
435 with name C<globalname>. Return the object, or NULL if not found.
437 RT#46161 - For now this function prefers non-namespaces, it will eventually
438 entirely use the untyped interface.
445 PARROT_WARN_UNUSED_RESULT
446 PARROT_CAN_RETURN_NULL
448 Parrot_find_global_k(PARROT_INTERP
, ARGIN_NULLOK(PMC
*pmc_key
), ARGIN(STRING
*globalname
))
451 Parrot_get_namespace_keyed(interp
,
452 Parrot_get_ctx_HLL_namespace(interp
),
454 return Parrot_find_global_n(interp
, ns
, globalname
);
459 =item C<PMC * Parrot_find_global_s>
461 Search the namespace designated by C<str_key>, or the HLL root if
462 C<str_key> is NULL, for an object with name C<globalname>. Return the
463 object, or NULL if not found.
465 RT#46161 - For now this function prefers non-namespaces, it will eventually
466 entirely use the untyped interface.
473 PARROT_WARN_UNUSED_RESULT
474 PARROT_CAN_RETURN_NULL
476 Parrot_find_global_s(PARROT_INTERP
, ARGIN_NULLOK(STRING
*str_key
),
477 ARGIN_NULLOK(STRING
*globalname
))
480 Parrot_get_namespace_keyed_str(interp
,
481 Parrot_get_ctx_HLL_namespace(interp
),
483 return Parrot_find_global_n(interp
, ns
, globalname
);
488 =item C<void Parrot_store_global_n>
490 Store the PMC C<val> into the namespace PMC C<ns> with name C<globalname>.
498 Parrot_store_global_n(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
),
499 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
503 PIO_printf(interp
, "store_global name '%Ss'\n", globalname
);
509 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
514 =item C<void Parrot_store_global_cur>
516 RT#48260: Not yet documented!!!
524 Parrot_store_global_cur(PARROT_INTERP
, ARGIN_NULLOK(STRING
*globalname
),
525 ARGIN_NULLOK(PMC
*val
))
527 Parrot_store_global_n(interp
,
528 CONTEXT(interp
)->current_namespace
,
531 /* RT#46165 - method cache invalidation should occur */
536 =item C<void Parrot_store_global_k>
538 Store the PMC C<val> into the namespace designated by C<pmc_key>,
539 which may be a key PMC, an array of namespace name strings, or a
540 string PMC, with name C<globalname>.
542 RT#46161 - For now this function prefers non-namespaces, it will eventually
543 entirely use the untyped interface.
551 Parrot_store_global_k(PARROT_INTERP
, ARGIN(PMC
*pmc_key
),
552 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
557 * RT#46167 - temporary hack to notice when key is actually a string, so that
558 * the legacy logic for invalidating method cache will be called; this is
559 * not good enough but it avoids regressesions for now
561 if (pmc_key
->vtable
->base_type
== enum_class_String
) {
562 Parrot_store_global_s(interp
, PMC_str_val(pmc_key
),
567 ns
= Parrot_make_namespace_keyed(interp
,
568 Parrot_get_ctx_HLL_namespace(interp
),
571 Parrot_store_global_n(interp
, ns
, globalname
, val
);
573 /* RT#46165 - method cache invalidation should occur */
578 =item C<void Parrot_store_global_s>
580 Store the PMC C<val> into the namespace designated by C<str_key>, or
581 the HLL root if C<str_key> is NULL, with the name C<globalname>.
589 Parrot_store_global_s(PARROT_INTERP
, ARGIN_NULLOK(STRING
*str_key
),
590 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
592 PMC
* const ns
= Parrot_make_namespace_keyed_str(interp
,
593 Parrot_get_ctx_HLL_namespace(interp
),
596 Parrot_store_global_n(interp
, ns
, globalname
, val
);
598 /* RT#46169 - method cache invalidation should be a namespace function */
599 Parrot_invalidate_method_cache(interp
, str_key
, globalname
);
605 =item C<PMC * Parrot_find_global_op>
607 If the global exists in the given namespace PMC, return it. If not, return
615 PARROT_WARN_UNUSED_RESULT
616 PARROT_CANNOT_RETURN_NULL
618 Parrot_find_global_op(PARROT_INTERP
, ARGIN(PMC
*ns
),
619 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(void *next
))
624 real_exception(interp
, next
, E_NameError
,
625 "Tried to get null global");
627 res
= Parrot_find_global_n(interp
, ns
, globalname
);
637 =item C<PMC * Parrot_find_name_op>
639 RT#46171 - THIS IS BROKEN - it doesn't walk up the scopes yet
641 Find the given C<name> in lexicals, then the current namespace, then the HLL
642 root namespace, and finally Parrot builtins. If the name isn't found
643 anywhere, return PMCNULL.
650 PARROT_WARN_UNUSED_RESULT
651 PARROT_CAN_RETURN_NULL
653 Parrot_find_name_op(PARROT_INTERP
, ARGIN(STRING
*name
), SHIM(void *next
))
655 parrot_context_t
* const ctx
= CONTEXT(interp
);
656 PMC
* const lex_pad
= Parrot_find_pad(interp
, name
, ctx
);
659 if (PMC_IS_NULL(lex_pad
))
662 g
= VTABLE_get_pmc_keyed_str(interp
, lex_pad
, name
);
664 /* RT#46171 - walk up the scopes! duh!! */
666 if (PMC_IS_NULL(g
)) {
667 g
= Parrot_find_global_cur(interp
, name
);
669 if (PMC_IS_NULL(g
)) {
670 g
= Parrot_find_global_n(interp
,
671 Parrot_get_ctx_HLL_namespace(interp
), name
);
673 if (PMC_IS_NULL(g
)) {
674 g
= Parrot_find_builtin(interp
, name
);
687 =item C<static PMC * get_namespace_pmc>
689 RT#48260: Not yet documented!!!
695 PARROT_WARN_UNUSED_RESULT
696 PARROT_CAN_RETURN_NULL
698 get_namespace_pmc(PARROT_INTERP
, ARGIN(PMC
*sub
))
700 PMC
* const nsname
= PMC_sub(sub
)->namespace_name
;
701 PMC
* const nsroot
= Parrot_get_HLL_namespace(interp
, PMC_sub(sub
)->HLL_id
);
703 /* If we have a NULL, return the HLL namespace */
704 if (PMC_IS_NULL(nsname
))
706 /* If we have a String, do a string lookup */
707 else if (nsname
->vtable
->base_type
== enum_class_String
)
708 return Parrot_make_namespace_keyed_str(interp
, nsroot
, PMC_str_val(nsname
));
709 /* Otherwise, do a PMC lookup */
711 return Parrot_make_namespace_keyed(interp
, nsroot
, nsname
);
716 =item C<static void store_sub_in_multi>
718 RT#48260: Not yet documented!!!
725 store_sub_in_multi(PARROT_INTERP
, ARGIN(PMC
*sub
), ARGIN(PMC
*ns
))
729 STRING
* const subname
= PMC_sub(sub
)->name
;
730 PMC
*multisub
= VTABLE_get_pmc_keyed_str(interp
, ns
, subname
);
732 /* is there an existing MultiSub PMC? or do we need to create one? */
733 if (PMC_IS_NULL(multisub
)) {
734 multisub
= pmc_new(interp
, enum_class_MultiSub
);
735 /* we have to push the sub onto the MultiSub before we try to store
736 it because storing requires information from the sub */
737 VTABLE_push_pmc(interp
, multisub
, sub
);
738 VTABLE_set_pmc_keyed_str(interp
, ns
, subname
, multisub
);
741 VTABLE_push_pmc(interp
, multisub
, sub
);
743 c_meth
= string_to_cstring(interp
, subname
);
744 func_nr
= Parrot_MMD_method_idx(interp
, c_meth
);
746 Parrot_mmd_rebuild_table(interp
, -1, func_nr
);
747 string_cstring_free(c_meth
);
752 =item C<void Parrot_store_sub_in_namespace>
754 RT#48260: Not yet documented!!!
762 Parrot_store_sub_in_namespace(PARROT_INTERP
, ARGIN(PMC
*sub
))
764 const INTVAL cur_id
= CONTEXT(interp
)->current_HLL
;
767 /* PF structures aren't fully constructed yet */
768 Parrot_block_GC_mark(interp
);
769 /* store relative to HLL namespace */
770 CONTEXT(interp
)->current_HLL
= PMC_sub(sub
)->HLL_id
;
772 ns
= get_namespace_pmc(interp
, sub
);
774 /* attach a namespace to the sub for lookups */
775 PMC_sub(sub
)->namespace_stash
= ns
;
777 /* store a :multi sub */
778 if (!PMC_IS_NULL(PMC_sub(sub
)->multi_signature
))
779 store_sub_in_multi(interp
, sub
, ns
);
780 /* store other subs (as long as they're not :anon) */
781 else if (!(PObj_get_FLAGS(sub
) & SUB_FLAG_PF_ANON
)) {
782 STRING
* const name
= PMC_sub(sub
)->name
;
783 PMC
* const nsname
= PMC_sub(sub
)->namespace_name
;
785 Parrot_store_global_n(interp
, ns
, name
, sub
);
787 /* TEMPORARY HACK - cache invalidation should be a namespace function */
788 if (!PMC_IS_NULL(nsname
)) {
789 STRING
* const nsname_s
= VTABLE_get_string(interp
, nsname
);
790 Parrot_invalidate_method_cache(interp
, nsname_s
, name
);
795 CONTEXT(interp
)->current_HLL
= cur_id
;
796 Parrot_unblock_GC_mark(interp
);
805 F<include/parrot/global.h>
814 * c-file-style: "parrot"
816 * vim: expandtab shiftwidth=4: