2 Copyright (C) 2001-2003, The Perl Foundation.
7 objects.c - Class and object
11 Handles class and object manipulation.
21 #define PARROT_IN_OBJECTS_C
22 #include "parrot/parrot.h"
25 #include "objects.str"
27 static void parrot_class_register(Interp
* , PMC
*name
,
28 PMC
*new_class
, PMC
*parent
, PMC
*mro
);
32 =item C<int Parrot_is_vtable_name(Interp *, const char *name)>
34 Return true if C<name> is a valid vtable slot name.
41 Parrot_is_vtable_name(Interp
*interp
, const char *name
)
45 for (i
= 0; (meth
= Parrot_vtable_slot_names
[i
]); ++i
) {
48 /* XXX slot_names still have __ in front */
49 if (strcmp(name
, meth
+ 2) == 0)
56 readable_name(Interp
*interp
, PMC
*name
)
58 if (name
->vtable
->base_type
== enum_class_String
)
59 return VTABLE_get_string(interp
, name
);
61 STRING
*j
= CONST_STRING(interp
, ";");
62 PMC
*ar
= pmc_new(interp
, enum_class_ResizableStringArray
);
63 assert(name
->vtable
->base_type
== enum_class_Key
);
65 VTABLE_push_string(interp
, ar
, key_string(interp
, name
));
66 name
= key_next(interp
, name
);
68 return string_join(interp
, j
, ar
);
73 fail_if_exist(Interp
*interp
, PMC
*name
)
78 PMC
* const classname_hash
= interp
->class_hash
;
79 PMC
* type_pmc
= VTABLE_get_pointer_keyed(interp
,
80 classname_hash
, name
);
81 if (PMC_IS_NULL(type_pmc
) ||
82 type_pmc
->vtable
->base_type
== enum_class_NameSpace
)
85 type
= VTABLE_get_integer(interp
, type_pmc
);
86 /* TODO get printable name */
87 class_name
= VTABLE_get_string(interp
, name
);
88 if (type
> enum_type_undef
) {
89 real_exception(interp
, NULL
, INVALID_OPERATION
,
90 "Class %Ss already registered!\n", class_name
);
92 if (type
< enum_type_undef
) {
93 real_exception(interp
, NULL
, INVALID_OPERATION
,
94 "native type with name '%s' already exists - "
95 "can't register Class", data_types
[type
].name
);
100 * FIXME make array clone shallow
103 clone_array(Interp
*interp
, PMC
*source_array
)
105 PMC
* const new_array
= pmc_new(interp
,
106 source_array
->vtable
->base_type
);
107 const INTVAL count
= VTABLE_elements(interp
, source_array
);
111 * preserve type, we have OrderedHash and Array
112 * XXX this doesn't preserve the keys of the ordered hash
113 * (but the keys aren't used -leo)
115 VTABLE_set_integer_native(interp
, new_array
, count
);
116 for (i
= 0; i
< count
; i
++) {
117 VTABLE_set_pmc_keyed_int(interp
, new_array
, i
,
118 VTABLE_get_pmc_keyed_int(interp
, source_array
, i
));
123 /* Take the class and completely rebuild the attribute stuff for
124 it. Horribly destructive, and definitely not a good thing to do if
125 there are instantiated objects for the class */
127 rebuild_attrib_stuff(Interp
*interp
, PMC
*class)
130 SLOTTYPE
*class_slots
;
131 PMC
*attr_offset_hash
;
139 PMC
* const orig_class
= class;
142 /* attrib count isn't set yet, a GC causedd by concat could
143 * corrupt data under construction
145 Parrot_block_DOD(interp
);
147 class_slots
= PMC_data(class);
148 attr_offset_hash
= pmc_new(interp
, enum_class_Hash
);
149 set_attrib_num(class, class_slots
, PCD_ATTRIBUTES
, attr_offset_hash
);
151 mro
= class->vtable
->mro
;
152 n_mro
= VTABLE_elements(interp
, mro
);
155 * walk from oldest parent downto n_class == 0 which is this class
158 for (n_class
= n_mro
- 1; n_class
>= 0; --n_class
) {
159 class = VTABLE_get_pmc_keyed_int(interp
, mro
, n_class
);
160 if (!PObj_is_class_TEST(class)) {
161 /* this Class isa PMC - no attributes there
166 class_slots
= PMC_data(class);
167 classname
= VTABLE_get_string(interp
,
168 get_attrib_num(class_slots
, PCD_CLASS_NAME
));
169 attribs
= get_attrib_num(class_slots
, PCD_CLASS_ATTRIBUTES
);
170 attr_count
= VTABLE_elements(interp
, attribs
);
174 STRING
* const partial_name
=
175 string_concat(interp
, classname
,
176 string_from_cstring(interp
, "\0", 1),
178 for (offset
= 0; offset
< attr_count
; offset
++) {
179 STRING
* const attr_name
=
180 VTABLE_get_string_keyed_int(interp
, attribs
, offset
);
181 STRING
* const full_name
=
182 string_concat(interp
, partial_name
, attr_name
, 0);
184 * store this attribute with short and full name
186 VTABLE_set_integer_keyed_str(interp
, attr_offset_hash
,
187 attr_name
, cur_offset
);
188 VTABLE_set_integer_keyed_str(interp
, attr_offset_hash
,
189 full_name
, cur_offset
++);
195 assert(class == orig_class
);
198 /* And note the totals */
199 CLASS_ATTRIB_COUNT(class) = cur_offset
;
200 Parrot_unblock_DOD(interp
);
205 =item C<static PMC *find_vtable_override_byname(Interp *interp,
207 STRING *method_name)>
209 Tries to locate a PIR override method for the given v-table method in the
210 given class. If one is found, returns the method.
217 find_vtable_override_byname(Interp
*interp
, PMC
*class_name
,
220 /* First try it in the :vtable namespace. */
221 STRING
* vtable_str
= string_from_const_cstring(interp
,
223 PMC
*ns
= Parrot_find_global_k(interp
, class_name
, vtable_str
);
224 if (!PMC_IS_NULL(ns
)) {
225 STRING
*no_underscores
= string_substr(interp
, method_name
,
226 2, method_name
->strlen
- 2, NULL
, 0);
227 PMC
*res
= VTABLE_get_pmc_keyed_str(interp
, ns
,
229 if (!PMC_IS_NULL(res
))
233 /* Otherwise, do lookup in the old way. */
234 return Parrot_find_global_k(interp
, class_name
, method_name
);
239 =item C<static void create_deleg_pmc_vtable(Interp *, PMC *class,
240 PMC *class_name, int full)>
242 Create a vtable that dispatches either to the contained PMC in the first
243 attribute (deleg_pmc) or to an overridden method (delegate), depending
244 on the existence of the method for this class.
251 create_deleg_pmc_vtable(Interp
*interp
, PMC
*class,
252 PMC
*class_name
, int full
)
259 PMC
* const vtable_pmc
= get_attrib_num((SLOTTYPE
*)PMC_data(class),
261 VTABLE
* const vtable
= PMC_struct_val(vtable_pmc
);
262 VTABLE
* const ro_vtable
= vtable
->ro_variant_vtable
;
263 VTABLE
* const deleg_pmc_vtable
=
264 interp
->vtables
[enum_class_deleg_pmc
];
265 VTABLE
* const object_vtable
=
266 interp
->vtables
[enum_class_ParrotObject
];
267 VTABLE
* const ro_object_vtable
= object_vtable
->ro_variant_vtable
;
268 VTABLE
* const delegate_vtable
= interp
->vtables
[enum_class_delegate
];
270 memset(&meth_str
, 0, sizeof(meth_str
));
271 meth_str
.encoding
= Parrot_fixed_8_encoding_ptr
;
272 meth_str
.charset
= Parrot_default_charset_ptr
;
273 for (i
= 0; (meth
= Parrot_vtable_slot_names
[i
]); ++i
) {
276 meth_str
.strstart
= const_cast(meth
);
277 meth_str
.strlen
= meth_str
.bufused
= strlen(meth
);
278 meth_str
.hashval
= 0;
279 if (find_vtable_override_byname(interp
, class_name
, &meth_str
)) {
281 * the method exists; keep the ParrotObject aka delegate vtable slot
283 ((void **)vtable
)[i
] = ((void**)object_vtable
)[i
];
285 ((void **)ro_vtable
)[i
] = ((void**)ro_object_vtable
)[i
];
288 PIO_eprintf(interp
, "deleg_pmc class '%Ss' found '%s'\n",
294 * the method doesn't exist; put in the deleg_pmc vtable,
295 * but only if ParrotObject hasn't overridden the method
297 if (((void **)delegate_vtable
)[i
] == ((void**)object_vtable
)[i
]) {
299 ((void **)ro_vtable
)[i
] = ((void**)deleg_pmc_vtable
)[i
];
300 ((void **)vtable
)[i
] = ((void**)deleg_pmc_vtable
)[i
];
303 ((void **)vtable
)[i
] = ((void**)object_vtable
)[i
];
305 ((void **)ro_vtable
)[i
] = ((void**)ro_object_vtable
)[i
];
314 =item C<const char* Parrot_MMD_method_name(Interp*, INTVAL)>
316 Return the method name for the given MMD enum.
318 =item C<INTVAL Parrot_MMD_method_idx(Interp*, STRING *)>
320 Return the MMD function number for method name or -1 on failure.
322 TODO allow dynamic expansion at runtime.
328 Parrot_MMD_method_name(Interp
*interp
, INTVAL idx
)
332 if (idx
>= MMD_USER_FIRST
)
334 return Parrot_mmd_func_names
[idx
];
338 Parrot_MMD_method_idx(Interp
*interp
, char *name
)
342 for (i
= 0; i
< MMD_USER_FIRST
; ++i
) {
343 if (!strcmp(Parrot_mmd_func_names
[i
], name
))
353 Parrot_single_subclass(Interp *interp, PMC *base_class,
354 PMC *child_class_name)>
356 Subclass a class. Single parent class, nice and straightforward. If
357 C<child_class> is C<NULL>, this is an anonymous subclass we're creating,
358 which happens commonly enough to warrant an actual single-subclass
366 Parrot_single_subclass(Interp
*interp
, PMC
*base_class
,
370 SLOTTYPE
*child_class_array
;
371 PMC
*parents
, *temp_pmc
, *mro
;
374 /* Set the classname, if we have one */
375 if (!PMC_IS_NULL(name
)) {
376 fail_if_exist(interp
, name
);
379 /* XXX not really threadsafe but good enough for now */
380 static int anon_count
;
382 STRING
*child_class_name
= Parrot_sprintf_c(interp
,
383 "%c%canon_%d", 0, 0, ++anon_count
);
384 name
= pmc_new(interp
, enum_class_String
);
385 VTABLE_set_string_native(interp
, name
, child_class_name
);
388 * ParrotClass is the baseclass anyway, so build just a new class
390 if (base_class
== interp
->vtables
[enum_class_ParrotClass
]->class) {
391 return pmc_new_init(interp
, enum_class_ParrotClass
, name
);
393 parent_is_class
= PObj_is_class_TEST(base_class
);
395 child_class
= pmc_new(interp
, enum_class_ParrotClass
);
396 /* Hang an array off the data pointer */
397 set_attrib_array_size(child_class
, PCD_MAX
);
398 child_class_array
= PMC_data(child_class
);
399 set_attrib_flags(child_class
);
400 /* We will have five entries in this array */
402 /* We have the same number of attributes as our parent */
403 CLASS_ATTRIB_COUNT(child_class
) = parent_is_class
404 ? CLASS_ATTRIB_COUNT(base_class
) : 0;
406 /* Our parent class array has a single member in it */
407 parents
= pmc_new(interp
, enum_class_ResizablePMCArray
);
408 VTABLE_set_integer_native(interp
, parents
, 1);
409 VTABLE_set_pmc_keyed_int(interp
, parents
, 0, base_class
);
410 set_attrib_num(child_class
, child_class_array
, PCD_PARENTS
, parents
);
413 set_attrib_num(child_class
, child_class_array
, PCD_CLASS_NAME
, name
);
415 /* Our mro list is a clone of our parent's mro
416 * list, with our self unshifted onto the beginning
418 mro
= VTABLE_clone(interp
, base_class
->vtable
->mro
);
419 VTABLE_unshift_pmc(interp
, mro
, child_class
);
421 /* But we have no attributes of our own. Yet */
422 temp_pmc
= pmc_new(interp
, enum_class_ResizablePMCArray
);
423 set_attrib_num(child_class
, child_class_array
, PCD_CLASS_ATTRIBUTES
,
426 parrot_class_register(interp
, name
, child_class
,
429 rebuild_attrib_stuff(interp
, child_class
);
431 if (!parent_is_class
) {
432 /* we append one attribute to hold the PMC */
433 Parrot_add_attribute(interp
, child_class
,
434 CONST_STRING(interp
, "__value"));
436 * then create a vtable derived from ParrotObject and
437 * deleg_pmc - the ParrotObject vtable is already built
439 create_deleg_pmc_vtable(interp
, child_class
, name
, 1);
443 * if any parent isa PMC, then still individual vtables might
444 * be overridden in this subclass
447 int i
, n
, any_pmc_parent
;
449 n
= VTABLE_elements(interp
, mro
);
452 /* 0 = this, 1 = parent (handled above), 2 = grandpa */
453 for (i
= 2; i
< n
; ++i
) {
454 parent
= VTABLE_get_pmc_keyed_int(interp
, mro
, i
);
455 if (!PObj_is_class_TEST(parent
)) {
461 create_deleg_pmc_vtable(interp
, child_class
, name
, 0);
469 Parrot_new_class(Interp *interp, PMC *class, PMC *class_name)>
471 Creates a new class, named C<class_name>.
478 Parrot_new_class(Interp
*interp
, PMC
*class, PMC
*name
)
480 SLOTTYPE
*class_array
;
483 /* check against duplicate newclasses */
484 fail_if_exist(interp
, name
);
486 /* Hang an array off the data pointer, empty of course */
487 set_attrib_array_size(class, PCD_MAX
);
488 class_array
= PMC_data(class);
489 /* set_attrib_flags(class); init does it */
491 /* Our parent class array has nothing in it */
492 set_attrib_num(class, class_array
, PCD_PARENTS
,
493 pmc_new(interp
, enum_class_ResizablePMCArray
));
494 /* TODO create all class structures in constant PMC pool
498 * create MRO (method resolution order) array
499 * first entry is this class itself
501 mro
= pmc_new(interp
, enum_class_ResizablePMCArray
);
502 VTABLE_push_pmc(interp
, mro
, class);
506 set_attrib_num(class, class_array
, PCD_CLASS_ATTRIBUTES
,
507 pmc_new(interp
, enum_class_ResizablePMCArray
));
509 /* Set the classname */
510 set_attrib_num(class, class_array
, PCD_CLASS_NAME
, name
);
512 parrot_class_register(interp
, name
, class, NULL
, mro
);
514 rebuild_attrib_stuff(interp
, class);
520 Parrot_class_lookup(Interp *interp, STRING *class_name)>
523 Parrot_class_lookup_p(Interp *interp, PMC *class_name)>
525 Looks for the class named C<class_name> and returns it if it exists.
526 Otherwise it returns C<PMCNULL>.
533 Parrot_class_lookup(Interp
*interp
, STRING
*class_name
)
535 const INTVAL type
= pmc_type(interp
, class_name
);
537 PMC
* const pmc
= interp
->vtables
[type
]->class;
545 Parrot_class_lookup_p(Interp
*interp
, PMC
*class_name
)
547 const INTVAL type
= pmc_type_p(interp
, class_name
);
549 PMC
* const pmc
= interp
->vtables
[type
]->class;
557 register_type(Interp
*interp
, PMC
*name
)
560 PMC
* classname_hash
, *item
;
562 /* so pt_shared_fixup() can safely do a type lookup */
563 LOCK_INTERPRETER(interp
);
564 classname_hash
= interp
->class_hash
;
566 type
= interp
->n_vtable_max
++;
567 /* Have we overflowed the table? */
568 if (type
>= interp
->n_vtable_alloced
) {
569 parrot_realloc_vtables(interp
);
571 /* set entry in name->type hash */
572 item
= pmc_new(interp
, enum_class_Integer
);
573 PMC_int_val(item
) = type
;
574 VTABLE_set_pmc_keyed(interp
, classname_hash
, name
, item
);
575 UNLOCK_INTERPRETER(interp
);
583 parrot_class_register(Interp *interp, PMC *class_name,
584 PMC *new_class, PMC *mro)>
586 This is the way to register a new Parrot class as an instantiable
587 type. Doing this involves putting it in the class hash, setting its
588 vtable so that the C<init> method initializes objects of the class rather than
589 the class itself, and adding it to the interpreter's base type table so
590 you can create a new C<foo> in PASM like this: C<new Px, foo>.
597 parrot_class_register(Interp
*interp
, PMC
*name
,
598 PMC
*new_class
, PMC
*parent
, PMC
*mro
)
600 VTABLE
*new_vtable
, *parent_vtable
;
605 new_type
= register_type(interp
, name
);
606 /* Build a new vtable for this class
607 * The child class PMC gets the vtable of its parent class or
608 * a ParrotClass vtable
610 parent_vtable
= new_class
->vtable
;
611 if (parent
&& PObj_is_class_TEST(parent
))
612 parent_vtable
= parent
->vtable
;
614 parent_vtable
= new_class
->vtable
;
615 new_vtable
= Parrot_clone_vtable(interp
, parent_vtable
);
617 /* Set the vtable's type to the newly allocated type */
618 new_vtable
->base_type
= new_type
;
619 /* And cache our class PMC in the vtable so we can find it later */
620 new_vtable
->class = new_class
;
621 new_vtable
->mro
= mro
;
623 if (parent_vtable
->ro_variant_vtable
)
624 new_vtable
->ro_variant_vtable
=
625 Parrot_clone_vtable(interp
, parent_vtable
->ro_variant_vtable
);
627 /* Reset the init method to our instantiation method */
628 new_vtable
->init
= Parrot_instantiate_object
;
629 new_vtable
->init_pmc
= Parrot_instantiate_object_init
;
630 new_class
->vtable
= new_vtable
;
632 /* Put our new vtable in the global table */
633 interp
->vtables
[new_type
] = new_vtable
;
635 /* check if we already have a NameSpace */
636 top
= CONTEXT(interp
->ctx
)->current_namespace
;
637 ns
= VTABLE_get_pmc_keyed(interp
, top
, name
);
638 /* XXX nested, use current as base ? */
639 if (PMC_IS_NULL(ns
)) {
640 /* XXX try HLL namespace too XXX */
641 top
= Parrot_get_ctx_HLL_namespace(interp
);
642 ns
= VTABLE_get_pmc_keyed(interp
, top
, name
);
644 if (PMC_IS_NULL(ns
)) {
645 ns
= pmc_new(interp
, enum_class_NameSpace
);
646 VTABLE_set_pmc_keyed(interp
, top
, name
, ns
);
648 /* attach namspace to vtable */
649 new_vtable
->_namespace
= ns
;
651 if (new_vtable
->ro_variant_vtable
) {
652 VTABLE
* const ro_vt
= new_vtable
->ro_variant_vtable
;
653 ro_vt
->base_type
= new_vtable
->base_type
;
654 ro_vt
->class = new_vtable
->class;
655 ro_vt
->mro
= new_vtable
->mro
;
656 ro_vt
->_namespace
= new_vtable
->_namespace
;
660 * prepare object vtable - again that of the parent or
661 * a ParrotObject vtable
663 if (parent
&& PObj_is_class_TEST(parent
)) {
665 get_attrib_num((SLOTTYPE
*)PMC_data(parent
), PCD_OBJECT_VTABLE
);
666 parent_vtable
= PMC_struct_val(vtable_pmc
);
669 parent_vtable
= interp
->vtables
[enum_class_ParrotObject
];
671 new_vtable
= Parrot_clone_vtable(interp
, parent_vtable
);
672 if (parent_vtable
->ro_variant_vtable
)
673 new_vtable
->ro_variant_vtable
=
674 Parrot_clone_vtable(interp
, parent_vtable
->ro_variant_vtable
);
675 new_vtable
->base_type
= new_type
;
676 new_vtable
->mro
= mro
;
677 new_vtable
->class = new_class
;
679 set_attrib_num(new_class
, (SLOTTYPE
*)PMC_data(new_class
), PCD_OBJECT_VTABLE
,
680 vtable_pmc
= constant_pmc_new(interp
, enum_class_VtableCache
));
681 PMC_struct_val(vtable_pmc
) = new_vtable
;
682 /* attach namspace to object vtable too */
683 new_vtable
->_namespace
= ns
;
685 if (new_vtable
->ro_variant_vtable
) {
686 VTABLE
* const ro_vt
= new_vtable
->ro_variant_vtable
;
687 ro_vt
->base_type
= new_vtable
->base_type
;
688 ro_vt
->class = new_vtable
->class;
689 ro_vt
->mro
= new_vtable
->mro
;
690 ro_vt
->_namespace
= new_vtable
->_namespace
;
695 get_init_meth(Interp
*interp
, PMC
*class,
696 STRING
*prop_str
, STRING
**meth_str
)
700 PMC
*props
, *ns
, *method
;
705 prop
= VTABLE_getprop(interp
, class, prop_str
);
706 if (!VTABLE_defined(interp
, prop
))
708 meth
= VTABLE_get_string(interp
, prop
);
710 if ( !(props
= PMC_metadata(class)))
712 b
= parrot_hash_get_bucket(interp
,
713 (Hash
*) PMC_struct_val(props
), prop_str
);
716 meth
= PMC_str_val((PMC
*) b
->value
);
720 ns
= VTABLE_namespace(interp
, class);
721 method
= VTABLE_get_pmc_keyed_str(interp
, ns
, meth
);
722 return PMC_IS_NULL(method
) ? NULL
: method
;
727 do_initcall(Interp
*interp
, PMC
* class, PMC
*object
, PMC
*init
)
729 PMC
* const classsearch_array
= class->vtable
->mro
;
733 * 1) if class has a CONSTRUCT property run it on the object
736 * XXX isn't CONSTRUCT for creating new objects?
739 PMC
*meth
= get_init_meth(interp
, class,
740 CONST_STRING(interp
, "CONSTRUCT"), &meth_str
);
745 Parrot_run_meth_fromc_args(interp
, meth
,
746 object
, meth_str
, "vP", init
);
748 Parrot_run_meth_fromc_args(interp
, meth
,
749 object
, meth_str
, "v");
752 * 2. if class has a BUILD property call it for all classes
753 * in reverse search order - this class last.
755 * Note: mro contains this class as first element
757 nparents
= VTABLE_elements(interp
, classsearch_array
);
758 for (i
= nparents
- 1; i
>= 0; --i
) {
759 parent_class
= VTABLE_get_pmc_keyed_int(interp
,
760 classsearch_array
, i
);
761 /* if it's a PMC, we put one PMC of that type into
762 * the attribute slot #0 and call init() on that PMC
764 if (!PObj_is_class_TEST(parent_class
)) {
765 PMC
*attr
, *next_parent
;
769 * but only if init isn't inherited
770 * or rather just on the last non-class parent
773 next_parent
= VTABLE_get_pmc_keyed_int(interp
,
774 classsearch_array
, i
- 1);
775 if (!PObj_is_class_TEST(next_parent
)) {
778 attr
= pmc_new_noinit(interp
,
779 parent_class
->vtable
->base_type
);
780 obj_data
= PMC_data(object
);
781 set_attrib_num(object
, obj_data
, 0, attr
);
782 VTABLE_init(interp
, attr
);
785 meth
= get_init_meth(interp
, parent_class
,
786 CONST_STRING(interp
, "BUILD"), &meth_str
);
787 /* no method found and no BUILD property set? */
788 if (!meth
&& meth_str
== NULL
) {
791 STRING
*vtable_ns_name
= string_from_const_cstring(interp
,
794 /* use __init as fallback constructor method, if it exists */
795 meth_str
= CONST_STRING(interp
, "__init");
796 meth_str_v
= CONST_STRING(interp
, "init");
797 ns
= VTABLE_namespace(interp
, parent_class
);
798 vtable_ns
= Parrot_get_namespace_keyed_str(interp
, ns
,
800 /* can't use find_method, it walks mro */
801 if (!PMC_IS_NULL(vtable_ns
))
802 meth
= VTABLE_get_pmc_keyed_str(interp
, vtable_ns
,
804 if (PMC_IS_NULL(meth
))
805 meth
= VTABLE_get_pmc_keyed_str(interp
, ns
, meth_str
);
814 Parrot_run_meth_fromc_args(interp
, meth
,
815 object
, meth_str
, "vP", init
);
817 Parrot_run_meth_fromc_args(interp
, meth
,
818 object
, meth_str
, "v");
820 else if (meth_str
!= NULL
&&
821 string_length(interp
, meth_str
) != 0 && !default_meth
) {
822 real_exception(interp
, NULL
, METH_NOT_FOUND
,
823 "Class BUILD method ('%Ss') not found", meth_str
);
831 Parrot_instantiate_object(Interp *interp, PMC *object, PMC *init)>
833 Creates a Parrot object. Takes a passed-in class PMC that has sufficient
834 information to describe the layout of the object and, well, makes the
841 static void instantiate_object(Interp
*, PMC
*object
, PMC
*init
);
844 Parrot_instantiate_object_init(Interp
*interp
,
845 PMC
*object
, PMC
*init
)
847 instantiate_object(interp
, object
, init
);
851 Parrot_instantiate_object(Interp
*interp
, PMC
*object
)
853 instantiate_object(interp
, object
, NULL
);
857 instantiate_object(Interp
*interp
, PMC
*object
, PMC
*init
)
859 SLOTTYPE
*new_object_array
;
860 INTVAL attrib_count
, i
;
862 PMC
* const class = object
->vtable
->class;
864 * put in the real vtable
866 PMC
* const vtable_pmc
= get_attrib_num((SLOTTYPE
*)PMC_data(class),
868 object
->vtable
= PMC_struct_val(vtable_pmc
);
870 /* Grab the attribute count from the class */
871 attrib_count
= CLASS_ATTRIB_COUNT(class);
873 /* Build the array that hangs off the new object */
874 /* First presize it */
875 set_attrib_array_size(object
, attrib_count
);
876 new_object_array
= PMC_data(object
);
878 /* fill with PMCNULL, so that access doesn't segfault */
879 for (i
= 0; i
< attrib_count
; ++i
)
880 set_attrib_num(object
, new_object_array
, i
, PMCNULL
);
882 /* turn marking on */
883 set_attrib_flags(object
);
885 /* We are an object now */
886 PObj_is_object_SET(object
);
888 /* We really ought to call the class init routines here...
889 * this assumes that an object isa delegate
891 do_initcall(interp
, class, object
, init
);
897 Parrot_add_parent(Interp *interp, PMC *class,
900 Add the parent class to the current class' parent list. This also
901 involved adding all the parent's parents, as well as all attributes of
902 the parent classes that we're adding in.
904 The MRO (method resolution order) is the C3 algorithm used by Perl6
905 and Python (>= 2.3). See also:
906 L<http://pugs.blogs.com/pugs/2005/07/day_165_r5671_j.html>
913 /* create a list if non-empty lists */
915 not_empty(Interp
*interp
, PMC
*seqs
)
918 PMC
* const nseqs
= pmc_new(interp
, enum_class_ResizablePMCArray
);
920 for (i
= 0; i
< VTABLE_elements(interp
, seqs
); ++i
) {
921 PMC
* const list
= VTABLE_get_pmc_keyed_int(interp
, seqs
, i
);
922 if (VTABLE_elements(interp
, list
))
923 VTABLE_push_pmc(interp
, nseqs
, list
);
928 /* merge the list if lists */
930 class_mro_merge(Interp
*interp
, PMC
*seqs
)
932 PMC
*res
, *seq
, *cand
, *nseqs
, *s
;
934 cand
= NULL
; /* silence compiler uninit warning */
936 res
= pmc_new(interp
, enum_class_ResizablePMCArray
);
938 nseqs
= not_empty(interp
, seqs
);
939 if (!VTABLE_elements(interp
, nseqs
))
941 for (i
= 0; i
< VTABLE_elements(interp
, nseqs
); ++i
) {
942 seq
= VTABLE_get_pmc_keyed_int(interp
, nseqs
, i
);
943 cand
= VTABLE_get_pmc_keyed_int(interp
, seq
, 0);
944 /* check if candidate is valid */
945 for (j
= 0; j
< VTABLE_elements(interp
, nseqs
); ++j
) {
946 s
= VTABLE_get_pmc_keyed_int(interp
, nseqs
, j
);
947 for (k
= 1; k
< VTABLE_elements(interp
, s
); ++k
)
948 if (VTABLE_get_pmc_keyed_int(interp
, s
, k
) == cand
) {
957 real_exception(interp
, NULL
, E_TypeError
,
958 "inconsisten class hierarchy");
959 /* push candidate onto mro result */
960 VTABLE_push_pmc(interp
, res
, cand
);
961 /* remove candidate from head of lists */
962 for (i
= 0; i
< VTABLE_elements(interp
, nseqs
); ++i
) {
963 seq
= VTABLE_get_pmc_keyed_int(interp
, nseqs
, i
);
964 if (VTABLE_get_pmc_keyed_int(interp
, seq
, 0) == cand
) {
965 VTABLE_shift_pmc(interp
, seq
);
974 create_class_mro(Interp
*interp
, PMC
*class)
976 PMC
*lparents
, *bases
;
980 * [ [class] [mro of bases] [bases] ]
982 PMC
* const lall
= pmc_new(interp
, enum_class_ResizablePMCArray
);
983 PMC
* const lc
= pmc_new(interp
, enum_class_ResizablePMCArray
);
985 VTABLE_push_pmc(interp
, lc
, class);
986 VTABLE_push_pmc(interp
, lall
, lc
);
988 bases
= get_attrib_num(PMC_data(class), PCD_PARENTS
);
989 for (i
= 0; i
< VTABLE_elements(interp
, bases
); ++i
) {
990 PMC
* const base
= VTABLE_get_pmc_keyed_int(interp
, bases
, i
);
991 PMC
* const lmap
= PObj_is_class_TEST(base
) ?
992 create_class_mro(interp
, base
) : base
->vtable
->mro
;
993 VTABLE_push_pmc(interp
, lall
, lmap
);
995 lparents
= VTABLE_clone(interp
, bases
);
996 VTABLE_push_pmc(interp
, lall
, lparents
);
997 return class_mro_merge(interp
, lall
);
1001 Parrot_add_parent(Interp
*interp
, PMC
*class, PMC
*parent
)
1003 PMC
*current_parent_array
;
1005 if (!PObj_is_class_TEST(class))
1006 internal_exception(1, "Class isn't a ParrotClass");
1007 if (!PObj_is_class_TEST(parent
) && parent
== parent
->vtable
->class) {
1008 /* Permit inserting non-classes so at least thaw'ing classes
1009 * is easy. Adding these parents after classes have been
1010 * subclassed is dangerous, however.
1014 if (CLASS_ATTRIB_COUNT(class) != 0) {
1015 internal_exception(1, "Subclassing built-in type too late");
1017 Parrot_add_attribute(interp
, class,
1018 CONST_STRING(interp
, "__value"));
1019 class_name
= pmc_new(interp
, enum_class_String
);
1020 VTABLE_set_string_native(interp
, class_name
,
1021 VTABLE_name(interp
, class));
1022 create_deleg_pmc_vtable(interp
, class, class_name
, 1);
1023 } else if (!PObj_is_class_TEST(parent
)) {
1024 internal_exception(1, "Parent isn't a ParrotClass");
1028 current_parent_array
= get_attrib_num(PMC_data(class), PCD_PARENTS
);
1029 VTABLE_push_pmc(interp
, current_parent_array
, parent
);
1031 class->vtable
->mro
= create_class_mro(interp
, class);
1033 rebuild_attrib_stuff(interp
, class);
1040 Parrot_remove_parent(Interp *interp, PMC *removed_class,
1041 PMC *existing_class)>
1043 This currently does nothing but return C<NULL>.
1050 Parrot_remove_parent(Interp
*interp
, PMC
*removed_class
,
1051 PMC
*existing_class
) {
1058 Parrot_multi_subclass(Interp *interp, PMC *base_class_array,
1059 STRING *child_class_name)>
1061 This currently does nothing but return C<NULL>.
1068 Parrot_multi_subclass(Interp
*interp
, PMC
*base_class_array
,
1069 STRING
*child_class_name
) {
1076 Parrot_object_isa(Interp *interp, PMC *pmc, PMC *cl)>
1078 Return whether the object C<pmc> is an instance of class C<cl>.
1085 Parrot_object_isa(Interp
*interp
, PMC
*pmc
, PMC
*cl
)
1088 INTVAL i
, classcount
;
1090 /* if this is not a class */
1091 if (!PObj_is_class_TEST(pmc
)) {
1092 pmc
= VTABLE_get_class(interp
, pmc
);
1094 mro
= pmc
->vtable
->mro
;
1095 classcount
= VTABLE_elements(interp
, mro
);
1096 for (i
= 0; i
< classcount
; ++i
) {
1097 if (VTABLE_get_pmc_keyed_int(interp
, mro
, i
) == cl
)
1106 Parrot_new_method_cache(Interp *interp)>
1108 This should create and return a new method cache PMC.
1110 Currently it does nothing but return C<NULL>.
1117 Parrot_new_method_cache(Interp
*interp
) {
1124 Parrot_find_method_with_cache(Interp *interp, PMC *class,
1125 STRING *method_name)>
1127 Find a method PMC for a named method, given the class PMC, current
1128 interp, and name of the method.
1130 This routine should use the current scope's method cache, if there is
1131 one. If not, it creates a new method cache. Or, rather, it will when
1132 we've got that bit working. For now it unconditionally goes and looks up
1133 the name in the global stash.
1136 Parrot_find_method_direct(Interp *interp, PMC *class,
1137 STRING *method_name)>
1139 Find a method PMC for a named method, given the class PMC, current
1140 interpreter, and name of the method. Don't use a possible method cache.
1142 =item void Parrot_invalidate_method_cache(Interp *, STRING *class)
1144 Clear method cache for the given class. If class is NULL caches for
1145 all classes are invalidated.
1151 static PMC
* find_method_direct(Interp
*, PMC
*, STRING
*);
1154 mark_object_cache(Interp
*interp
)
1159 init_object_cache(Interp
*interp
)
1161 Caches
* const mc
= interp
->caches
=
1162 mem_sys_allocate_zeroed(sizeof(*mc
));
1166 #define TBL_SIZE_MASK 0x1ff /* x bits 2..10 */
1167 #define TBL_SIZE (1 + TBL_SIZE_MASK)
1170 invalidate_type_caches(Interp
*interp
, UINTVAL type
)
1172 Caches
* const mc
= interp
->caches
;
1177 /* is it a valid entry */
1178 if (type
>= mc
->mc_size
|| !mc
->idx
[type
])
1180 for (i
= 0; i
< TBL_SIZE
; ++i
) {
1181 Meth_cache_entry
*e
;
1182 for (e
= mc
->idx
[type
][i
]; e
; ) {
1183 Meth_cache_entry
* const next
= e
->next
;
1188 mem_sys_free(mc
->idx
[type
]);
1189 mc
->idx
[type
] = NULL
;
1193 invalidate_all_caches(Interp
*interp
)
1196 for (i
= 1; i
< (UINTVAL
)interp
->n_vtable_max
; ++i
)
1197 invalidate_type_caches(interp
, i
);
1201 Parrot_invalidate_method_cache(Interp
*interp
, STRING
*class, STRING
*meth
)
1205 /* during interp creation and NCI registration the class_hash
1207 if (!interp
->class_hash
)
1209 if (interp
->resume_flag
& RESUME_INITIAL
)
1212 invalidate_all_caches(interp
);
1215 type
= pmc_type(interp
, class);
1219 invalidate_all_caches(interp
);
1222 invalidate_type_caches(interp
, (UINTVAL
)type
);
1226 * quick'n'dirty method cache
1227 * TODO: use a hash if method_name is not constant
1228 * i.e. from obj.$Sreg(args)
1229 * If this hash is implemented mark it during DOD
1232 Parrot_find_method_direct(Interp
*interp
, PMC
*class,
1233 STRING
*method_name
)
1235 return find_method_direct(interp
, class, method_name
);
1239 Parrot_find_method_with_cache(Interp
*interp
, PMC
*class,
1240 STRING
*method_name
)
1247 Meth_cache_entry
*e
, *old
;
1249 assert(method_name
!= 0);
1251 #if DISABLE_METH_CACHE
1252 return find_method_direct(interp
, class, method_name
);
1255 is_const
= PObj_constant_TEST(method_name
);
1257 return find_method_direct(interp
, class, method_name
);
1259 mc
= interp
->caches
;
1260 type
= class->vtable
->base_type
;
1261 bits
= (((UINTVAL
) method_name
->strstart
) >> 2) & TBL_SIZE_MASK
;
1262 if (type
>= mc
->mc_size
) {
1264 mc
->idx
= mem_sys_realloc(mc
->idx
, sizeof(UINTVAL
*) * (type
+ 1));
1267 mc
->idx
= mem_sys_allocate(sizeof(UINTVAL
*) * (type
+ 1));
1269 for (i
= mc
->mc_size
; i
<= type
; ++i
)
1271 mc
->mc_size
= type
+ 1;
1273 if (!mc
->idx
[type
]) {
1274 mc
->idx
[type
] = mem_sys_allocate(sizeof(Meth_cache_entry
*) * TBL_SIZE
);
1275 for (i
= 0; i
< TBL_SIZE
; ++i
)
1276 mc
->idx
[type
][i
] = NULL
;
1278 e
= mc
->idx
[type
][bits
];
1280 while (e
&& e
->strstart
!= method_name
->strstart
) {
1285 PMC
* const found
= find_method_direct(interp
, class, method_name
);
1286 /* when here no or no correct entry was at [bits] */
1287 e
= mem_sys_allocate(sizeof(Meth_cache_entry
));
1291 mc
->idx
[type
][bits
] = e
;
1294 e
->strstart
= method_name
->strstart
;
1301 # define TRACE_FM(i, c, m, sub)
1304 debug_trace_find_meth(Interp
*interp
, PMC
*class, STRING
*name
, PMC
*sub
)
1310 if (!Interp_trace_TEST(interp
, PARROT_TRACE_FIND_METH_FLAG
))
1312 if (PObj_is_class_TEST(class)) {
1313 SLOTTYPE
* const class_array
= PMC_data(class);
1314 PMC
*const class_name_pmc
= get_attrib_num(class_array
, PCD_CLASS_NAME
);
1315 class_name
= PMC_str_val(class_name_pmc
);
1318 class_name
= class->vtable
->whoami
;
1320 if (sub
->vtable
->base_type
== enum_class_NCI
)
1327 tracer
= interp
->debugger
?
1328 interp
->debugger
: interp
;
1330 "# find_method class '%Ss' method '%Ss': %s\n",
1331 class_name
, name
, result
);
1334 # define TRACE_FM(i, c, m, sub) \
1335 debug_trace_find_meth(i, c, m, sub)
1339 find_method_direct_1(Interp
*interp
, PMC
*class,
1340 STRING
*method_name
)
1345 PMC
* const mro
= class->vtable
->mro
;
1346 const INTVAL n
= VTABLE_elements(interp
, mro
);
1347 for (i
= 0; i
< n
; ++i
) {
1348 class = VTABLE_get_pmc_keyed_int(interp
, mro
, i
);
1349 ns
= VTABLE_namespace(interp
, class);
1350 method
= VTABLE_get_pmc_keyed_str(interp
, ns
, method_name
);
1351 TRACE_FM(interp
, class, method_name
, method
);
1352 if (!PMC_IS_NULL(method
)) {
1356 TRACE_FM(interp
, class, method_name
, NULL
);
1361 find_method_direct(Interp
*interp
, PMC
*class,
1362 STRING
*method_name
)
1364 PMC
* const found
= find_method_direct_1(interp
, class, method_name
);
1368 s1
= CONST_STRING(interp
, "__get_string");
1369 s2
= CONST_STRING(interp
, "__get_repr");
1370 if (string_equal(interp
, method_name
, s1
) == 0)
1371 return find_method_direct_1(interp
, class, s2
);
1377 Parrot_note_method_offset(Interp *interp, UINTVAL offset, PMC *method)>
1379 Notes where in the hierarchy we just found a method. Used so that we
1380 can do a next and continue the search through the hierarchy for the
1381 next instance of this method.
1385 Parrot_note_method_offset(Interp
*interp
, UINTVAL offset
, PMC
*method
)
1392 Parrot_add_attribute(Interp *interp, PMC* class, STRING* attr)>
1394 Adds the attribute C<attr> to the class.
1400 /* Life is ever so much easier if a class keeps its attributes at the
1401 end of the attribute array, since we don't have to insert and
1402 reorder attributes. Inserting's no big deal, especially since we're
1403 going to break horribly if you insert into a class that's been
1404 subclassed, but it'll do for now */
1407 Parrot_add_attribute(Interp
*interp
, PMC
* class, STRING
* attr
)
1409 STRING
*full_attr_name
;
1412 SLOTTYPE
* const class_array
= (SLOTTYPE
*)PMC_data(class);
1413 STRING
* const class_name
= VTABLE_get_string(interp
,
1414 get_attrib_num(class_array
, PCD_CLASS_NAME
));
1415 PMC
* const attr_array
= get_attrib_num(class_array
, PCD_CLASS_ATTRIBUTES
);
1416 PMC
* const attr_hash
= get_attrib_num(class_array
, PCD_ATTRIBUTES
);
1417 INTVAL idx
= VTABLE_elements(interp
, attr_array
);
1419 VTABLE_set_integer_native(interp
, attr_array
, idx
+ 1);
1420 VTABLE_set_string_keyed_int(interp
, attr_array
, idx
, attr
);
1421 full_attr_name
= string_concat(interp
, class_name
,
1422 string_from_cstring(interp
, "\0", 1), 0);
1423 full_attr_name
= string_concat(interp
, full_attr_name
, attr
, 0);
1424 /* TODO escape NUL char */
1425 if (VTABLE_exists_keyed_str(interp
, attr_hash
, full_attr_name
))
1427 c_error
= string_to_cstring(interp
, full_attr_name
);
1428 internal_exception(1, "Attribute '%s' already exists", c_error
);
1429 string_cstring_free(c_error
);
1432 * TODO check if someone is trying to add attributes to a parent class
1433 * while there are already child class attrs
1435 idx
= CLASS_ATTRIB_COUNT(class)++;
1436 VTABLE_set_integer_keyed_str(interp
, attr_hash
,
1438 VTABLE_set_integer_keyed_str(interp
, attr_hash
,
1439 full_attr_name
, idx
);
1446 Parrot_get_attrib_by_num(Interp *interp, PMC *object, INTVAL attrib)>
1448 Returns attribute number C<attrib> from C<object>. Presumably the code
1449 is asking for the correct attribute number.
1452 Parrot_get_attrib_by_str(Interp *interp, PMC *object, STRING *attr)>
1454 Returns attribute with full qualified name C<attr> from C<object>.
1461 Parrot_get_attrib_by_num(Interp
*interp
, PMC
*object
, INTVAL attrib
)
1464 * this is called from ParrotObject's vtable now, so
1465 * their is no need for checking object being a valid
1468 SLOTTYPE
* const attrib_array
= PMC_data(object
);
1469 const INTVAL attrib_count
= PMC_int_val(object
);
1471 if (attrib
>= attrib_count
|| attrib
< 0) {
1472 real_exception(interp
, NULL
, ATTRIB_NOT_FOUND
,
1473 "No such attribute #%d", (int)attrib
);
1475 return get_attrib_num(attrib_array
, attrib
);
1479 attr_str_2_num(Interp
*interp
, PMC
*object
, STRING
*attr
)
1483 SLOTTYPE
*class_array
;
1490 if (!PObj_is_object_TEST(object
))
1491 internal_exception(INTERNAL_NOT_IMPLEMENTED
,
1492 "Can't set non-core object attribs yet");
1494 class = GET_CLASS((SLOTTYPE
*)PMC_data(object
), object
);
1495 if (PObj_is_PMC_shared_TEST(object
)) {
1496 /* XXX Shared objects have the 'wrong' class stored in them
1497 * (because of the reference to the namespace and because it
1498 * references PMCs that may go away),
1499 * since we actually want one from the current interpreter. */
1500 class = VTABLE_get_class(interp
, object
);
1502 class_array
= (SLOTTYPE
*)PMC_data(class);
1503 attr_hash
= get_attrib_num(class_array
, PCD_ATTRIBUTES
);
1504 b
= parrot_hash_get_bucket(interp
,
1505 (Hash
*) PMC_struct_val(attr_hash
), attr
);
1507 return PMC_int_val((PMC
*)b
->value
);
1509 /* Create a delimiter for splitting up the Class\0attribute syntax. */
1510 delimit
= string_from_cstring(interp
, "\0", 1);
1512 /* Calculate the offset and the length of the attribute string. */
1513 idx
= string_str_index(interp
, attr
, delimit
, 0) + 1;
1515 real_exception(interp
, NULL
, ATTRIB_NOT_FOUND
,
1516 "No such attribute '%Ss'", attr
);
1519 length
= string_length(interp
, attr
) - idx
;
1521 /* Extract the attribute and object name. */
1522 attr_name
= string_substr(interp
, attr
, idx
, length
, 0, 0);
1523 obj_name
= string_substr(interp
, attr
, 0, idx
-1, 0, 0);
1525 real_exception(interp
, NULL
, ATTRIB_NOT_FOUND
,
1526 "No such attribute '%Ss\\0%Ss'",
1527 obj_name
, attr_name
);
1533 Parrot_get_attrib_by_str(Interp
*interp
, PMC
*object
, STRING
*attr
)
1535 return Parrot_get_attrib_by_num(interp
, object
,
1536 attr_str_2_num(interp
, object
, attr
));
1542 Parrot_set_attrib_by_num(Interp *interp, PMC *object,
1543 INTVAL attrib, PMC *value)>
1545 Set attribute number C<attrib> from C<object> to C<value>. Presumably the code
1546 is asking for the correct attribute number.
1549 Parrot_set_attrib_by_str(Interp *interp, PMC *object,
1550 STRING *attr, PMC *value)>
1552 Sets attribute with full qualified name C<attr> from C<object> to C<value>.
1559 Parrot_set_attrib_by_num(Interp
*interp
, PMC
*object
,
1560 INTVAL attrib
, PMC
*value
)
1562 SLOTTYPE
* const attrib_array
= PMC_data(object
);
1563 const INTVAL attrib_count
= PMC_int_val(object
);
1565 if (attrib
>= attrib_count
|| attrib
< 0) {
1566 real_exception(interp
, NULL
, ATTRIB_NOT_FOUND
,
1567 "No such attribute #%d", (int)attrib
);
1569 set_attrib_num(object
, attrib_array
, attrib
, value
);
1573 Parrot_set_attrib_by_str(Interp
*interp
, PMC
*object
,
1574 STRING
*attr
, PMC
*value
)
1577 Parrot_set_attrib_by_num(interp
, object
,
1578 attr_str_2_num(interp
, object
, attr
),
1583 Parrot_class_offset(Interp
*interp
, PMC
*object
, STRING
*class) {
1584 PMC
*class_pmc
, *mro
, *attribs
;
1585 INTVAL offset
, i
, n
, attr_count
;
1587 if (!PObj_is_object_TEST(object
))
1588 real_exception(interp
, NULL
, 1, "Not an object");
1589 class_pmc
= GET_CLASS((SLOTTYPE
*)PMC_data(object
), object
);
1590 /* unroll common case - object is this class */
1591 attribs
= get_attrib_num(PMC_data(class_pmc
), PCD_CLASS_ATTRIBUTES
);
1592 attr_count
= VTABLE_elements(interp
, attribs
);
1593 offset
= PMC_int_val(object
) - attr_count
;
1594 if (!string_equal(interp
, VTABLE_name(interp
, class_pmc
), class))
1597 mro
= class_pmc
->vtable
->mro
;
1598 n
= VTABLE_elements(interp
, mro
);
1599 for (i
= 1; i
< n
; ++i
) {
1600 class_pmc
= VTABLE_get_pmc_keyed_int(interp
, mro
, i
);
1601 attribs
= get_attrib_num(PMC_data(class_pmc
), PCD_CLASS_ATTRIBUTES
);
1602 attr_count
= VTABLE_elements(interp
, attribs
);
1603 offset
-= attr_count
;
1604 if (!string_equal(interp
,
1605 VTABLE_name(interp
, class_pmc
), class))
1608 return -1; /* error is catched in opcode */
1613 =item C<PMC *Parrot_find_class_constructor(Interp *interp,
1614 STRING *class, INTVAL classtoken)>
1616 Find and return the constructor method PMC for the named sub. The
1617 classtoken is an identifier for the class used for fast lookup, or 0
1618 if you don't have an identifier token. Which, as they're currently
1619 undefined, is pretty likely
1625 PMC
*Parrot_find_class_constructor(Interp
*interp
, STRING
*class,
1631 PMC
*Parrot_find_class_destructor(Interp
*interp
, STRING
*class,
1637 PMC
*Parrot_find_class_fallback(Interp
*interp
, STRING
*class,
1643 void Parrot_set_class_constructor(Interp
*interp
, STRING
*class,
1644 INTVAL classtoken
, STRING
*method
)
1648 void Parrot_set_class_destructor(Interp
*interp
, STRING
*class,
1649 INTVAL classtoken
, STRING
*method
)
1653 void Parrot_set_class_fallback(Interp
*interp
, STRING
*class,
1654 INTVAL classtoken
, STRING
*method
)
1664 F<include/parrot/objects.h>, F<docs/pdds/pdd15_objects.pod>.
1673 * c-file-style: "parrot"
1675 * vim: expandtab shiftwidth=4: