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_namespace_autobase(Interp *, PMC *key)>
163 Find a namespace with the key C<key>, which may be a String, a Key, or an
164 array of strings. If it is a String, then the lookup is relative to the
165 current namespace. Otherwise, it is relative to the current HLL root
166 namespace. Return the namespace, or NULL if not found.
169 Parrot_make_namespace_autobase(Interp *, PMC *pmc_key)>
171 Find, or create if necessary, a namespace with the key C<key>, which may be a
172 String, a Key, or an array of strings. If it is a String, then the lookup is
173 relative to the current namespace. Otherwise, it is relative to the current HLL
174 root namespace. Return the namespace. Errors will result in exceptions.
182 Parrot_make_namespace_autobase(Interp
*interp
, PMC
*key
)
185 if (VTABLE_isa(interp
, key
, string_from_const_cstring(interp
, "String", 0)))
186 base_ns
= CONTEXT(interp
->ctx
)->current_namespace
;
188 base_ns
= VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
,
189 CONTEXT(interp
->ctx
)->current_HLL
);
190 return Parrot_make_namespace_keyed(interp
, base_ns
, key
);
194 Parrot_get_namespace_autobase(Interp
*interp
, PMC
*key
)
197 if (VTABLE_isa(interp
, key
, string_from_const_cstring(interp
, "String", 0)))
198 base_ns
= CONTEXT(interp
->ctx
)->current_namespace
;
200 base_ns
= VTABLE_get_pmc_keyed_int(interp
, interp
->HLL_namespace
,
201 CONTEXT(interp
->ctx
)->current_HLL
);
202 return Parrot_get_namespace_keyed(interp
, base_ns
, key
);
209 Parrot_get_global(Interp *, PMC *ns, STRING *globalname)>
211 Look up the global named C<globalname> in the namespace C<ns>. Return the
212 global, or return PMCNULL if C<ns> is null or if the global is not found.
214 KLUDGE ALERT: Currently prefers non-namespaces in case of collision.
217 Parrot_set_global(Interp *, PMC *ns, STRING *globalname, PMC *val)>
219 Set the global named C<globalname> in the namespace C<ns> to the value C<val>.
226 Parrot_get_global(Interp
*interp
, PMC
*ns
, STRING
*globalname
)
231 return (PMC
*)VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
235 Parrot_set_global(Interp
*interp
, PMC
*ns
, STRING
*globalname
, PMC
*val
)
237 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
244 Parrot_find_global_n(Interp *, PMC *ns, STRING *globalname)>
246 Search the namespace PMC C<ns> for an object with name C<globalname>.
247 Return the object, or NULL if not found.
249 XXX - For now this function prefers non-namespaces, it will eventually
250 entirely use the untyped interface.
253 Parrot_find_global_k(Interp *, PMC *pmc_key, STRING *globalname)>
255 Search the namespace designated by C<pmc_key>, which may be a key PMC,
256 an array of namespace name strings, or a string PMC, for an object
257 with name C<globalname>. Return the object, or NULL if not found.
259 XXX - For now this function prefers non-namespaces, it will eventually
260 entirely use the untyped interface.
263 Parrot_find_global_s(Interp *, STRING *str_key, STRING *globalname)>
265 Search the namespace designated by C<str_key>, or the HLL root if
266 C<str_key> is NULL, for an object with name C<globalname>. Return the
267 object, or NULL if not found.
269 XXX - For now this function prefers non-namespaces, it will eventually
270 entirely use the untyped interface.
277 Parrot_find_global_n(Interp
*interp
, PMC
*ns
, STRING
*globalname
)
283 PIO_printf(interp
, "find_global name '%Ss'\n", globalname
);
290 * XXX - we should be able to use 'get_pmc_keyed' here,
291 * but we can't because Parrot's default namespaces are not
292 * fully typed and there's a pseudo-typed interface that
293 * distinguishes 'get_pmc_keyed' from 'get_pointer_keyed';
294 * the former is for NS and the latter is for non-NS.
296 res
= (PMC
*)VTABLE_get_pointer_keyed_str(interp
, ns
, globalname
);
299 return PMC_IS_NULL(res
) ? NULL
: res
;
303 Parrot_find_global_cur(Interp
*interp
, STRING
*globalname
)
305 PMC
* const ns
= CONTEXT(interp
->ctx
)->current_namespace
;
306 return Parrot_find_global_n(interp
, ns
, globalname
);
310 Parrot_find_global_k(Interp
*interp
, PMC
*pmc_key
, STRING
*globalname
)
313 Parrot_get_namespace_keyed(interp
,
314 Parrot_get_ctx_HLL_namespace(interp
),
316 return Parrot_find_global_n(interp
, ns
, globalname
);
320 Parrot_find_global_s(Interp
*inter
, STRING
*str_key
, STRING
*globalname
)
323 Parrot_get_namespace_keyed_str(inter
,
324 Parrot_get_ctx_HLL_namespace(inter
),
326 return Parrot_find_global_n(inter
, ns
, globalname
);
332 Parrot_store_global_n(Interp *, PMC *ns, STRING *globalname, PMC *val)>
334 Store the PMC C<val> into the namespace PMC C<ns> with name C<globalname>.
337 Parrot_store_global_k(Interp *, PMC *pmc_key, STRING *globalname, PMC *val)>
339 Store the PMC C<val> into the namespace designated by C<pmc_key>,
340 which may be a key PMC, an array of namespace name strings, or a
341 string PMC, with name C<globalname>.
343 XXX - For now this function prefers non-namespaces, it will eventually
344 entirely use the untyped interface.
347 Parrot_store_global_s(Interp *, STRING *str_key, STRING *globalname, PMC *val)>
349 Store the PMC C<val> into the namespace designated by C<str_key>, or
350 the HLL root if C<str_key> is NULL, with the name C<globalname>.
357 Parrot_store_global_n(Interp
*interp
, PMC
*ns
,
358 STRING
*globalname
, PMC
*val
)
362 PIO_printf(interp
, "store_global name '%Ss'\n", globalname
);
368 VTABLE_set_pmc_keyed_str(interp
, ns
, globalname
, val
);
372 Parrot_store_global_cur(Interp
*interp
, STRING
*globalname
, PMC
*val
)
374 Parrot_store_global_n(interp
,
375 CONTEXT(interp
->ctx
)->current_namespace
,
378 /* FIXME - method cache invalidation should occur */
382 Parrot_store_global_k(Interp
*interp
, PMC
*pmc_key
,
383 STRING
*globalname
, PMC
*val
)
388 * XXX - temporary hack to notice when key is actually a string, so that
389 * the legacy logic for invalidating method cache will be called; this is
390 * not good enough but it avoids regressesions for now
392 if (pmc_key
->vtable
->base_type
== enum_class_String
) {
393 Parrot_store_global_s(interp
, PMC_str_val(pmc_key
),
398 ns
= Parrot_make_namespace_keyed(interp
,
399 Parrot_get_ctx_HLL_namespace(interp
),
402 Parrot_store_global_n(interp
, ns
, globalname
, val
);
404 /* FIXME - method cache invalidation should occur */
408 Parrot_store_global_s(Interp
*inter
, STRING
*str_key
,
409 STRING
*globalname
, PMC
*val
)
413 ns
= Parrot_make_namespace_keyed_str(inter
,
414 Parrot_get_ctx_HLL_namespace(inter
),
417 Parrot_store_global_n(inter
, ns
, globalname
, val
);
419 /* FIXME - method cache invalidation should be a namespace function */
420 Parrot_invalidate_method_cache(inter
, str_key
, globalname
);
427 Parrot_find_global_op(Interp *, PMC *ns, STRING *globalname, void *next)>
429 If the global exists in the given namespace PMC, return it. If not, return
437 Parrot_find_global_op(Interp
*interp
, PMC
*ns
,
438 STRING
*globalname
, void *next
)
443 real_exception(interp
, next
, E_NameError
,
444 "Tried to get null global");
446 res
= Parrot_find_global_n(interp
, ns
, globalname
);
457 Parrot_find_name_op(Interp *, STRING *name, void *next)>
459 TODO - THIS IS BROKEN - it doesn't walk up the scopes yet - TODO
461 Find the given C<name> in lexicals, then the current namespace, then the HLL
462 root namespace, and finally Parrot builtins. If the name isn't found
463 anywhere, return PMCNULL.
470 Parrot_find_name_op(Interp
*interp
, STRING
*name
, void *next
)
472 parrot_context_t
* const ctx
= CONTEXT(interp
->ctx
);
477 lex_pad
= Parrot_find_pad(interp
, name
, ctx
);
478 if (!PMC_IS_NULL(lex_pad
))
479 g
= VTABLE_get_pmc_keyed_str(interp
, lex_pad
, name
);
481 /* TODO TODO TODO - walk up the scopes! duh!! */
484 g
= Parrot_find_global_cur(interp
, name
);
487 g
= Parrot_find_global_n(interp
,
488 Parrot_get_ctx_HLL_namespace(interp
),
492 g
= Parrot_find_builtin(interp
, name
);
494 if (! PMC_IS_NULL(g
))
501 get_namespace_pmc(Parrot_Interp interp
, PMC
*sub
)
503 PMC
*nsname
= PMC_sub(sub
)->namespace_name
;
504 PMC
*nsroot
= Parrot_get_HLL_namespace(interp
, PMC_sub(sub
)->HLL_id
);
506 /* If we have a NULL, return the HLL namespace */
507 if (PMC_IS_NULL(nsname
))
509 /* If we have a String, do a string lookup */
510 else if (nsname
->vtable
->base_type
== enum_class_String
)
511 return Parrot_make_namespace_keyed_str(interp
, nsroot
, PMC_str_val(nsname
));
512 /* Otherwise, do a PMC lookup */
514 return Parrot_make_namespace_keyed(interp
, nsroot
, nsname
);
518 store_sub_in_multi(Parrot_Interp interp
, PMC
*sub
, PMC
*ns
)
522 STRING
*subname
= PMC_sub(sub
)->name
;
523 PMC
*multisub
= VTABLE_get_pmc_keyed_str(interp
, ns
, subname
);
525 /* is there an existing MultiSub PMC? or do we need to create one? */
526 if (PMC_IS_NULL(multisub
)) {
527 multisub
= pmc_new(interp
, enum_class_MultiSub
);
528 /* we have to push the sub onto the MultiSub before we try to store
529 it because storing requires information from the sub */
530 VTABLE_push_pmc(interp
, multisub
, sub
);
531 VTABLE_set_pmc_keyed_str(interp
, ns
, subname
, multisub
);
534 VTABLE_push_pmc(interp
, multisub
, sub
);
536 c_meth
= string_to_cstring(interp
, subname
);
537 if ((func_nr
= Parrot_MMD_method_idx(interp
, c_meth
)) >= 0) {
538 Parrot_mmd_rebuild_table(interp
, -1, func_nr
);
540 string_cstring_free(c_meth
);
544 Parrot_store_sub_in_namespace(Parrot_Interp interp
, PMC
*sub
)
546 INTVAL cur_id
= CONTEXT(interp
->ctx
)->current_HLL
;
548 /* PF structures aren't fully constructed yet */
549 Parrot_block_DOD(interp
);
550 /* store relative to HLL namespace */
551 CONTEXT(interp
->ctx
)->current_HLL
= PMC_sub(sub
)->HLL_id
;
553 ns
= get_namespace_pmc(interp
, sub
);
555 /* attach a namespace to the sub for lookups */
556 PMC_sub(sub
)->namespace_stash
= ns
;
558 /* store a :multi sub */
559 if (!PMC_IS_NULL(PMC_sub(sub
)->multi_signature
))
560 store_sub_in_multi(interp
, sub
, ns
);
561 /* store other subs (as long as they're not :anon) */
562 else if (!(PObj_get_FLAGS(sub
) & SUB_FLAG_PF_ANON
)) {
563 STRING
*name
= PMC_sub(sub
)->name
;
564 PMC
*nsname
= PMC_sub(sub
)->namespace_name
;
566 Parrot_store_global_n(interp
, ns
, name
, sub
);
568 /* TEMPORARY HACK - cache invalidation should be a namespace function */
569 if (!PMC_IS_NULL(nsname
))
571 STRING
*nsname_s
= VTABLE_get_string(interp
, nsname
);
572 Parrot_invalidate_method_cache(interp
, nsname_s
, name
);
577 CONTEXT(interp
->ctx
)->current_HLL
= cur_id
;
578 Parrot_unblock_DOD(interp
);
586 F<include/parrot/global.h>
595 * c-file-style: "parrot"
597 * vim: expandtab shiftwidth=4: