* t/op/lexicals-2.t (added), MANIFEST:
[parrot.git] / src / pmc.c
blob10758ae148a9983ac5b6433a6f4edd2662d5ab71
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc.c - The base vtable calling functions
9 =head1 DESCRIPTION
11 =head2 Functions
13 =over 4
15 =cut
19 #include "parrot/parrot.h"
20 #include "pmc.str"
22 /* HEADERIZER HFILE: include/parrot/pmc.h */
24 /* HEADERIZER BEGIN: static */
25 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
27 PARROT_WARN_UNUSED_RESULT
28 PARROT_CANNOT_RETURN_NULL
29 static PMC* create_class_pmc(PARROT_INTERP, INTVAL type)
30 __attribute__nonnull__(1);
32 PARROT_WARN_UNUSED_RESULT
33 PARROT_CANNOT_RETURN_NULL
34 static PMC* get_new_pmc_header(PARROT_INTERP,
35 INTVAL base_type,
36 UINTVAL flags)
37 __attribute__nonnull__(1);
39 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
40 /* HEADERIZER END: static */
43 #if PARROT_CATCH_NULL
44 PMC * PMCNULL;
45 #endif
49 =item C<INTVAL PMC_is_null>
51 Tests if the given pmc is null.
53 =cut
57 PARROT_API
58 INTVAL
59 PMC_is_null(SHIM_INTERP, NULLOK(const PMC *pmc))
61 #if PARROT_CATCH_NULL
62 return pmc == PMCNULL || pmc == NULL;
63 #else
64 return pmc == NULL;
65 #endif
70 =item C<PMC * pmc_new>
72 Creates a new PMC of type C<base_type> (which is an index into the list of PMC
73 types declared in C<vtables> in F<include/parrot/pmc.h>). Once the PMC has been
74 successfully created and its vtable pointer initialized, we call its C<init>
75 method to perform any other necessary initialization.
77 =cut
81 PARROT_API
82 PARROT_CANNOT_RETURN_NULL
83 PARROT_WARN_UNUSED_RESULT
84 PMC *
85 pmc_new(PARROT_INTERP, INTVAL base_type)
87 PMC *const classobj = interp->vtables[base_type]->pmc_class;
89 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
90 return VTABLE_instantiate(interp, classobj, PMCNULL);
91 else {
92 PMC * const pmc = get_new_pmc_header(interp, base_type, 0);
93 VTABLE_init(interp, pmc);
94 return pmc;
100 =item C<PMC* pmc_reuse>
102 Reuse an existing PMC, turning it into an empty PMC of the new type. Any
103 required internal structure will be put in place (such as the extension area)
104 and the PMC will be ready to go. This will throw an exception if the PMC is
105 constant or of a singleton type (such as the environment PMC) or is being
106 turned into a PMC of a singleton type.
108 =cut
112 PARROT_API
113 PARROT_CANNOT_RETURN_NULL
114 PMC*
115 pmc_reuse(PARROT_INTERP, ARGIN(PMC *pmc), INTVAL new_type,
116 SHIM(UINTVAL flags))
118 INTVAL has_ext, new_flags;
119 VTABLE *new_vtable;
121 if (pmc->vtable->base_type == new_type)
122 return pmc;
124 new_vtable = interp->vtables[new_type];
126 /* Singleton/const PMCs/types are not eligible */
128 if ((pmc->vtable->flags | new_vtable->flags)
129 & (VTABLE_PMC_IS_SINGLETON | VTABLE_IS_CONST_FLAG))
131 /* First, is the destination a singleton? No joy for us there */
132 if (new_vtable->flags & VTABLE_PMC_IS_SINGLETON)
133 real_exception(interp, NULL, ALLOCATION_ERROR,
134 "Parrot VM: Can't turn to a singleton type!\n");
136 /* First, is the destination a constant? No joy for us there */
137 if (new_vtable->flags & VTABLE_IS_CONST_FLAG)
138 real_exception(interp, NULL, ALLOCATION_ERROR,
139 "Parrot VM: Can't turn to a constant type!\n");
141 /* Is the source a singleton? */
142 if (pmc->vtable->flags & VTABLE_PMC_IS_SINGLETON)
143 real_exception(interp, NULL, ALLOCATION_ERROR,
144 "Parrot VM: Can't modify a singleton\n");
146 /* Is the source constant? */
147 if (pmc->vtable->flags & VTABLE_IS_CONST_FLAG)
148 real_exception(interp, NULL, ALLOCATION_ERROR,
149 "Parrot VM: Can't modify a constant\n");
152 /* Do we have an extension area? */
153 has_ext = (PObj_is_PMC_EXT_TEST(pmc) && pmc->pmc_ext);
155 /* Do we need one? */
156 if (new_vtable->flags & VTABLE_PMC_NEEDS_EXT) {
157 if (!has_ext) {
158 /* If we need an ext area, go allocate one */
159 add_pmc_ext(interp, pmc);
161 new_flags = PObj_is_PMC_EXT_FLAG;
163 else {
164 if (has_ext)
165 Parrot_free_pmc_ext(interp, pmc);
167 #if ! PMC_DATA_IN_EXT
168 PMC_data(pmc) = NULL;
169 #endif
170 new_flags = 0;
173 /* we are a PMC + maybe is_PMC_EXT */
174 PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG | new_flags);
176 /* Set the right vtable */
177 pmc->vtable = new_vtable;
179 /* Call the base init for the redone pmc */
180 VTABLE_init(interp, pmc);
182 return pmc;
187 =item C<static PMC* get_new_pmc_header>
189 Gets a new PMC header.
191 =cut
195 PARROT_WARN_UNUSED_RESULT
196 PARROT_CANNOT_RETURN_NULL
197 static PMC*
198 get_new_pmc_header(PARROT_INTERP, INTVAL base_type, UINTVAL flags)
200 PMC *pmc;
201 VTABLE *vtable = interp->vtables[base_type];
202 UINTVAL vtable_flags;
204 /* This is usually because you either didn't call init_world early enough,
205 * you added a new PMC class without adding Parrot_(classname)_class_init
206 * to init_world, or you forgot to run 'make realclean' after adding a new
207 * PMC class. */
208 if (!vtable)
209 PANIC(interp, "Null vtable used; did you add a new PMC?");
211 vtable_flags = vtable->flags;
213 /* we only have one global Env object, living in the interp */
214 if (vtable_flags & VTABLE_PMC_IS_SINGLETON) {
216 * singletons (monadic objects) exist only once, the interface
217 * with the class is:
218 * - get_pointer: return NULL or a pointer to the single instance
219 * - set_pointer: set the only instance once
221 * - singletons are created in the constant pmc pool
223 PMC *pmc = (PMC *)(vtable->get_pointer)(interp, NULL);
225 /* LOCK */
226 if (!pmc) {
227 pmc = new_pmc_header(interp, PObj_constant_FLAG);
228 PARROT_ASSERT(pmc);
230 pmc->vtable = vtable;
231 pmc->real_self = pmc;
232 VTABLE_set_pointer(interp, pmc, pmc);
235 return pmc;
238 if (vtable_flags & VTABLE_IS_CONST_PMC_FLAG) {
239 flags |= PObj_constant_FLAG;
241 else if (vtable_flags & VTABLE_IS_CONST_FLAG) {
242 /* put the normal vtable in, so that the pmc can be initialized first
243 * parrot or user code has to set the _ro property then,
244 * to morph the PMC to the const variant
245 * This assumes that a constant PMC enum is one bigger then
246 * the normal one.
250 * XXX not yet we can't assure that all contents in the
251 * const PMC is const too
252 * see e.g. t/pmc/sarray_13.pir
254 #if 0
255 flags |= PObj_constant_FLAG;
256 #endif
257 --base_type;
258 vtable = interp->vtables[base_type];
261 if (vtable_flags & VTABLE_PMC_NEEDS_EXT) {
262 flags |= PObj_is_PMC_EXT_FLAG;
263 if (vtable_flags & VTABLE_IS_SHARED_FLAG)
264 flags |= PObj_is_PMC_shared_FLAG;
267 pmc = new_pmc_header(interp, flags);
268 pmc->vtable = vtable;
269 pmc->real_self = pmc;
271 #ifdef GC_VERBOSE
272 if (Interp_flags_TEST(interp, PARROT_TRACE_FLAG)) {
273 /* XXX make a more verbose trace flag */
274 fprintf(stderr, "\t=> new %p type %d\n", pmc, (int)base_type);
276 #endif
278 return pmc;
284 =item C<PMC * pmc_new_noinit>
286 Creates a new PMC of type C<base_type> (which is an index into the list of PMC
287 types declared in C<vtables> in F<include/parrot/pmc.h>). Unlike C<pmc_new()>,
288 C<pmc_new_noinit()> does not call its C<init> method. This allows separate
289 allocation and initialization for continuations.
291 =cut
295 PARROT_API
296 PARROT_CANNOT_RETURN_NULL
297 PMC *
298 pmc_new_noinit(PARROT_INTERP, INTVAL base_type)
300 PMC *const classobj = interp->vtables[base_type]->pmc_class;
302 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
303 return VTABLE_instantiate(interp, classobj, PMCNULL);
305 return get_new_pmc_header(interp, base_type, 0);
310 =item C<PMC * constant_pmc_new_noinit>
312 Creates a new constant PMC of type C<base_type>.
314 =cut
318 PARROT_API
319 PARROT_CANNOT_RETURN_NULL
320 PMC *
321 constant_pmc_new_noinit(PARROT_INTERP, INTVAL base_type)
323 return get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
328 =item C<PMC * constant_pmc_new>
330 Creates a new constant PMC of type C<base_type>, the call C<init>.
332 =cut
336 PARROT_API
337 PARROT_CANNOT_RETURN_NULL
338 PMC *
339 constant_pmc_new(PARROT_INTERP, INTVAL base_type)
341 PMC * const pmc = get_new_pmc_header(interp, base_type,
342 PObj_constant_FLAG);
343 VTABLE_init(interp, pmc);
344 return pmc;
349 =item C<PMC * pmc_new_init>
351 As C<pmc_new()>, but passes C<init> to the PMC's C<init_pmc()> method.
353 =cut
357 PARROT_API
358 PARROT_CANNOT_RETURN_NULL
359 PMC *
360 pmc_new_init(PARROT_INTERP, INTVAL base_type, ARGOUT(PMC *init))
362 PMC *const classobj = interp->vtables[base_type]->pmc_class;
364 if (!PMC_IS_NULL(classobj) && PObj_is_class_TEST(classobj))
365 return VTABLE_instantiate(interp, classobj, init);
366 else {
367 PMC * const pmc = get_new_pmc_header(interp, base_type, 0);
368 VTABLE_init_pmc(interp, pmc, init);
369 return pmc;
375 =item C<PMC * constant_pmc_new_init>
377 As C<constant_pmc_new>, but passes C<init> to the PMC's C<init_pmc> method.
379 =cut
383 PARROT_API
384 PARROT_CANNOT_RETURN_NULL
385 PMC *
386 constant_pmc_new_init(PARROT_INTERP, INTVAL base_type, ARGIN_NULLOK(PMC *init))
388 PMC * const pmc = get_new_pmc_header(interp, base_type, PObj_constant_FLAG);
389 VTABLE_init_pmc(interp, pmc, init);
390 return pmc;
395 =item C<INTVAL pmc_register>
397 This segment handles PMC registration and such.
399 =cut
403 PARROT_API
404 INTVAL
405 pmc_register(PARROT_INTERP, ARGIN(STRING *name))
407 PMC *classname_hash;
409 /* If they're looking to register an existing class, return that
410 class' type number */
411 INTVAL type = pmc_type(interp, name);
413 if (type > enum_type_undef)
414 return type;
416 if (type < enum_type_undef)
417 real_exception(interp, NULL, 1,
418 "undefined type already exists - can't register PMC");
420 classname_hash = interp->class_hash;
421 type = interp->n_vtable_max++;
423 /* Have we overflowed the table? */
424 if (type >= interp->n_vtable_alloced)
425 parrot_realloc_vtables(interp);
427 /* set entry in name->type hash */
428 VTABLE_set_integer_keyed_str(interp, classname_hash, name, type);
430 return type;
435 =item C<INTVAL pmc_type>
437 Returns the PMC type for C<name>.
439 =cut
443 PARROT_API
444 PARROT_WARN_UNUSED_RESULT
445 INTVAL
446 pmc_type(PARROT_INTERP, ARGIN_NULLOK(STRING *name))
448 if (!name)
449 return enum_type_undef;
450 else {
451 PMC * const classname_hash = interp->class_hash;
452 PMC * const item =
453 (PMC *)VTABLE_get_pointer_keyed_str(interp, classname_hash, name);
455 /* nested namespace with same name */
456 if (item->vtable->base_type == enum_class_NameSpace)
457 return enum_type_undef;
459 if (!PMC_IS_NULL(item))
460 return VTABLE_get_integer(interp, item);
462 return Parrot_get_datatype_enum(interp, name);
468 =item C<INTVAL pmc_type_p>
470 Returns the PMC type for C<name>.
472 =cut
476 PARROT_API
477 INTVAL
478 pmc_type_p(PARROT_INTERP, ARGIN(PMC *name))
480 PMC * const classname_hash = interp->class_hash;
481 PMC * const item =
482 (PMC *)VTABLE_get_pointer_keyed(interp, classname_hash, name);
484 if (!PMC_IS_NULL(item))
485 return VTABLE_get_integer(interp, item);
487 return 0;
492 =item C<static PMC* create_class_pmc>
494 Create a class object for this interpreter. Takes an interpreter
495 name and type as arguments. Returns a pointer to the class object.
497 =cut
501 PARROT_WARN_UNUSED_RESULT
502 PARROT_CANNOT_RETURN_NULL
503 static PMC*
504 create_class_pmc(PARROT_INTERP, INTVAL type)
507 * class interface - a PMC is its own class
508 * put an instance of this PMC into class
510 * create a constant PMC
512 PMC * const _class = get_new_pmc_header(interp, type,
513 PObj_constant_FLAG);
515 /* If we are a second thread, we may get the same object as the
516 * original because we have a singleton. Just set the singleton to
517 * be our class object, but don't mess with its vtable.
519 if ((interp->vtables[type]->flags & VTABLE_PMC_IS_SINGLETON)
520 && (_class == _class->vtable->pmc_class)) {
521 interp->vtables[type]->pmc_class = _class;
523 else {
524 if (PObj_is_PMC_EXT_TEST(_class))
525 Parrot_free_pmc_ext(interp, _class);
527 DOD_flag_CLEAR(is_special_PMC, _class);
529 PMC_pmc_val(_class) = (PMC *)0xdeadbeef;
530 PMC_struct_val(_class) = (void *)0xdeadbeef;
532 PObj_is_PMC_shared_CLEAR(_class);
534 interp->vtables[type]->pmc_class = _class;
537 return _class;
542 =item C<void Parrot_create_mro>
544 Create the MRO (method resolution order) array for this type.
546 =cut
550 PARROT_API
551 void
552 Parrot_create_mro(PARROT_INTERP, INTVAL type)
554 PMC *_class, *mro;
555 INTVAL i, count;
557 VTABLE *vtable = interp->vtables[type];
558 PMC *mro_list = vtable->mro;
560 /* multithreaded: has already mro */
561 if (mro_list && mro_list->vtable->base_type != enum_class_ResizableStringArray)
562 return;
564 mro = pmc_new(interp, enum_class_ResizablePMCArray);
565 vtable->mro = mro;
567 if (vtable->ro_variant_vtable)
568 vtable->ro_variant_vtable->mro = mro;
570 count = VTABLE_elements(interp, mro_list);
572 for (i = 0; i < count; ++i) {
573 STRING *class_name = VTABLE_get_string_keyed_int(interp, mro_list, i);
574 INTVAL parent_type = pmc_type(interp, class_name);
576 /* abstract classes don't have a vtable */
577 if (!parent_type)
578 break;
580 vtable = interp->vtables[parent_type];
582 if (!vtable->_namespace) {
583 /* need a namespace Hash, anchor at parent, name it */
584 PMC * const ns = pmc_new(interp,
585 Parrot_get_ctx_HLL_type(interp, enum_class_NameSpace));
586 vtable->_namespace = ns;
588 /* anchor at parent, aka current_namespace, that is 'parrot' */
589 VTABLE_set_pmc_keyed_str(interp,
590 CONTEXT(interp)->current_namespace, class_name, ns);
593 _class = vtable->pmc_class;
594 if (!_class)
595 _class = create_class_pmc(interp, parent_type);
597 VTABLE_push_pmc(interp, mro, _class);
603 =back
605 =head2 DOD registry interface
607 =over 4
609 =item C<void dod_register_pmc>
611 Registers the PMC with the interpreter's DOD registery.
613 =cut
617 PARROT_API
618 void
619 dod_register_pmc(PARROT_INTERP, ARGIN(PMC* pmc))
621 /* Better not trigger a DOD run with a potentially unanchored PMC */
622 Parrot_block_GC_mark(interp);
624 PARROT_ASSERT(interp->DOD_registry);
626 VTABLE_set_pmc_keyed(interp, interp->DOD_registry, pmc, PMCNULL);
627 Parrot_unblock_GC_mark(interp);
632 =item C<void dod_unregister_pmc>
634 Unregisters the PMC from the interpreter's DOD registry.
636 =cut
640 void
641 dod_unregister_pmc(PARROT_INTERP, ARGIN(PMC* pmc))
643 PARROT_ASSERT(interp->DOD_registry);
645 VTABLE_delete_keyed(interp, interp->DOD_registry, pmc);
652 =back
654 =head1 SEE ALSO
656 F<include/parrot/vtable.h>.
658 C<5.1.0.14.2.20011008152120.02158148@pop.sidhe.org>
659 (http://www.nntp.perl.org/group/perl.perl6.internals/5516).
661 =head1 HISTORY
663 Initial version by Simon on 2001.10.20.
665 =cut
671 * Local variables:
672 * c-file-style: "parrot"
673 * End:
674 * vim: expandtab shiftwidth=4: