1 /*
2 Copyright (C) 2004-2010, Parrot Foundation.
3
4 =head1 NAME
5
6 src/namespace.c
7
8 =head1 DESCRIPTION
9
10 Common routines for storing and finding elements in namespaces
11
12 =cut
13
14 */
15
16 #include "parrot/parrot.h"
17 #include "namespace.str"
18 #include "pmc/pmc_sub.h"
19 #include "pmc/pmc_callcontext.h"
20
21 /* HEADERIZER HFILE: include/parrot/namespace.h */
22 /* HEADERIZER BEGIN: static */
23 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
24
25 PARROT_WARN_UNUSED_RESULT
26 PARROT_CANNOT_RETURN_NULL
27 static PMC * get_namespace_pmc(PARROT_INTERP, ARGIN(PMC *sub_pmc))
28 __attribute__nonnull__(1)
29 __attribute__nonnull__(2);
30
31 PARROT_WARN_UNUSED_RESULT
32 PARROT_CANNOT_RETURN_NULL
33 static PMC * internal_ns_keyed(PARROT_INTERP,
34 ARGIN(PMC *base_ns),
35 ARGIN(PMC *pmc_key),
36 int flags)
37 __attribute__nonnull__(1)
38 __attribute__nonnull__(2)
39 __attribute__nonnull__(3);
40
41 PARROT_WARN_UNUSED_RESULT
42 PARROT_CANNOT_RETURN_NULL
43 static PMC * internal_ns_keyed_key(PARROT_INTERP,
44 ARGIN(PMC *ns),
45 ARGIN(PMC *key),
46 int flags)
47 __attribute__nonnull__(1)
48 __attribute__nonnull__(2)
49 __attribute__nonnull__(3);
50
51 PARROT_WARN_UNUSED_RESULT
52 PARROT_CANNOT_RETURN_NULL
53 static PMC * internal_ns_keyed_str(PARROT_INTERP,
54 ARGIN(PMC *base_ns),
55 ARGIN(STRING *key),
56 int flags)
57 __attribute__nonnull__(1)
58 __attribute__nonnull__(2)
59 __attribute__nonnull__(3);
60
61 PARROT_WARN_UNUSED_RESULT
62 PARROT_CANNOT_RETURN_NULL
63 static PMC * internal_ns_maybe_create(PARROT_INTERP,
64 ARGIN(PMC *ns),
65 ARGIN(STRING *key),
66 int flags)
67 __attribute__nonnull__(1)
68 __attribute__nonnull__(2)
69 __attribute__nonnull__(3);
70
71 static void store_sub_in_multi(PARROT_INTERP,
72 ARGIN(PMC *sub_pmc),
73 ARGIN(PMC *ns))
74 __attribute__nonnull__(1)
75 __attribute__nonnull__(2)
76 __attribute__nonnull__(3);
77
78 #define ASSERT_ARGS_get_namespace_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
79 PARROT_ASSERT_ARG(interp) \
80 , PARROT_ASSERT_ARG(sub_pmc))
81 #define ASSERT_ARGS_internal_ns_keyed __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
82 PARROT_ASSERT_ARG(interp) \
83 , PARROT_ASSERT_ARG(base_ns) \
84 , PARROT_ASSERT_ARG(pmc_key))
85 #define ASSERT_ARGS_internal_ns_keyed_key __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
86 PARROT_ASSERT_ARG(interp) \
87 , PARROT_ASSERT_ARG(ns) \
88 , PARROT_ASSERT_ARG(key))
89 #define ASSERT_ARGS_internal_ns_keyed_str __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
90 PARROT_ASSERT_ARG(interp) \
91 , PARROT_ASSERT_ARG(base_ns) \
92 , PARROT_ASSERT_ARG(key))
93 #define ASSERT_ARGS_internal_ns_maybe_create __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
94 PARROT_ASSERT_ARG(interp) \
95 , PARROT_ASSERT_ARG(ns) \
96 , PARROT_ASSERT_ARG(key))
97 #define ASSERT_ARGS_store_sub_in_multi __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
98 PARROT_ASSERT_ARG(interp) \
99 , PARROT_ASSERT_ARG(sub_pmc) \
100 , PARROT_ASSERT_ARG(ns))
101 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
102 /* HEADERIZER END: static */
103
104 /* flags for internal_ns_keyed */
105 #define INTERN_NS_CREAT 1 /* I'm a fan of the classics */
106
107 /*
108
109 =head1 Internal Static Functions
110
111 =over 4
112
113 =item C<static PMC * internal_ns_keyed_str(PARROT_INTERP, PMC *base_ns, STRING
114 *key, int flags)>
115
116 Looks up a nested NameSpace PMC starting from C<base_ns> and doing a relative
117 lookup. C<key> is a STRING containing the name of the NameSpace to look up.
118 Flags can be 0 or INTERN_NS_CREAT. In the former case, PMCNULL is returned
119 if the namespace is not found. In the later, a new namespace with the given
120 is created and returned if it is not found.
121
122 =cut
123
124 */
125
126 PARROT_WARN_UNUSED_RESULT
127 PARROT_CANNOT_RETURN_NULL
128 static PMC *
internal_ns_keyed_str(PARROT_INTERP,ARGIN (PMC * base_ns),ARGIN (STRING * key),int flags)129 internal_ns_keyed_str(PARROT_INTERP, ARGIN(PMC *base_ns),
130 ARGIN(STRING *key), int flags)
131 {
132 ASSERT_ARGS(internal_ns_keyed_str)
133 PMC * const ns = VTABLE_get_pmc_keyed_str(interp, base_ns, key);
134 STRING * const namesp = CONST_STRING(interp, "NameSpace");
135
136 if (!PMC_IS_NULL(ns)
137 && (ns->vtable->base_type == enum_class_NameSpace
138 || VTABLE_isa(interp, ns, namesp)))
139 return ns;
140
141 return internal_ns_maybe_create(interp, base_ns, key, flags);
142 }
143
144 /*
145
146 =item C<static PMC * internal_ns_keyed_key(PARROT_INTERP, PMC *ns, PMC *key, int
147 flags)>
148
149 Internal function to do keyed namespace lookup relative to a given namespace
150 PMC. The namespace to find is located by C<key> relative to C<ns>. C<flags>
151 determines what happens when an existing namespace is not found. 0 means
152 PMCNULL is returned, INTERN_NS_CREAT means a new namespace is created.
153
154 =cut
155
156 */
157
158 PARROT_WARN_UNUSED_RESULT
159 PARROT_CANNOT_RETURN_NULL
160 static PMC *
internal_ns_keyed_key(PARROT_INTERP,ARGIN (PMC * ns),ARGIN (PMC * key),int flags)161 internal_ns_keyed_key(PARROT_INTERP, ARGIN(PMC *ns), ARGIN(PMC *key), int flags)
162 {
163 ASSERT_ARGS(internal_ns_keyed_key)
164 while (key) {
165 STRING * const part = VTABLE_get_string(interp, key);
166 PMC *sub_ns = VTABLE_get_pmc_keyed_str(interp, ns, part);
167
168 if (PMC_IS_NULL(sub_ns) || !VTABLE_isa(interp, sub_ns, CONST_STRING(interp, "NameSpace"))) {
169 sub_ns = internal_ns_maybe_create(interp, ns, part, flags);
170
171 if (PMC_IS_NULL(sub_ns))
172 return PMCNULL;
173 }
174
175 ns = sub_ns;
176 key = VTABLE_shift_pmc(interp, key);
177 }
178
179 return ns;
180 }
181
182 /*
183
184 =item C<static PMC * internal_ns_keyed(PARROT_INTERP, PMC *base_ns, PMC
185 *pmc_key, int flags)>
186
187 Search for a namespace PMC starting from a base namespace C<base_ns> and
188 following C<pmc_key> to the nested namespace. C<pmc_key> can be a String,
189 a Key, or an array of strings (such as an ResizableStringArray, or a
190 ResizablePMCArray that contains Strings). Flags determines what we do if the
191 requested namespace is not found: 0 means we return PMCNULL, INTERN_NS_CREAT
192 means we create the new namespace and return it.
193
194 =cut
195
196 */
197
198 PARROT_WARN_UNUSED_RESULT
199 PARROT_CANNOT_RETURN_NULL
200 static PMC *
internal_ns_keyed(PARROT_INTERP,ARGIN (PMC * base_ns),ARGIN (PMC * pmc_key),int flags)201 internal_ns_keyed(PARROT_INTERP, ARGIN(PMC *base_ns), ARGIN(PMC *pmc_key), int flags)
202 {
203 ASSERT_ARGS(internal_ns_keyed)
204
205 if (PMC_IS_TYPE(pmc_key, Key))
206 return internal_ns_keyed_key(interp, base_ns, pmc_key, flags);
207 else if (VTABLE_isa(interp, pmc_key, CONST_STRING(interp, "String"))) {
208 STRING * const str_key = VTABLE_get_string(interp, pmc_key);
209 return internal_ns_keyed_str(interp, base_ns, str_key, flags);
210 }
211 else {
212 /* array of strings */
213 STRING * const isans = CONST_STRING(interp, "NameSpace");
214 const INTVAL n = VTABLE_elements(interp, pmc_key);
215 INTVAL i;
216 PMC *ns = base_ns;
217
218 for (i = 0; i < n; ++i) {
219 STRING * const part = VTABLE_get_string_keyed_int(interp, pmc_key, i);
220 PMC *sub_ns = VTABLE_get_pmc_keyed_str(interp, ns, part);
221
222 if (PMC_IS_NULL(sub_ns) || !VTABLE_isa(interp, sub_ns, isans)) {
223 sub_ns = internal_ns_maybe_create(interp, ns, part, flags);
224 if (PMC_IS_NULL(sub_ns))
225 return PMCNULL;
226 }
227 ns = sub_ns;
228 }
229 return ns;
230 }
231 }
232
233 /*
234
235 =item C<static PMC * internal_ns_maybe_create(PARROT_INTERP, PMC *ns, STRING
236 *key, int flags)>
237
238 Given a namespace PMC C<ns>, a STRING C<key> containing a name, and flags from
239 C<internal_ns_keyed> or C<internal_ns_keyed_str>, creates and returns a new
240 namespace with the given name as a child of the given namespace. This is an
241 internal function only.
242
243 =cut
244
245 */
246
247 PARROT_WARN_UNUSED_RESULT
248 PARROT_CANNOT_RETURN_NULL
249 static PMC *
internal_ns_maybe_create(PARROT_INTERP,ARGIN (PMC * ns),ARGIN (STRING * key),int flags)250 internal_ns_maybe_create(PARROT_INTERP, ARGIN(PMC *ns), ARGIN(STRING *key), int flags)
251 {
252 ASSERT_ARGS(internal_ns_maybe_create)
253
254 /* TT #1220 - stop depending on typed namespace */
255 if (!(flags & INTERN_NS_CREAT))
256 return PMCNULL;
257 else {
258 const INTVAL type_id = Parrot_hll_get_ctx_HLL_type(interp, enum_class_NameSpace);
259 /* TT #1221 - match HLL of enclosing namespace? */
260 PMC * const sub_ns = Parrot_pmc_new(interp, type_id);
261
262 if (PMC_IS_NULL(sub_ns))
263 return PMCNULL;
264
265 VTABLE_set_pmc_keyed_str(interp, ns, key, sub_ns);
266 return sub_ns;
267 }
268 }
269
270 /*
271
272 =item C<static PMC * get_namespace_pmc(PARROT_INTERP, PMC *sub_pmc)>
273
274 Return the namespace PMC associated with the PMC C<sub>. If there is no
275 NameSpace associated with the sub, return it's HLL NameSpace PMC instead.
276
277 =cut
278
279 */
280
281 PARROT_WARN_UNUSED_RESULT
282 PARROT_CANNOT_RETURN_NULL
283 static PMC *
get_namespace_pmc(PARROT_INTERP,ARGIN (PMC * sub_pmc))284 get_namespace_pmc(PARROT_INTERP, ARGIN(PMC *sub_pmc))
285 {
286 ASSERT_ARGS(get_namespace_pmc)
287 Parrot_Sub_attributes *sub;
288 PMC *nsname, *nsroot;
289
290 PMC_get_sub(interp, sub_pmc, sub);
291 nsname = sub->namespace_name;
292 nsroot = Parrot_hll_get_HLL_namespace(interp, sub->HLL_id);
293
294 /* If we have a NULL, return the HLL namespace */
295 if (PMC_IS_NULL(nsname))
296 return nsroot;
297 /* If we have a String, do a string lookup */
298 else if (nsname->vtable->base_type == enum_class_String)
299 return Parrot_ns_make_namespace_keyed_str(interp, nsroot,
300 VTABLE_get_string(interp, nsname));
301 /* Otherwise, do a PMC lookup */
302 else
303 return Parrot_ns_make_namespace_keyed(interp, nsroot, nsname);
304 }
305
306 /*
307
308 =item C<static void store_sub_in_multi(PARROT_INTERP, PMC *sub_pmc, PMC *ns)>
309
310 Adds the sub C<sub> into a multisub of the same name in the namespace C<ns>.
311 If no multisub by that name currently exists, we create one.
312
313 =cut
314
315 */
316
317 static void
store_sub_in_multi(PARROT_INTERP,ARGIN (PMC * sub_pmc),ARGIN (PMC * ns))318 store_sub_in_multi(PARROT_INTERP, ARGIN(PMC *sub_pmc), ARGIN(PMC *ns))
319 {
320 ASSERT_ARGS(store_sub_in_multi)
321 Parrot_Sub_attributes *sub;
322 STRING *ns_entry_name;
323 PMC *multisub;
324
325 PMC_get_sub(interp, sub_pmc, sub);
326 ns_entry_name = sub->ns_entry_name;
327 multisub = VTABLE_get_pmc_keyed_str(interp, ns, ns_entry_name);
328
329 /* is there an existing MultiSub PMC? or do we need to create one? */
330 if (PMC_IS_NULL(multisub)) {
331 multisub = Parrot_pmc_new(interp,
332 Parrot_hll_get_ctx_HLL_type(interp, enum_class_MultiSub));
333 /* we have to push the sub onto the MultiSub before we try to store
334 it because storing requires information from the sub */
335 VTABLE_push_pmc(interp, multisub, sub_pmc);
336 VTABLE_set_pmc_keyed_str(interp, ns, ns_entry_name, multisub);
337 }
338 else
339 VTABLE_push_pmc(interp, multisub, sub_pmc);
340 }
341
342 /*
343
344 =back
345
346 =head1 NameSpace API Functions
347
348 =over 4
349
350 =item C<PMC * Parrot_ns_get_namespace_keyed(PARROT_INTERP, PMC *base_ns, PMC
351 *pmc_key)>
352
353 Find the namespace relative to the namespace C<base_ns> with the key
354 C<pmc_key>, which may be a String, a Key, or an array of strings. Return
355 the namespace, or NULL if not found.
356
357 =cut
358
359 */
360
361 PARROT_EXPORT
362 PARROT_WARN_UNUSED_RESULT
363 PARROT_CANNOT_RETURN_NULL
364 PMC *
Parrot_ns_get_namespace_keyed(PARROT_INTERP,ARGIN (PMC * base_ns),ARGIN (PMC * pmc_key))365 Parrot_ns_get_namespace_keyed(PARROT_INTERP, ARGIN(PMC *base_ns), ARGIN(PMC *pmc_key))
366 {
367 ASSERT_ARGS(Parrot_ns_get_namespace_keyed)
368 return internal_ns_keyed(interp, base_ns, pmc_key, 0);
369 }
370
371 /*
372
373 =item C<PMC * Parrot_ns_get_namespace_keyed_str(PARROT_INTERP, PMC *base_ns,
374 STRING *str_key)>
375
376 Find the namespace relative to the namespace C<base_ns> with the string key
377 C<str_key>. Return the namespace, or NULL if not found.
378
379 =cut
380
381 */
382
383 PARROT_EXPORT
384 PARROT_WARN_UNUSED_RESULT
385 PARROT_CANNOT_RETURN_NULL
386 PMC *
Parrot_ns_get_namespace_keyed_str(PARROT_INTERP,ARGIN (PMC * base_ns),ARGIN_NULLOK (STRING * str_key))387 Parrot_ns_get_namespace_keyed_str(PARROT_INTERP, ARGIN(PMC *base_ns),
388 ARGIN_NULLOK(STRING *str_key))
389 {
390 ASSERT_ARGS(Parrot_ns_get_namespace_keyed_str)
391 return internal_ns_keyed_str(interp, base_ns, str_key, 0);
392 }
393
394 /*
395
396 =item C<PMC * Parrot_ns_make_namespace_keyed(PARROT_INTERP, PMC *base_ns, PMC
397 *pmc_key)>
398
399 Find, or create if necessary, the namespace relative to the namespace
400 C<base_ns> with the key C<pmc_key>, which may be a String, a Key, or an
401 array of strings. Return the namespace. Errors will result in exceptions.
402
403 =cut
404
405 */
406
407 PARROT_EXPORT
408 PARROT_WARN_UNUSED_RESULT
409 PARROT_CANNOT_RETURN_NULL
410 PMC *
Parrot_ns_make_namespace_keyed(PARROT_INTERP,ARGIN (PMC * base_ns),ARGIN (PMC * pmc_key))411 Parrot_ns_make_namespace_keyed(PARROT_INTERP, ARGIN(PMC *base_ns),
412 ARGIN(PMC *pmc_key))
413 {
414 ASSERT_ARGS(Parrot_ns_make_namespace_keyed)
415 return internal_ns_keyed(interp, base_ns, pmc_key, INTERN_NS_CREAT);
416 }
417
418 /*
419
420 =item C<PMC * Parrot_ns_make_namespace_keyed_str(PARROT_INTERP, PMC *base_ns,
421 STRING *str_key)>
422
423 Find, or create if necessary, the namespace relative to the namespace
424 C<base_ns> with the string key C<str_key>. Return the namespace. Errors
425 will result in exceptions.
426
427 =cut
428
429 */
430
431 PARROT_EXPORT
432 PARROT_WARN_UNUSED_RESULT
433 PARROT_CANNOT_RETURN_NULL
434 PMC *
Parrot_ns_make_namespace_keyed_str(PARROT_INTERP,ARGIN (PMC * base_ns),ARGIN (STRING * str_key))435 Parrot_ns_make_namespace_keyed_str(PARROT_INTERP, ARGIN(PMC *base_ns),
436 ARGIN(STRING *str_key))
437 {
438 ASSERT_ARGS(Parrot_ns_make_namespace_keyed_str)
439 return internal_ns_keyed_str(interp, base_ns, str_key, INTERN_NS_CREAT);
440 }
441
442 /*
443
444 =item C<PMC * Parrot_ns_make_namespace_autobase(PARROT_INTERP, PMC *key)>
445
446 Find, or create if necessary, a namespace with the key C<key>, which may be a
447 String, a Key, or an array of strings. If it is a String, then the lookup is
448 relative to the current namespace. Otherwise, it is relative to the current HLL
449 root namespace. Return the namespace. Errors will result in exceptions.
450
451 =cut
452
453 */
454
455 PARROT_EXPORT
456 PARROT_WARN_UNUSED_RESULT
457 PARROT_CANNOT_RETURN_NULL
458 PMC *
Parrot_ns_make_namespace_autobase(PARROT_INTERP,ARGIN (PMC * key))459 Parrot_ns_make_namespace_autobase(PARROT_INTERP, ARGIN(PMC *key))
460 {
461 ASSERT_ARGS(Parrot_ns_make_namespace_autobase)
462 PMC *base_ns;
463 if (VTABLE_isa(interp, key, CONST_STRING(interp, "String")))
464 base_ns = Parrot_pcc_get_namespace(interp, CURRENT_CONTEXT(interp));
465 else
466 base_ns = VTABLE_get_pmc_keyed_int(interp, interp->HLL_namespace,
467 Parrot_pcc_get_HLL(interp, CURRENT_CONTEXT(interp)));
468 return Parrot_ns_make_namespace_keyed(interp, base_ns, key);
469 }
470
471 /*
472
473 =item C<PMC * Parrot_ns_get_name(PARROT_INTERP, PMC *_namespace)>
474
475 Get the name of the namespace, as a ResizableStringArray. For instance, the
476 namespace Foo:Bar:Baz would return an RSA with three elements.
477
478 =cut
479
480 */
481
482 PARROT_EXPORT
483 PARROT_WARN_UNUSED_RESULT
484 PARROT_CAN_RETURN_NULL
485 PMC *
Parrot_ns_get_name(PARROT_INTERP,ARGIN (PMC * _namespace))486 Parrot_ns_get_name(PARROT_INTERP, ARGIN(PMC *_namespace))
487 {
488 ASSERT_ARGS(Parrot_ns_get_name)
489 PMC *names;
490 STRING * const get_name = CONST_STRING(interp, "get_name");
491 Parrot_pcc_invoke_method_from_c_args(interp, _namespace, get_name, "->P", &names);
492 return names;
493 }
494
495 /*
496
497 =item C<PMC * Parrot_ns_get_global(PARROT_INTERP, PMC *ns, STRING *globalname)>
498
499 Look up the global named C<globalname> in the namespace C<ns>. Return the
500 global, or return PMCNULL if C<ns> is null or if the global is not found.
501
502 Parrot_ns_get_global allows a null namespace without throwing an exception; it
503 simply returns PMCNULL in that case.
504
505 NOTE: At present the use of the {get, set}_global functions is mandatory due
506 to the wacky namespace typing of the default Parrot namespace.
507 Eventually it will be safe to just use the standard hash interface
508 (if desired).
509
510 =cut
511
512 */
513
514 PARROT_EXPORT
515 PARROT_WARN_UNUSED_RESULT
516 PARROT_CANNOT_RETURN_NULL
517 PMC *
Parrot_ns_get_global(PARROT_INTERP,ARGIN_NULLOK (PMC * ns),ARGIN_NULLOK (STRING * globalname))518 Parrot_ns_get_global(PARROT_INTERP, ARGIN_NULLOK(PMC *ns), ARGIN_NULLOK(STRING *globalname))
519 {
520 ASSERT_ARGS(Parrot_ns_get_global)
521 if (PMC_IS_NULL(ns))
522 return PMCNULL;
523
524 return (PMC *)VTABLE_get_pointer_keyed_str(interp, ns, globalname);
525 }
526
527 /*
528
529 =item C<void Parrot_ns_set_global(PARROT_INTERP, PMC *ns, STRING *globalname,
530 PMC *val)>
531
532 Set the global named C<globalname> in the namespace C<ns> to the value C<val>.
533
534 =cut
535
536 */
537
538 PARROT_EXPORT
539 void
Parrot_ns_set_global(PARROT_INTERP,ARGIN (PMC * ns),ARGIN_NULLOK (STRING * globalname),ARGIN_NULLOK (PMC * val))540 Parrot_ns_set_global(PARROT_INTERP, ARGIN(PMC *ns),
541 ARGIN_NULLOK(STRING *globalname), ARGIN_NULLOK(PMC *val))
542 {
543 ASSERT_ARGS(Parrot_ns_set_global)
544 VTABLE_set_pmc_keyed_str(interp, ns, globalname, val);
545 }
546
547
548 /*
549
550 =item C<PMC * Parrot_ns_find_namespace_global(PARROT_INTERP, PMC *ns, STRING
551 *globalname)>
552
553 Search the namespace PMC C<ns> for an object with name C<globalname>.
554 Return the object, or PMCNULL if not found.
555
556 TT #1222 - For now this function prefers non-namespaces, it will eventually
557 entirely use the untyped interface.
558
559 =cut
560
561 */
562
563 PARROT_EXPORT
564 PARROT_WARN_UNUSED_RESULT
565 PARROT_CANNOT_RETURN_NULL
566 PMC *
Parrot_ns_find_namespace_global(PARROT_INTERP,ARGIN_NULLOK (PMC * ns),ARGIN_NULLOK (STRING * globalname))567 Parrot_ns_find_namespace_global(PARROT_INTERP,
568 ARGIN_NULLOK(PMC *ns), ARGIN_NULLOK(STRING *globalname))
569 {
570 ASSERT_ARGS(Parrot_ns_find_namespace_global)
571 PMC *res;
572
573 if (PMC_IS_NULL(ns))
574 res = PMCNULL;
575 else {
576 /*
577 * TT #1219 - we should be able to use 'get_pmc_keyed' here,
578 * but we can't because Parrot's default namespaces are not
579 * fully typed and there's a pseudo-typed interface that
580 * distinguishes 'get_pmc_keyed' from 'get_pointer_keyed';
581 * the former is for NS and the latter is for non-NS.
582 */
583 res = (PMC *)VTABLE_get_pointer_keyed_str(interp, ns, globalname);
584 }
585
586 return PMC_IS_NULL(res) ? PMCNULL : res;
587 }
588
589 /*
590
591 =item C<PMC * Parrot_ns_find_current_namespace_global(PARROT_INTERP, STRING
592 *globalname)>
593
594 Finds and returns the data time named C<globalname> in the current namespace.
595
596 =cut
597
598 */
599
600 PARROT_EXPORT
601 PARROT_WARN_UNUSED_RESULT
602 PARROT_CANNOT_RETURN_NULL
603 PMC *
Parrot_ns_find_current_namespace_global(PARROT_INTERP,ARGIN_NULLOK (STRING * globalname))604 Parrot_ns_find_current_namespace_global(PARROT_INTERP, ARGIN_NULLOK(STRING *globalname))
605 {
606 ASSERT_ARGS(Parrot_ns_find_current_namespace_global)
607 PMC * const ns = Parrot_pcc_get_namespace(interp, CURRENT_CONTEXT(interp));
608 return Parrot_ns_find_namespace_global(interp, ns, globalname);
609 }
610
611 /*
612
613 =item C<void Parrot_ns_store_global(PARROT_INTERP, PMC *ns, STRING *globalname,
614 PMC *val)>
615
616 Store the PMC C<val> into the namespace PMC C<ns> with name C<globalname>. If
617 the namespace is null, do nothing.
618
619 =cut
620
621 */
622
623 PARROT_EXPORT
624 void
Parrot_ns_store_global(PARROT_INTERP,ARGIN_NULLOK (PMC * ns),ARGIN_NULLOK (STRING * globalname),ARGIN_NULLOK (PMC * val))625 Parrot_ns_store_global(PARROT_INTERP, ARGIN_NULLOK(PMC *ns),
626 ARGIN_NULLOK(STRING *globalname), ARGIN_NULLOK(PMC *val))
627 {
628 ASSERT_ARGS(Parrot_ns_store_global)
629
630 if (PMC_IS_NULL(ns))
631 return;
632
633 VTABLE_set_pmc_keyed_str(interp, ns, globalname, val);
634 }
635
636 /*
637
638 =item C<PMC * Parrot_ns_find_global_from_op(PARROT_INTERP, PMC *ns, STRING
639 *globalname, void *next)>
640
641 If the global exists in the given namespace PMC, return it. If not, return
642 PMCNULL. Throw an exception if a NULL name is passed.
643
644 =cut
645
646 */
647
648 PARROT_EXPORT
649 PARROT_WARN_UNUSED_RESULT
650 PARROT_CANNOT_RETURN_NULL
651 PMC *
Parrot_ns_find_global_from_op(PARROT_INTERP,ARGIN (PMC * ns),ARGIN_NULLOK (STRING * globalname),SHIM (void * next))652 Parrot_ns_find_global_from_op(PARROT_INTERP, ARGIN(PMC *ns),
653 ARGIN_NULLOK(STRING *globalname), SHIM(void *next))
654 {
655 ASSERT_ARGS(Parrot_ns_find_global_from_op)
656 if (STRING_IS_NULL(globalname))
657 Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_GLOBAL_NOT_FOUND,
658 "Tried to get null global");
659 else {
660 PMC * const res = Parrot_ns_find_namespace_global(interp, ns, globalname);
661 return res;
662 }
663 }
664
665
666 /*
667
668 =item C<PMC * Parrot_ns_find_named_item(PARROT_INTERP, STRING *name, void
669 *next)>
670
671 Find the given C<name> in lexicals, then the current namespace, then the HLL
672 root namespace, and finally Parrot builtins. If the name isn't found
673 anywhere, return PMCNULL.
674
675 =cut
676
677 */
678
679 PARROT_EXPORT
680 PARROT_WARN_UNUSED_RESULT
681 PARROT_CANNOT_RETURN_NULL
682 PMC *
Parrot_ns_find_named_item(PARROT_INTERP,ARGIN (STRING * name),ARGIN (SHIM (void * next)))683 Parrot_ns_find_named_item(PARROT_INTERP, ARGIN(STRING *name), ARGIN(SHIM(void *next)))
684 {
685 ASSERT_ARGS(Parrot_ns_find_named_item)
686 PMC * const ctx = CURRENT_CONTEXT(interp);
687 PMC * const lex_pad = Parrot_sub_find_pad(interp, name, ctx);
688 PMC * g = PMCNULL;
689
690 if (!PMC_IS_NULL(lex_pad)) {
691 g = VTABLE_get_pmc_keyed_str(interp, lex_pad, name);
692
693 /* GH #563 - walk up the scopes! duh!! */
694 if (!PMC_IS_NULL(g))
695 return g;
696 }
697
698 g = Parrot_ns_find_current_namespace_global(interp, name);
699 if (!PMC_IS_NULL(g))
700 return g;
701
702 g = Parrot_ns_find_namespace_global(interp, Parrot_hll_get_ctx_HLL_namespace(interp), name);
703 if (!PMC_IS_NULL(g))
704 return g;
705 return PMCNULL;
706 }
707
708 /*
709
710 =item C<void Parrot_ns_store_sub(PARROT_INTERP, PMC *sub_pmc)>
711
712 Adds the PMC C<sub> into the current namespace. Adds the sub to a multi of the
713 same name if it's defined as a multi.
714
715 =cut
716
717 */
718
719 PARROT_EXPORT
720 void
Parrot_ns_store_sub(PARROT_INTERP,ARGIN (PMC * sub_pmc))721 Parrot_ns_store_sub(PARROT_INTERP, ARGIN(PMC *sub_pmc))
722 {
723 ASSERT_ARGS(Parrot_ns_store_sub)
724 const INTVAL cur_id = Parrot_pcc_get_HLL(interp, CURRENT_CONTEXT(interp));
725
726 PMC *ns;
727 Parrot_Sub_attributes *sub;
728
729 /* store relative to HLL namespace */
730 PMC_get_sub(interp, sub_pmc, sub);
731 Parrot_pcc_set_HLL(interp, CURRENT_CONTEXT(interp), sub->HLL_id);
732
733 ns = get_namespace_pmc(interp, sub_pmc);
734
735 /* attach a namespace to the sub for lookups */
736 sub->namespace_stash = ns;
737
738 /* store a :multi sub */
739 if (!PMC_IS_NULL(sub->multi_signature))
740 store_sub_in_multi(interp, sub_pmc, ns);
741
742 /* store other subs (as long as they're not :anon) */
743 else if (!(PObj_get_FLAGS(sub_pmc) & SUB_FLAG_PF_ANON)
744 || sub->vtable_index != -1) {
745 STRING * const ns_entry_name = sub->ns_entry_name;
746 PMC * const nsname = sub->namespace_name;
747
748 Parrot_ns_store_global(interp, ns, ns_entry_name, sub_pmc);
749
750 /* TT #1224:
751 TEMPORARY HACK - cache invalidation should be a namespace function
752 */
753 if (!PMC_IS_NULL(nsname)) {
754 STRING * const nsname_s = VTABLE_get_string(interp, nsname);
755 Parrot_invalidate_method_cache(interp, nsname_s);
756 }
757 }
758
759 /* restore HLL_id */
760 Parrot_pcc_set_HLL(interp, CURRENT_CONTEXT(interp), cur_id);
761 }
762
763 /*
764
765 =item C<Parrot_PMC Parrot_ns_get_root_namespace(PARROT_INTERP)>
766
767 Return the root namespace
768
769 =cut
770
771 */
772
773 PARROT_EXPORT
774 PARROT_PURE_FUNCTION
775 Parrot_PMC
Parrot_ns_get_root_namespace(PARROT_INTERP)776 Parrot_ns_get_root_namespace(PARROT_INTERP)
777 {
778 ASSERT_ARGS(Parrot_ns_get_root_namespace)
779
780 return interp->root_namespace;
781 }
782
783 /*
784
785 =back
786
787 =head1 SEE ALSO
788
789 F<include/parrot/namespace.h>
790
791 =cut
792
793 */
794
795
796 /*
797 * Local variables:
798 * c-file-style: "parrot"
799 * End:
800 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
801 */
802