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 */
25 PARROT_WARN_UNUSED_RESULT
26 PARROT_CAN_RETURN_NULL
27 static PMC
* get_namespace_pmc(PARROT_INTERP
, ARGIN(PMC
*sub
))
28 __attribute__nonnull__(1)
29 __attribute__nonnull__(2);
31 PARROT_WARN_UNUSED_RESULT
32 PARROT_CAN_RETURN_NULL
33 static PMC
* internal_ns_keyed(PARROT_INTERP
,
35 ARGIN_NULLOK(PMC
*pmc_key
),
36 ARGIN_NULLOK(STRING
*str_key
),
38 __attribute__nonnull__(1)
39 __attribute__nonnull__(2);
41 static void store_sub_in_multi(PARROT_INTERP
,
44 __attribute__nonnull__(1)
45 __attribute__nonnull__(2)
46 __attribute__nonnull__(3);
48 /* HEADERIZER END: static */
50 #define DEBUG_GLOBAL 0
52 /* flags for internal_ns_keyed */
53 #define INTERN_NS_CREAT 1 /* I'm a fan of the classics */
57 =item C<static PMC * internal_ns_keyed>
59 internal_ns_keyed: Internal function to do keyed namespace lookup
60 relative to a given namespace PMC. Understands STRINGs, String PMCs,
61 Key pmcs, and array PMCs containing strings.
67 PARROT_WARN_UNUSED_RESULT
68 PARROT_CAN_RETURN_NULL
70 internal_ns_keyed(PARROT_INTERP
, ARGIN(PMC
*base_ns
), ARGIN_NULLOK(PMC
*pmc_key
),
71 ARGIN_NULLOK(STRING
*str_key
), int flags
)
75 static const INTVAL max_intval
= (INTVAL
)((~(UINTVAL
)0) >> 1); /*2s comp*/
81 else if (pmc_key
->vtable
->base_type
== enum_class_String
) {
82 str_key
= VTABLE_get_string(interp
, pmc_key
);
85 else if (pmc_key
->vtable
->base_type
== enum_class_Key
)
86 n
= max_intval
; /* we don't yet know how big the key is */
88 n
= VTABLE_elements(interp
, pmc_key
); /* array of strings */
90 for (i
= 0; i
< n
; ++i
) {
95 else if (n
== max_intval
) {
97 real_exception(interp
, NULL
, 1,
98 "Passing a NULL pmc_key into key_string()");
100 part
= key_string(interp
, pmc_key
);
101 pmc_key
= key_next(interp
, pmc_key
);
103 n
= i
+ 1; /* now we know how big the key is */
107 real_exception(interp
, NULL
, 1,
108 "Passed a NULL pmc_key into VTABLE_get_string_keyed_int");
110 part
= VTABLE_get_string_keyed_int(interp
, pmc_key
, i
);
113 sub_ns
= VTABLE_get_pmc_keyed_str(interp
, ns
, part
);
115 if (PMC_IS_NULL(sub_ns
)
116 /* RT#46157 - stop depending on typed namespace */
117 || sub_ns
->vtable
->base_type
!= enum_class_NameSpace
)
119 if (!(flags
& INTERN_NS_CREAT
))
122 /* RT#46159 - match HLL of enclosing namespace? */
123 sub_ns
= pmc_new(interp
,
124 Parrot_get_ctx_HLL_type(interp
,
125 enum_class_NameSpace
));
126 if (PMC_IS_NULL(sub_ns
))
128 VTABLE_set_pmc_keyed_str(interp
, ns
, part
, sub_ns
);
138 =item C<PMC * Parrot_get_namespace_keyed>
140 Find the namespace relative to the namespace C<base_ns> with the key
141 C<pmc_key>, which may be a String, a Key, or an array of strings. Return
142 the namespace, or NULL if not found.
149 PARROT_WARN_UNUSED_RESULT
150 PARROT_CAN_RETURN_NULL
152 Parrot_get_namespace_keyed(PARROT_INTERP
, ARGIN(PMC
*base_ns
), ARGIN_NULLOK(PMC
*pmc_key
))
154 return internal_ns_keyed(interp
, base_ns
, pmc_key
, NULL
, 0);
159 =item C<PMC * Parrot_get_namespace_keyed_str>
161 Find the namespace relative to the namespace C<base_ns> with the string key
162 C<str_key>. Return the namespace, or NULL if not found.
169 PARROT_WARN_UNUSED_RESULT
170 PARROT_CAN_RETURN_NULL
172 Parrot_get_namespace_keyed_str(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
173 ARGIN_NULLOK(STRING
*str_key
))
175 return internal_ns_keyed(interp
, base_ns
, PMCNULL
, str_key
, 0);
180 =item C<PMC * Parrot_make_namespace_keyed>
182 Find, or create if necessary, the namespace relative to the namespace
183 C<base_ns> with the key C<pmc_key>, which may be a String, a Key, or an
184 array of strings. Return the namespace. Errors will result in exceptions.
191 PARROT_WARN_UNUSED_RESULT
192 PARROT_CAN_RETURN_NULL
194 Parrot_make_namespace_keyed(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
195 ARGIN_NULLOK(PMC
*pmc_key
))
197 return internal_ns_keyed(interp
, base_ns
, pmc_key
, NULL
, INTERN_NS_CREAT
);
202 =item C<PMC * Parrot_make_namespace_keyed_str>
204 Find, or create if necessary, the namespace relative to the namespace
205 C<base_ns> with the string key C<str_key>. Return the namespace. Errors
206 will result in exceptions.
213 PARROT_WARN_UNUSED_RESULT
214 PARROT_CAN_RETURN_NULL
216 Parrot_make_namespace_keyed_str(PARROT_INTERP
, ARGIN(PMC
*base_ns
),
217 ARGIN_NULLOK(STRING
*str_key
))
219 return internal_ns_keyed(interp
, base_ns
, NULL
, str_key
, INTERN_NS_CREAT
);
225 =item C<PMC * Parrot_make_namespace_autobase>
227 Find, or create if necessary, a namespace with the key C<key>, which may be a
228 String, a Key, or an array of strings. If it is a String, then the lookup is
229 relative to the current namespace. Otherwise, it is relative to the current HLL
230 root namespace. Return the namespace. Errors will result in exceptions.
237 PARROT_WARN_UNUSED_RESULT
238 PARROT_CAN_RETURN_NULL
240 Parrot_make_namespace_autobase(PARROT_INTERP
, ARGIN_NULLOK(PMC
*key
))
243 if (VTABLE_isa(interp
, key
, CONST_STRING(interp
, "String")))
244 base_ns
= CONTEXT(interp
->ctx
)->current_namespace
;
246 base_ns
= VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
,
247 CONTEXT(interp
->ctx
)->current_HLL
);
248 return Parrot_make_namespace_keyed(interp
, base_ns
, key
);
253 =item C<PMC * Parrot_get_namespace_autobase>
255 Find a namespace with the key C<key>, which may be a String, a Key, or an
256 array of strings. If it is a String, then the lookup is relative to the
257 current namespace. Otherwise, it is relative to the current HLL root
258 namespace. Return the namespace, or NULL if not found.
265 PARROT_WARN_UNUSED_RESULT
266 PARROT_CAN_RETURN_NULL
268 Parrot_get_namespace_autobase(PARROT_INTERP
, ARGIN_NULLOK(PMC
*key
))
271 if (VTABLE_isa(interp
, key
, CONST_STRING(interp
, "String")))
272 base_ns
= CONTEXT(interp
->ctx
)->current_namespace
;
274 base_ns
= VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
,
275 CONTEXT(interp
->ctx
)->current_HLL
);
276 return Parrot_get_namespace_keyed(interp
, base_ns
, key
);
282 =item C<PMC * Parrot_get_global>
284 Parrot_get_global allows a null namespace without throwing an exception; it
285 simply returns PMCNULL in that case.
287 NOTE: At present the use of the {get, set}_global functions is mandatory due to the
288 wacky namespace typing of the default Parrot namespace. Eventually it will be
289 safe to just use the standard hash interface (if desired).
291 Look up the global named C<globalname> in the namespace C<ns>. Return the
292 global, or return PMCNULL if C<ns> is null or if the global is not found.
294 KLUDGE ALERT: Currently prefers non-namespaces in case of collision.
304 * Parrot_get_global allows a null namespace without throwing an exception; it
305 * simply returns PMCNULL in that case.
307 * NOTE: At present the use of the {get, set}_global functions is mandatory due to the
308 * wacky namespace typing of the default Parrot namespace. Eventually it will be
309 * safe to just use the standard hash interface (if desired).
313 PARROT_WARN_UNUSED_RESULT
314 PARROT_CAN_RETURN_NULL
316 Parrot_get_global(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
), ARGIN_NULLOK(STRING
*globalname
))
321 return (PMC
*)VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
326 =item C<void Parrot_set_global>
328 Set the global named C<globalname> in the namespace C<ns> to the value C<val>.
336 Parrot_set_global(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
),
337 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
339 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
345 =item C<PMC * Parrot_find_global_n>
347 Search the namespace PMC C<ns> for an object with name C<globalname>.
348 Return the object, or NULL if not found.
350 RT#46161 - For now this function prefers non-namespaces, it will eventually
351 entirely use the untyped interface.
358 PARROT_WARN_UNUSED_RESULT
359 PARROT_CAN_RETURN_NULL
361 Parrot_find_global_n(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
), ARGIN_NULLOK(STRING
*globalname
))
367 PIO_printf(interp
, "find_global name '%Ss'\n", globalname
);
374 * RT#46163 - we should be able to use 'get_pmc_keyed' here,
375 * but we can't because Parrot's default namespaces are not
376 * fully typed and there's a pseudo-typed interface that
377 * distinguishes 'get_pmc_keyed' from 'get_pointer_keyed';
378 * the former is for NS and the latter is for non-NS.
380 res
= (PMC
*)VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
383 return PMC_IS_NULL(res
) ? NULL
: res
;
388 =item C<PMC * Parrot_find_global_cur>
390 RT#48260: Not yet documented!!!
397 PARROT_WARN_UNUSED_RESULT
398 PARROT_CAN_RETURN_NULL
400 Parrot_find_global_cur(PARROT_INTERP
, ARGIN_NULLOK(STRING
*globalname
))
402 PMC
* const ns
= CONTEXT(interp
->ctx
)->current_namespace
;
403 return Parrot_find_global_n(interp
, ns
, globalname
);
408 =item C<PMC * Parrot_find_global_k>
410 Search the namespace designated by C<pmc_key>, which may be a key PMC,
411 an array of namespace name strings, or a string PMC, for an object
412 with name C<globalname>. Return the object, or NULL if not found.
414 RT#46161 - For now this function prefers non-namespaces, it will eventually
415 entirely use the untyped interface.
422 PARROT_WARN_UNUSED_RESULT
423 PARROT_CAN_RETURN_NULL
425 Parrot_find_global_k(PARROT_INTERP
, ARGIN_NULLOK(PMC
*pmc_key
), ARGIN(STRING
*globalname
))
428 Parrot_get_namespace_keyed(interp
,
429 Parrot_get_ctx_HLL_namespace(interp
),
431 return Parrot_find_global_n(interp
, ns
, globalname
);
436 =item C<PMC * Parrot_find_global_s>
438 Search the namespace designated by C<str_key>, or the HLL root if
439 C<str_key> is NULL, for an object with name C<globalname>. Return the
440 object, or NULL if not found.
442 RT#46161 - For now this function prefers non-namespaces, it will eventually
443 entirely use the untyped interface.
450 PARROT_WARN_UNUSED_RESULT
451 PARROT_CAN_RETURN_NULL
453 Parrot_find_global_s(PARROT_INTERP
, ARGIN_NULLOK(STRING
*str_key
),
454 ARGIN_NULLOK(STRING
*globalname
))
457 Parrot_get_namespace_keyed_str(interp
,
458 Parrot_get_ctx_HLL_namespace(interp
),
460 return Parrot_find_global_n(interp
, ns
, globalname
);
465 =item C<void Parrot_store_global_n>
467 Store the PMC C<val> into the namespace PMC C<ns> with name C<globalname>.
475 Parrot_store_global_n(PARROT_INTERP
, ARGIN_NULLOK(PMC
*ns
),
476 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
480 PIO_printf(interp
, "store_global name '%Ss'\n", globalname
);
486 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
491 =item C<void Parrot_store_global_cur>
493 RT#48260: Not yet documented!!!
501 Parrot_store_global_cur(PARROT_INTERP
, ARGIN_NULLOK(STRING
*globalname
),
502 ARGIN_NULLOK(PMC
*val
))
504 Parrot_store_global_n(interp
,
505 CONTEXT(interp
->ctx
)->current_namespace
,
508 /* RT#46165 - method cache invalidation should occur */
513 =item C<void Parrot_store_global_k>
515 Store the PMC C<val> into the namespace designated by C<pmc_key>,
516 which may be a key PMC, an array of namespace name strings, or a
517 string PMC, with name C<globalname>.
519 RT#46161 - For now this function prefers non-namespaces, it will eventually
520 entirely use the untyped interface.
528 Parrot_store_global_k(PARROT_INTERP
, ARGIN(PMC
*pmc_key
),
529 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
534 * RT#46167 - temporary hack to notice when key is actually a string, so that
535 * the legacy logic for invalidating method cache will be called; this is
536 * not good enough but it avoids regressesions for now
538 if (pmc_key
->vtable
->base_type
== enum_class_String
) {
539 Parrot_store_global_s(interp
, PMC_str_val(pmc_key
),
544 ns
= Parrot_make_namespace_keyed(interp
,
545 Parrot_get_ctx_HLL_namespace(interp
),
548 Parrot_store_global_n(interp
, ns
, globalname
, val
);
550 /* RT#46165 - method cache invalidation should occur */
555 =item C<void Parrot_store_global_s>
557 Store the PMC C<val> into the namespace designated by C<str_key>, or
558 the HLL root if C<str_key> is NULL, with the name C<globalname>.
566 Parrot_store_global_s(PARROT_INTERP
, ARGIN_NULLOK(STRING
*str_key
),
567 ARGIN_NULLOK(STRING
*globalname
), ARGIN_NULLOK(PMC
*val
))
569 PMC
* const ns
= Parrot_make_namespace_keyed_str(interp
,
570 Parrot_get_ctx_HLL_namespace(interp
),
573 Parrot_store_global_n(interp
, ns
, globalname
, val
);
575 /* RT#46169 - method cache invalidation should be a namespace function */
576 Parrot_invalidate_method_cache(interp
, str_key
, globalname
);
582 =item C<PMC * Parrot_find_global_op>
584 If the global exists in the given namespace PMC, return it. If not, return
592 PARROT_WARN_UNUSED_RESULT
593 PARROT_CANNOT_RETURN_NULL
595 Parrot_find_global_op(PARROT_INTERP
, ARGIN(PMC
*ns
),
596 ARGIN(STRING
*globalname
), ARGIN_NULLOK(void *next
))
601 real_exception(interp
, next
, E_NameError
,
602 "Tried to get null global");
604 res
= Parrot_find_global_n(interp
, ns
, globalname
);
614 =item C<PMC * Parrot_find_name_op>
616 RT#46171 - THIS IS BROKEN - it doesn't walk up the scopes yet
618 Find the given C<name> in lexicals, then the current namespace, then the HLL
619 root namespace, and finally Parrot builtins. If the name isn't found
620 anywhere, return PMCNULL.
627 PARROT_WARN_UNUSED_RESULT
628 PARROT_CAN_RETURN_NULL
630 Parrot_find_name_op(PARROT_INTERP
, ARGIN(STRING
*name
), SHIM(void *next
))
632 parrot_context_t
* const ctx
= CONTEXT(interp
->ctx
);
633 PMC
* const lex_pad
= Parrot_find_pad(interp
, name
, ctx
);
636 if (PMC_IS_NULL(lex_pad
))
639 g
= VTABLE_get_pmc_keyed_str(interp
, lex_pad
, name
);
641 /* RT#46171 - walk up the scopes! duh!! */
643 if (PMC_IS_NULL(g
)) {
644 g
= Parrot_find_global_cur(interp
, name
);
646 if (PMC_IS_NULL(g
)) {
647 g
= Parrot_find_global_n(interp
,
648 Parrot_get_ctx_HLL_namespace(interp
), name
);
650 if (PMC_IS_NULL(g
)) {
651 g
= Parrot_find_builtin(interp
, name
);
664 =item C<static PMC * get_namespace_pmc>
666 RT#48260: Not yet documented!!!
672 PARROT_WARN_UNUSED_RESULT
673 PARROT_CAN_RETURN_NULL
675 get_namespace_pmc(PARROT_INTERP
, ARGIN(PMC
*sub
))
677 PMC
* const nsname
= PMC_sub(sub
)->namespace_name
;
678 PMC
* const nsroot
= Parrot_get_HLL_namespace(interp
, PMC_sub(sub
)->HLL_id
);
680 /* If we have a NULL, return the HLL namespace */
681 if (PMC_IS_NULL(nsname
))
683 /* If we have a String, do a string lookup */
684 else if (nsname
->vtable
->base_type
== enum_class_String
)
685 return Parrot_make_namespace_keyed_str(interp
, nsroot
, PMC_str_val(nsname
));
686 /* Otherwise, do a PMC lookup */
688 return Parrot_make_namespace_keyed(interp
, nsroot
, nsname
);
693 =item C<static void store_sub_in_multi>
695 RT#48260: Not yet documented!!!
702 store_sub_in_multi(PARROT_INTERP
, ARGIN(PMC
*sub
), ARGIN(PMC
*ns
))
706 STRING
* const subname
= PMC_sub(sub
)->name
;
707 PMC
*multisub
= VTABLE_get_pmc_keyed_str(interp
, ns
, subname
);
709 /* is there an existing MultiSub PMC? or do we need to create one? */
710 if (PMC_IS_NULL(multisub
)) {
711 multisub
= pmc_new(interp
, enum_class_MultiSub
);
712 /* we have to push the sub onto the MultiSub before we try to store
713 it because storing requires information from the sub */
714 VTABLE_push_pmc(interp
, multisub
, sub
);
715 VTABLE_set_pmc_keyed_str(interp
, ns
, subname
, multisub
);
718 VTABLE_push_pmc(interp
, multisub
, sub
);
720 c_meth
= string_to_cstring(interp
, subname
);
721 func_nr
= Parrot_MMD_method_idx(interp
, c_meth
);
723 Parrot_mmd_rebuild_table(interp
, -1, func_nr
);
724 string_cstring_free(c_meth
);
729 =item C<void Parrot_store_sub_in_namespace>
731 RT#48260: Not yet documented!!!
739 Parrot_store_sub_in_namespace(PARROT_INTERP
, ARGIN(PMC
*sub
))
741 const INTVAL cur_id
= CONTEXT(interp
->ctx
)->current_HLL
;
744 /* PF structures aren't fully constructed yet */
745 Parrot_block_DOD(interp
);
746 /* store relative to HLL namespace */
747 CONTEXT(interp
->ctx
)->current_HLL
= PMC_sub(sub
)->HLL_id
;
749 ns
= get_namespace_pmc(interp
, sub
);
751 /* attach a namespace to the sub for lookups */
752 PMC_sub(sub
)->namespace_stash
= ns
;
754 /* store a :multi sub */
755 if (!PMC_IS_NULL(PMC_sub(sub
)->multi_signature
))
756 store_sub_in_multi(interp
, sub
, ns
);
757 /* store other subs (as long as they're not :anon) */
758 else if (!(PObj_get_FLAGS(sub
) & SUB_FLAG_PF_ANON
)) {
759 STRING
* const name
= PMC_sub(sub
)->name
;
760 PMC
* const nsname
= PMC_sub(sub
)->namespace_name
;
762 Parrot_store_global_n(interp
, ns
, name
, sub
);
764 /* TEMPORARY HACK - cache invalidation should be a namespace function */
765 if (!PMC_IS_NULL(nsname
)) {
766 STRING
* const nsname_s
= VTABLE_get_string(interp
, nsname
);
767 Parrot_invalidate_method_cache(interp
, nsname_s
, name
);
772 CONTEXT(interp
->ctx
)->current_HLL
= cur_id
;
773 Parrot_unblock_DOD(interp
);
782 F<include/parrot/global.h>
791 * c-file-style: "parrot"
793 * vim: expandtab shiftwidth=4: