2 Copyright (C) 2004, The Perl Foundation.
7 src/global.c - Access to global PMCs
23 #include "parrot/parrot.h"
26 #define DEBUG_GLOBAL 0
29 * internal_ns_keyed: Internal function to do keyed namespace lookup
30 * relative to a given namespace PMC. Understands STRINGs, String PMCs,
31 * Key pmcs, and array PMCs containing strings.
34 /* flags for internal_ns_keyed */
35 #define INTERN_NS_CREAT 1 /* I'm a fan of the classics */
37 static PMC
* internal_ns_keyed(Interp
*interp
, PMC
*base_ns
, PMC
*pmc_key
,
38 STRING
*str_key
, int flags
)
42 static const INTVAL max_intval
= (INTVAL
)( (~(UINTVAL
)0) >> 1); /*2s comp*/
48 else if (pmc_key
->vtable
->base_type
== enum_class_String
) {
49 str_key
= VTABLE_get_string(interp
, pmc_key
);
52 else if (pmc_key
->vtable
->base_type
== enum_class_Key
)
53 n
= max_intval
; /* we don't yet know how big the key is */
55 n
= VTABLE_elements(interp
, pmc_key
); /* array of strings */
57 for (i
= 0; i
< n
; ++i
) {
62 else if (n
== max_intval
) {
63 part
= key_string(interp
, pmc_key
);
64 pmc_key
= key_next(interp
, pmc_key
);
66 n
= i
+ 1; /* now we know how big the key is */
69 part
= VTABLE_get_string_keyed_int(interp
, pmc_key
, i
);
71 sub_ns
= VTABLE_get_pmc_keyed_str(interp
, ns
, part
);
73 if (PMC_IS_NULL(sub_ns
)
74 /* TODO - stop depending on typed namespace */
75 || sub_ns
->vtable
->base_type
!= enum_class_NameSpace
)
77 if (!(flags
& INTERN_NS_CREAT
))
80 /* TODO - match HLL of enclosing namespace? */
81 sub_ns
= pmc_new(interp
,
82 Parrot_get_ctx_HLL_type(interp
,
83 enum_class_NameSpace
));
84 if (PMC_IS_NULL(sub_ns
))
86 VTABLE_set_pmc_keyed_str(interp
, ns
, part
, sub_ns
);
98 Parrot_get_namespace_keyed(Interp *, PMC *base_ns, PMC *pmc_key)>
100 Find the namespace relative to the namespace C<base_ns> with the key
101 C<pmc_key>, which may be a String, a Key, or an array of strings. Return
102 the namespace, or NULL if not found.
105 Parrot_get_namespace_keyed_str(Interp *, PMC *base_ns, STRING *str_key)>
107 Find the namespace relative to the namespace C<base_ns> with the string key
108 C<str_key>. Return the namespace, or NULL if not found.
111 Parrot_make_namespace_keyed(Interp *, PMC *base_ns, PMC *pmc_key)>
113 Find, or create if necessary, the namespace relative to the namespace
114 C<base_ns> with the key C<pmc_key>, which may be a String, a Key, or an
115 array of strings. Return the namespace. Errors will result in exceptions.
118 Parrot_make_namespace_keyed_str(Interp *, PMC *base_ns, STRING *str_key)>
120 Find, or create if necessary, the namespace relative to the namespace
121 C<base_ns> with the string key C<str_key>. Return the namespace. Errors
122 will result in exceptions.
130 Parrot_get_namespace_keyed(Interp
*interp
, PMC
*base_ns
, PMC
*pmc_key
)
132 return internal_ns_keyed(interp
, base_ns
,
137 Parrot_get_namespace_keyed_str(Interp
*interp
, PMC
*base_ns
, STRING
*str_key
)
139 return internal_ns_keyed(interp
, base_ns
,
140 PMCNULL
, str_key
, 0);
144 Parrot_make_namespace_keyed(Interp
*interp
, PMC
*base_ns
, PMC
*pmc_key
)
146 return internal_ns_keyed(interp
, base_ns
,
147 pmc_key
, NULL
, INTERN_NS_CREAT
);
151 Parrot_make_namespace_keyed_str(Interp
*interp
, PMC
*base_ns
, STRING
*str_key
)
153 return internal_ns_keyed(interp
, base_ns
,
154 NULL
, str_key
, INTERN_NS_CREAT
);
161 Parrot_get_global(Interp *, PMC *ns, STRING *globalname)>
163 Look up the global named C<globalname> in the namespace C<ns>. Return the
164 global, or return PMCNULL if C<ns> is null or if the global is not found.
166 KLUDGE ALERT: Currently prefers non-namespaces in case of collision.
169 Parrot_set_global(Interp *, PMC *ns, STRING *globalname, PMC *val)>
171 Set the global named C<globalname> in the namespace C<ns> to the value C<val>.
178 Parrot_get_global(Interp
*interp
, PMC
*ns
, STRING
*globalname
)
183 return VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
187 Parrot_set_global(Interp
*interp
, PMC
*ns
, STRING
*globalname
, PMC
*val
)
189 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
196 Parrot_find_global_n(Interp *, PMC *ns, STRING *globalname)>
198 Search the namespace PMC C<ns> for an object with name C<globalname>.
199 Return the object, or NULL if not found.
201 XXX - For now this function prefers non-namespaces, it will eventually
202 entirely use the untyped interface.
205 Parrot_find_global_k(Interp *, PMC *pmc_key, STRING *globalname)>
207 Search the namespace designated by C<pmc_key>, which may be a key PMC,
208 an array of namespace name strings, or a string PMC, for an object
209 with name C<globalname>. Return the object, or NULL if not found.
211 XXX - For now this function prefers non-namespaces, it will eventually
212 entirely use the untyped interface.
215 Parrot_find_global_s(Interp *, STRING *str_key, STRING *globalname)>
217 Search the namespace designated by C<str_key>, or the HLL root if
218 C<str_key> is NULL, for an object with name C<globalname>. Return the
219 object, or NULL if not found.
221 XXX - For now this function prefers non-namespaces, it will eventually
222 entirely use the untyped interface.
229 Parrot_find_global_n(Interp
*interpreter
, PMC
*ns
, STRING
*globalname
)
235 PIO_printf(interpreter
, "find_global name '%Ss'\n", globalname
);
242 * XXX - we should be able to use 'get_pmc_keyed' here,
243 * but we can't because Parrot's default namespaces are not
244 * fully typed and there's a pseudo-typed interface that
245 * distinguishes 'get_pmc_keyed' from 'get_pointer_keyed';
246 * the former is for NS and the latter is for non-NS.
248 res
= VTABLE_get_pointer_keyed_str(interpreter
, ns
, globalname
);
251 return PMC_IS_NULL(res
) ? NULL
: res
;
255 Parrot_find_global_cur(Interp
*interpreter
, STRING
*globalname
)
257 PMC
* const ns
= CONTEXT(interpreter
->ctx
)->current_namespace
;
258 return Parrot_find_global_n(interpreter
, ns
, globalname
);
262 Parrot_find_global_k(Interp
*interpreter
, PMC
*pmc_key
, STRING
*globalname
)
265 Parrot_get_namespace_keyed(interpreter
,
266 Parrot_get_ctx_HLL_namespace(interpreter
),
268 return Parrot_find_global_n(interpreter
, ns
, globalname
);
272 Parrot_find_global_s(Interp
*inter
, STRING
*str_key
, STRING
*globalname
)
275 Parrot_get_namespace_keyed_str(inter
,
276 Parrot_get_ctx_HLL_namespace(inter
),
278 return Parrot_find_global_n(inter
, ns
, globalname
);
284 Parrot_store_global_n(Interp *, PMC *ns, STRING *globalname, PMC *val)>
286 Store the PMC C<val> into the namespace PMC C<ns> with name C<globalname>.
289 Parrot_store_global_k(Interp *, PMC *pmc_key, STRING *globalname, PMC *val)>
291 Store the PMC C<val> into the namespace designated by C<pmc_key>,
292 which may be a key PMC, an array of namespace name strings, or a
293 string PMC, with name C<globalname>.
295 XXX - For now this function prefers non-namespaces, it will eventually
296 entirely use the untyped interface.
299 Parrot_store_global_s(Interp *, STRING *str_key, STRING *globalname, PMC *val)>
301 Store the PMC C<val> into the namespace designated by C<str_key>, or
302 the HLL root if C<str_key> is NULL, with the name C<globalname>.
309 Parrot_store_global_n(Interp
*interpreter
, PMC
*ns
,
310 STRING
*globalname
, PMC
*val
)
314 PIO_printf(interpreter
, "store_global name '%Ss'\n", globalname
);
320 VTABLE_set_pmc_keyed_str(interpreter
, ns
, globalname
, val
);
324 Parrot_store_global_cur(Interp
*interpreter
, STRING
*globalname
, PMC
*val
)
326 Parrot_store_global_n(interpreter
,
327 CONTEXT(interpreter
->ctx
)->current_namespace
,
330 /* FIXME - method cache invalidation should occur */
334 Parrot_store_global_k(Interp
*interpreter
, PMC
*pmc_key
,
335 STRING
*globalname
, PMC
*val
)
340 * XXX - temporary hack to notice when key is actually a string, so that
341 * the legacy logic for invalidating method cache will be called; this is
342 * not good enough but it avoids regressesions for now
344 if (pmc_key
->vtable
->base_type
== enum_class_String
) {
345 Parrot_store_global_s(interpreter
, PMC_str_val(pmc_key
),
350 ns
= Parrot_make_namespace_keyed(interpreter
,
351 Parrot_get_ctx_HLL_namespace(interpreter
),
354 Parrot_store_global_n(interpreter
, ns
, globalname
, val
);
356 /* FIXME - method cache invalidation should occur */
360 Parrot_store_global_s(Interp
*inter
, STRING
*str_key
,
361 STRING
*globalname
, PMC
*val
)
365 ns
= Parrot_make_namespace_keyed_str(inter
,
366 Parrot_get_ctx_HLL_namespace(inter
),
369 Parrot_store_global_n(inter
, ns
, globalname
, val
);
371 /* FIXME - method cache invalidation should be a namespace function */
372 Parrot_invalidate_method_cache(inter
, str_key
, globalname
);
379 Parrot_find_global_op(Interp *, PMC *ns, STRING *globalname, void *next)>
381 If the global exists in the given namespace PMC, return it. If not, return
389 Parrot_find_global_op(Interp
*interpreter
, PMC
*ns
,
390 STRING
*globalname
, void *next
)
395 real_exception(interpreter
, next
, E_NameError
,
396 "Tried to get null global");
398 res
= Parrot_find_global_n(interpreter
, ns
, globalname
);
409 Parrot_find_name_op(Interp *, STRING *name, void *next)>
411 TODO - THIS IS BROKEN - it doesn't walk up the scopes yet - TODO
413 Find the given C<name> in lexicals, then the current namespace, then the HLL
414 root namespace, and finally Parrot builtins. If the name isn't found
415 anywhere, return PMCNULL.
422 Parrot_find_name_op(Interp
*interpreter
, STRING
*name
, void *next
)
424 parrot_context_t
* const ctx
= CONTEXT(interpreter
->ctx
);
429 lex_pad
= Parrot_find_pad(interpreter
, name
, ctx
);
430 if (!PMC_IS_NULL(lex_pad
))
431 g
= VTABLE_get_pmc_keyed_str(interpreter
, lex_pad
, name
);
433 /* TODO TODO TODO - walk up the scopes! duh!! */
436 g
= Parrot_find_global_cur(interpreter
, name
);
439 g
= Parrot_find_global_n(interpreter
,
440 Parrot_get_ctx_HLL_namespace(interpreter
),
444 g
= Parrot_find_builtin(interpreter
, name
);
446 if (! PMC_IS_NULL(g
)) {
447 if (g
->vtable
->base_type
== enum_class_MultiSub
&&
448 interpreter
->current_args
) {
450 * inside a function call, we have an args signature
452 g
= Parrot_MMD_search_default_func(interpreter
, name
);
453 if (! PMC_IS_NULL(g
))
467 * FIXME - This should not be here!
468 * It's generic logic that should apply whenever a Sub is stored anywhere,
469 * and since lots of things can be invoked, maybe more than just Subs.
470 * Where it _should_ be, I don't know for sure.
472 * if pmc_key is provided, it wins.
473 * else if str_key is provided, it is used.
474 * if neither is provided, the HLL namespace is used.
478 store_sub(Interp
*interpreter
, PMC
*pmc_key
, STRING
*str_key
,
479 STRING
*sub_name
, PMC
*sub_pmc
)
484 if (sub_pmc
->vtable
->base_type
== enum_class_MultiSub
) {
487 one_sub
= VTABLE_get_pmc_keyed_int(interpreter
, sub_pmc
, 0);
488 hll_id
= PMC_sub(one_sub
)->HLL_id
;
491 hll_id
= PMC_sub(sub_pmc
)->HLL_id
;
493 ns
= Parrot_get_HLL_namespace(interpreter
, hll_id
);
494 if (!PMC_IS_NULL(pmc_key
))
495 ns
= Parrot_make_namespace_keyed(interpreter
, ns
, pmc_key
);
497 ns
= Parrot_make_namespace_keyed_str(interpreter
, ns
, str_key
);
499 Parrot_store_global_n(interpreter
, ns
, sub_name
, sub_pmc
);
501 /* TEMPORARY HACK - cache invalidation should be a namespace function */
502 if (! PMC_IS_NULL(pmc_key
)) {
503 if (pmc_key
->vtable
->base_type
== enum_class_String
)
504 Parrot_invalidate_method_cache(interpreter
,
505 PMC_str_val(pmc_key
), sub_name
);
508 Parrot_invalidate_method_cache(interpreter
, str_key
, sub_name
);
510 /* MultiSub isa R*PMCArray and doesn't have a PMC_sub structure
511 * MultiSub could also contain subs from various namespaces,
512 * so it doesn't make much sense to associate a namespace
515 if (sub_pmc
->vtable
->base_type
!= enum_class_MultiSub
)
516 PMC_sub(sub_pmc
)->namespace_stash
= ns
;
520 store_sub_in_namespace(Parrot_Interp interpreter
, PMC
* sub_pmc
,
521 PMC
*pmc_key
, STRING
*sub_name
)
524 * pmc_key is either a String, or a Key, or NULL
526 if (PMC_IS_NULL(pmc_key
))
527 store_sub(interpreter
, PMCNULL
, NULL
, sub_name
, sub_pmc
);
529 INTVAL type
= pmc_key
->vtable
->base_type
;
531 case enum_class_String
:
532 store_sub(interpreter
, PMCNULL
, PMC_str_val(pmc_key
),
536 store_sub(interpreter
, pmc_key
, NULL
, sub_name
, sub_pmc
);
539 internal_exception(1,
540 "Namespace constant is neither "
547 STRING
* Parrot_multi_long_name(Parrot_Interp interpreter
, PMC
* sub_pmc
);
550 Parrot_multi_long_name(Parrot_Interp interpreter
, PMC
* sub_pmc
)
553 STRING
* sub_name
, *sig
;
556 sub_name
= PMC_sub(sub_pmc
)->name
;
557 multi_sig
= PMC_sub(sub_pmc
)->multi_signature
;
558 n
= VTABLE_elements(interpreter
, multi_sig
);
560 * foo :multi(STRING, Integer) =>
562 * foo_@STRING_@Integer
564 for (i
= 0; i
< n
; ++i
) {
565 sig
= VTABLE_get_string_keyed_int(interpreter
, multi_sig
, i
);
566 sub_name
= string_concat(interpreter
, sub_name
,
567 const_string(interpreter
, "_@"), 0);
568 sub_name
= string_concat(interpreter
, sub_name
, sig
, 0);
574 store_named_in_namespace(Parrot_Interp interpreter
, PMC
* sub_pmc
)
582 sub_name
= PMC_sub(sub_pmc
)->name
;
583 namespace = PMC_sub(sub_pmc
)->namespace;
584 multi_sig
= PMC_sub(sub_pmc
)->multi_signature
;
586 if (PMC_IS_NULL(multi_sig
)) {
587 store_sub_in_namespace(interpreter
, sub_pmc
, namespace, sub_name
);
594 /* If namespace is NULL, we need to look in the root HLL namespace. But
595 since we haven't actually run code yet, the context hasn't been set
596 to include the HLL, so we have to do the work ourselves. */
597 stash
= Parrot_get_HLL_namespace(interpreter
, PMC_sub(sub_pmc
)->HLL_id
);
598 if (! PMC_IS_NULL(namespace))
599 stash
= VTABLE_get_pmc_keyed(interpreter
, stash
, namespace);
600 multi_sub
= PMC_IS_NULL(stash
)
602 : VTABLE_get_pmc_keyed_str(interpreter
, stash
, sub_name
);
604 /* is there an existing MultiSub PMC? or do we need to create one? */
605 if (PMC_IS_NULL(multi_sub
)) {
606 multi_sub
= pmc_new(interpreter
, enum_class_MultiSub
);
607 /* we have to push the sub onto the MultiSub before we try to store
608 it because storing requires information from the sub */
609 VTABLE_push_pmc(interpreter
, multi_sub
, sub_pmc
);
610 store_sub_in_namespace(interpreter
, multi_sub
,
611 namespace, sub_name
);
614 VTABLE_push_pmc(interpreter
, multi_sub
, sub_pmc
);
616 long_name
= Parrot_multi_long_name(interpreter
, sub_pmc
);
617 store_sub_in_namespace(interpreter
, sub_pmc
, namespace, long_name
);
619 c_meth
= string_to_cstring(interpreter
, sub_name
);
620 if ( (func_nr
= Parrot_MMD_method_idx(interpreter
, c_meth
)) >= 0) {
621 Parrot_mmd_rebuild_table(interpreter
, -1, func_nr
);
623 string_cstring_free(c_meth
);
627 /* TODO - this looks like it doesn't understand nested namespaces */
630 Parrot_store_sub_in_namespace(Parrot_Interp interpreter
, PMC
*sub
)
632 if (!(PObj_get_FLAGS(sub
) & SUB_FLAG_PF_ANON
)) {
633 INTVAL cur_id
= CONTEXT(interpreter
->ctx
)->current_HLL
;
634 /* PF structures aren't fully constructed yet */
635 Parrot_block_DOD(interpreter
);
636 /* store relative to HLL namespace */
637 CONTEXT(interpreter
->ctx
)->current_HLL
= PMC_sub(sub
)->HLL_id
;
639 store_named_in_namespace(interpreter
, sub
);
642 CONTEXT(interpreter
->ctx
)->current_HLL
= cur_id
;
643 Parrot_unblock_DOD(interpreter
);
647 Parrot_get_HLL_namespace(interpreter
, PMC_sub(sub
)->HLL_id
);
648 PMC_sub(sub
)->namespace_stash
= stash
;
657 F<include/parrot/global.h>
666 * c-file-style: "parrot"
668 * vim: expandtab shiftwidth=4: