tagged release 0.6.4
[parrot.git] / src / pmc / default.pmc
blobd5d5db655e72ca1d81129bd9e81bebac13f7b337
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/default.pmc - Abstract root class
9 =head1 DESCRIPTION
11 These are the vtable functions for the default PMC class.
13 All methods which are not defined here get a default implementation
14 generated from F<src/vtable.tbl> by F<tools/build/pmc2c.pl>.
16 =head2 Functions
18 =over 4
20 =cut
24 #include "parrot/parrot.h"
26 #define INT2KEY(i, k) key_new_integer((i), (k))
28 /* undef 'interface' to keep MSVC happy */
29 #undef interface
33 =item C<static const char *caller(PARROT_INTERP, PMC *pmc)>
35 Returns a C string for the name of C<*pmc>.
37 =cut
41 static const char *
42 caller(PARROT_INTERP, PMC *pmc /*NULLOK*/)
44     return pmc && pmc->vtable && pmc->vtable->whoami ?
45         VTABLE_name(interp, pmc)->strstart : "(null)";
50 =item C<static void cant_do_method(PARROT_INTERP, PMC *pmc,
51                                    const char *methname)>
53 Throws an exception "$methname() not implemented in class '$class'", used by
54 all unimplemented messages.
56 =cut
60 static void
61 cant_do_method(PARROT_INTERP, PMC *pmc /*NULLOK*/, const char *methname)
63     real_exception(interp, NULL, ILL_INHERIT,
64                        "%s() not implemented in class '%s'", methname,
65                        caller(interp, pmc));
70 =item C<static INTVAL
71 check_set_std_props(PARROT_INTERP, PMC *pmc, STRING *key, PMC *value)>
73 Called from C<setprop()>.
75 Returns a true value if C<setprop()> can avoid actually setting a property
76 in the prophash. If it returns true, the property setting will be reflected
77 in a future call to C<propagate_std_props()>
79 =cut
83 static INTVAL
84 check_set_std_props(PARROT_INTERP, PMC *pmc, STRING *key, PMC *value)
86     /* the quick hack below cannot be used because the string could
87        be constructed in an interpreter that is later destroyed */
88 #if  0
89     /* RT #46659
90      * a quick hack, to prevent freeing that string during DOD
91      * triggered in t/pmc/pmc_62.t when configured with --gc=libc
92      */
93     static STRING *ro;
94     if (!ro)
95         ro = string_make(interp, "_ro", 3, "ascii",
96             PObj_constant_FLAG|PObj_external_FLAG);
97     if (!string_compare(interp, key, ro)) {
98 #else
100     /*
101      * s2 in string_compare is freed here
102      */
103     if (!string_compare(interp, key, CONST_STRING(interp, "_ro"))) {
104 #endif
105         /* pmc should set/clear readonly */
106         const INTVAL on = VTABLE_get_bool(interp, value);
108         /* morph to Const/normal class or readonly class */
109         /* RT #46661 warn when this fails? */
110         if (on && (pmc->vtable->flags & VTABLE_HAS_CONST_TOO))
111             pmc->vtable = interp->vtables[pmc->vtable->base_type + 1];
112         else if (!on && (pmc->vtable->flags & (VTABLE_IS_CONST_FLAG)))
113             VTABLE_morph(interp, pmc, pmc->vtable->base_type - 1);
114         else if (on && (pmc->vtable->flags & VTABLE_HAS_READONLY_FLAG))
115             pmc->vtable = pmc->vtable->ro_variant_vtable;
116         else if (!on && (pmc->vtable->flags & VTABLE_IS_READONLY_FLAG)
117                 && pmc->vtable->ro_variant_vtable)
118             pmc->vtable = pmc->vtable->ro_variant_vtable;
119         else
120             return 0;
122         return 1;
123     }
125     return 0;
130 =item C<static void
131 propagate_std_props(PARROT_INTERP, PMC *self, PMC *prop_hash)>
133 Set pending standard properties in C<prop_hash>.
135 =cut
139 static void
140 propagate_std_props(PARROT_INTERP, PMC *self, PMC *prop_hash) {
141     if (self->vtable->flags & (VTABLE_IS_CONST_FLAG | VTABLE_IS_READONLY_FLAG)){
142         PMC * const pmc_true  = pmc_new(interp, enum_class_Integer);
143         PMC_int_val(pmc_true) = 1;
144         VTABLE_set_pmc_keyed_str(interp, prop_hash, CONST_STRING(interp, "_ro"), pmc_true);
145     }
150 =item C<static INTVAL
151 has_pending_std_props(PMC *self)>
153 Returns true if propagate_std_props() would create a non-empty prophash.
155 =cut
159 static INTVAL
160 has_pending_std_props(PMC *self) {
161     if (self->vtable->flags & (VTABLE_IS_CONST_FLAG | VTABLE_IS_READONLY_FLAG))
162         return 1;
163     else
164         return 0;
170 =item C<static PMC*
171 check_get_std_props(PARROT_INTERPeter, PMC *self, STRING *key)>
173 Checks if we can infer the value of C<key> property from C<self> without
174 looking at its prophash. Returns C<PMCNULL> if not, returns the value otherwise.
176 =cut
179 static PMC*
180 check_get_std_props(PARROT_INTERP, PMC *self, STRING *key) {
181     if ((self->vtable->flags & (VTABLE_IS_CONST_FLAG | VTABLE_IS_READONLY_FLAG))
182         &&!string_compare(interp, key, CONST_STRING(interp, "_ro"))) {
183         PMC * const ret_val  = pmc_new(interp, enum_class_Integer);
184         PMC_int_val(ret_val) = 1;
185         return ret_val;
186     }
187     else
188         return PMCNULL;
193 =item C<static PMC *
194 make_prop_hash(PARROT_INTERP, PMC *self)>
196 Create a property hash for C<self>. Returns the created hash. Inferred
197 properties will be added to the hash and it will be set as
198 C<PMC_metadata(self)>.
200 =cut
204 static PMC*
205 make_prop_hash(PARROT_INTERP, PMC *self) {
206     PMC *prop;
208     if (!self->pmc_ext)
209         add_pmc_ext(interp, self);
211     PMC_metadata(self) = prop = pmc_new_noinit(interp, enum_class_Hash);
212     GC_WRITE_BARRIER(interp, self, NULL, prop);
213     VTABLE_init(interp, prop);
214     propagate_std_props(interp, self, prop);
215     return prop;
220 =item C<static INTVAL
221 does_isa(PARROT_INTERP, STRING *method, STRING *what)>
223 Compares C<*method> and C<*what>.
224 Returns true (1) if B<method> is found in B<what>, false (0) otherwise.
226 =cut
230 static INTVAL
231 does_isa(PARROT_INTERP, const STRING *method, const STRING *what)
233     INTVAL pos = 0;
235     do {
236         INTVAL len;
238         pos = string_str_index(interp, what, method, pos);
240         if (pos < 0)
241             return 0;
243         if (pos >= (INTVAL)string_length(interp, what))
244             return 0;
246         len = string_length(interp, method);
248         if (pos && string_index(interp, what, pos - 1) != 32) {
249             pos += len;
250             continue;
251         }
253         if (pos+len < (INTVAL)string_length(interp, what) &&
254             string_index(interp, what, pos + len) != 32) {
255             pos += len;
256             continue;
257         }
259         return 1;
260     } while (1);
263 pmclass default abstract no_init {
267 =back
269 =head2 Methods
271 =over 4
273 =item C<void init()>
275 Does nothing.
277 =cut
281     VTABLE void init() {
282     }
286 =item C<void init_pmc(PMC *initializer)>
288 With a null C<initializer>, calls C<init()>, else throws an exception.
290 =cut
294     VTABLE void init_pmc(PMC *initializer) {
295         if (PMC_IS_NULL(initializer))
296             SELF.init();
297         else
298             real_exception(interp, NULL, ILL_INHERIT,
299                        "init_pmc() not implemented in class '%s'",
300                        caller(interp, pmc));
301     }
305 =item C<PMC *instantiate(PMC *init)>
307 Default fallback. Creates a new PMC of the type of the class SELF and
308 calls init().
310 =cut
314     VTABLE PMC *instantiate(PMC *init) {
315         const INTVAL type = VTABLE_type(INTERP, SELF);
317         /* Ensure no looping, as pmc_new calls the instantiate vtable entry for
318          * classes. */
319         if (PObj_is_class_TEST(SELF))
320             real_exception(interp, NULL, 1,
321                     "All high-level classes should override instantiate");
323         if (!PMC_IS_NULL(init))
324             return pmc_new_init(INTERP, type, init);
326         return pmc_new(INTERP, type);
327     }
331 =item C<void mark()>
333 Panics with a "no custom mark routine defined" error message.
335 =cut
339     VTABLE void mark() {
340         PANIC(INTERP, "custom_mark flag set but no custom mark routine defined");
341     }
345 =item C<PMC *getprop(STRING *key)>
347 Returns the property for C<*key>. If no property is defined then the
348 NULL PMC is returned.
350 =cut
354     VTABLE PMC *getprop(STRING *key) {
355         if (SELF->pmc_ext && PMC_metadata(SELF))
356             return VTABLE_get_pmc_keyed_str(INTERP, PMC_metadata(SELF), key);
357         else
358             return check_get_std_props(interp, SELF, key);
359     }
363 =item C<void setprop(STRING *key, PMC *value)>
365 Sets the property for C<*key> to C<*value>.
367 =cut
371     VTABLE void setprop(STRING *key, PMC *value) {
372         if (check_set_std_props(INTERP, SELF, key, value))
373             return;
375         if (SELF->pmc_ext && PMC_metadata(SELF)) {
376             VTABLE_set_pmc_keyed_str(INTERP,
377                 PMC_metadata(SELF), key, value);
378         }
379         else {
380             PMC * const prop = make_prop_hash(INTERP, SELF);
382             /* RT #46663 is this too late for --gc-debug? */
383             VTABLE_set_pmc_keyed_str(INTERP, prop, key, value);
384         }
385     }
389 =item C<void delprop(STRING *key)>
391 Deletes the property for C<*key>.
393 =cut
397     VTABLE void delprop(STRING *key) {
398         if (SELF->pmc_ext && PMC_metadata(SELF))
399             VTABLE_delete_keyed_str(INTERP, PMC_metadata(SELF), key);
400     }
404 =item C<PMC *getprops()>
406 Returns the PMC's properties or the NULL PMC if no properties exist.
408 =cut
412     VTABLE PMC *getprops() {
413         if (!SELF->pmc_ext)
414             add_pmc_ext(INTERP, SELF);
416         if (!PMC_metadata(SELF)) {
417             if (has_pending_std_props(SELF))
418                 return make_prop_hash(INTERP, SELF);
419             else
420                 return PMCNULL;
421         }
423         return PMC_metadata(SELF);
424     }
428 =item C<INTVAL type()>
430 Returns the PMC's type.
432 =cut
436     VTABLE INTVAL type() {
437         return SELF->vtable->base_type;
438     }
442 =item C<INTVAL type_keyed_int(INTVAL key)>
444 Converts C<key> to a PMC key and returns the result of calling
445 C<type_keyed()> with it.
447 =cut
451     VTABLE INTVAL type_keyed_int(INTVAL key) {
452         PMC *const r_key = INT2KEY(INTERP, key);
453         return SELF.type_keyed(r_key);
454     }
458 =item C<STRING *name()>
460 Returns the name of the PMC.
462 =cut
466     VTABLE STRING *name() {
467         return SELF->vtable->whoami;
468     }
473 =item C<PMC *get_namespace>
475 Return the namespace for this PMC.
477 =item C<PMC *find_method(STRING *method_name)>
479 Looks up the method for C<*method_name> and returns it. If no method is
480 found then C<NULL> is returned.
482 =item C<void add_method(STRING *method_name, PMC *sub)>
484 Store the method as a global in the namespace of this class.
486 =cut
490     VTABLE PMC *get_namespace() {
491         return SELF->vtable->_namespace;
492     }
495     VTABLE PMC *find_method(STRING *method_name) {
496         return Parrot_find_method_with_cache(INTERP, SELF, method_name);
497     }
499     VTABLE void add_method(STRING *method_name, PMC *sub_pmc) {
500         VTABLE_set_pmc_keyed_str(INTERP, SELF->vtable->_namespace,
501                                  method_name, sub_pmc);
502     }
505 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
507 Converts C<key> to a PMC key and returns the result of calling
508 C<get_integer_keyed()> with it.
510 =cut
514     VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
515         PMC *const r_key = INT2KEY(INTERP, key);
516         return SELF.get_integer_keyed(r_key);
517     }
521 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
523 Converts C<key> to a PMC key and returns the result of calling
524 C<get_number_keyed()> with it.
526 =cut
530     VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
531         PMC *const r_key = INT2KEY(INTERP, key);
532         return SELF.get_number_keyed(r_key);
533     }
538 =item C<STRING *get_string_keyed_int(INTVAL key)>
540 Converts C<key> to a PMC key and returns the result of calling
541 C<get_string_keyed()> with it.
543 =cut
547     VTABLE STRING *get_string_keyed_int(INTVAL key) {
548         PMC *const r_key = INT2KEY(INTERP, key);
549         return SELF.get_string_keyed(r_key);
550     }
554 =item C<INTVAL elements_keyed_int(INTVAL key)>
556 Converts C<key> to a PMC key and returns the result of calling
557 C<elements_keyed()> with it.
559 =cut
563     INTVAL elements_keyed_int(INTVAL key) {
564         PMC *const r_key = INT2KEY(INTERP, key);
565         return SELF.elements_keyed(r_key);
566     }
571 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
573 Converts C<key> to a PMC key and returns the result of calling
574 C<get_pmc_keyed()> with it.
576 =cut
580     VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
581         PMC *const r_key = INT2KEY(INTERP, key);
582         return SELF.get_pmc_keyed(r_key);
583     }
587 =item C<void *get_pointer()>
589 Returns the address of the PMC.
591 =cut
595     VTABLE void *get_pointer() {
596         return SELF;
597     }
601 =item C<INTVAL is_same(PMC *value)>
603 Returns whether the PMC is numerically equal to C<value>.
605 =cut
609     VTABLE INTVAL is_same(PMC *value) {
610         return SELF == value;
611     }
615 =item C<void assign_pmc(PMC *value)>
617 =item C<void assign_string_native(PMC *value)>
619 Defaults fall back to C<set_pmc> and C<set_string_native>.
621 =cut
625     VTABLE void assign_pmc(PMC *value) {
626         STRING * const undef = CONST_STRING(INTERP, "Undef");
628         if (VTABLE_isa(INTERP, value, undef))
629             pmc_reuse(INTERP, SELF, value->vtable->base_type, 0);
630         else
631             SELF.set_pmc(value);
632     }
634     VTABLE void assign_string_native(STRING *value) {
635         SELF.set_string_native(value);
636     }
640 =item C<void morph(INTVAL type)>
642 Changes the PMC to a PMC of a new type
644 =cut
648     VTABLE void morph(INTVAL type) {
649         pmc_reuse(INTERP, SELF, type, 0);
650     }
654 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
656 Converts C<key> to a PMC key and calls C<set_integer_keyed()> with it
657 and C<value>.
659 =cut
663     VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
664         PMC *const r_key = INT2KEY(INTERP, key);
665         SELF.set_integer_keyed(r_key, value);
666     }
670 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
672 Converts C<key> to a PMC key and calls C<set_number_keyed()> with it
673 and C<value>.
675 =cut
679     VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
680         PMC *const r_key = INT2KEY(INTERP, key);
681         SELF.set_number_keyed(r_key, value);
682     }
686 =item C<void set_string_keyed_int(INTVAL key, STRING *string)>
688 Converts C<key> to a PMC key and calls C<set_string_keyed()> with it
689 and C<value>.
691 =cut
695     VTABLE void set_string_keyed_int(INTVAL key, STRING *string) {
696         PMC *const r_key = INT2KEY(INTERP, key);
697         SELF.set_string_keyed(r_key, string);
698     }
702 =item C<void set_bool_keyed_int(INTVAL key, INTVAL value)>
704 Converts C<key> to a PMC key and calls C<set_bool_keyed()> with it
705 and C<value>.
707 =cut
711     void set_bool_keyed_int(INTVAL key, INTVAL value) {
712         PMC *const r_key = INT2KEY(INTERP, key);
713         SELF.set_bool_keyed(r_key, value);
714     }
718 =item C<void set_pmc_keyed_int(INTVAL key, PMC *value)>
720 Converts C<key> to a PMC key and calls C<set_pmc_keyed()> with it
721 and C<value>.
723 =cut
727     VTABLE void set_pmc_keyed_int(INTVAL key, PMC *value) {
728         PMC *const r_key = INT2KEY(INTERP, key);
729         SELF.set_pmc_keyed(r_key, value);
730     }
734 =item C<INTVAL is_equal(PMC *value)>
736 Returns whether the PMC is equal to C<*value>.
738 =cut
742     VTABLE INTVAL is_equal(PMC *value) {
743         return (SELF->vtable         == value->vtable
744             &&  PMC_struct_val(SELF) == PMC_struct_val(value)
745             &&  PMC_data(SELF)       == PMC_data(value));
746     }
750 =item C<INTVAL is_equal_num(PMC *value)>
752 Returns whether the PMC is numerically equal to C<*value>.
754 =cut
758     VTABLE INTVAL is_equal_num(PMC *value) {
759         return (VTABLE_get_number(INTERP, SELF) ==
760                 VTABLE_get_number(INTERP, value));
761     }
765 =item C<INTVAL is_equal_str(PMC *value)>
767 Returns whether the PMC is numerically equal to C<*value>.
769 =cut
773     VTABLE INTVAL is_equal_str(PMC *value) {
774         return (0 == string_equal(INTERP, VTABLE_get_string(INTERP, SELF),
775                                           VTABLE_get_string(INTERP, value)));
776     }
782 =item C<INTVAL exists_keyed_int(INTVAL key)>
784 Converts C<key> to a PMC key and returns the result of calling
785 C<exists_keyed()> with it.
787 =cut
791     VTABLE INTVAL exists_keyed_int(INTVAL key) {
792         PMC *const r_key = INT2KEY(INTERP, key);
793         return SELF.exists_keyed(r_key);
794     }
798 =item C<INTVAL defined()>
800 Returns true.
802 =cut
806     VTABLE INTVAL defined() {
807         return 1;
808     }
812 =item C<INTVAL defined_keyed_int(INTVAL key)>
814 Converts C<key> to a PMC key and returns the result of calling
815 C<defined_keyed()> with it.
817 =cut
821     VTABLE INTVAL defined_keyed_int(INTVAL key) {
822         PMC *const r_key = INT2KEY(INTERP, key);
823         return SELF.defined_keyed(r_key);
824     }
828 =item C<void delete_keyed_int(INTVAL key)>
830 Converts C<key> to a PMC key and calls C<delete_keyed()> with it.
832 =cut
836     VTABLE void delete_keyed_int(INTVAL key) {
837         PMC *const r_key = INT2KEY(INTERP, key);
838         SELF.delete_keyed(r_key);
839     }
843 =item C<PMC *nextkey_keyed_int(INTVAL key, INTVAL w)>
845 Converts C<key> to a PMC key and returns the result of calling
846 C<nextkey_keyed()> with it.
848 =cut
852     VTABLE PMC *nextkey_keyed_int(INTVAL key, INTVAL w) {
853         PMC *const r_key = INT2KEY(INTERP, key);
854         return SELF.nextkey_keyed(r_key, w);
855     }
859 =item C<INTVAL can(STRING *method)>
861 Reports whether the PMC "can" perform C<method>.
862 If the PMC implements the vtable function C<method>,
863 true (1) is returned; otherwise, false (0) is returned.
865 =cut
869     VTABLE INTVAL can(STRING *method) {
870         return !PMC_IS_NULL(VTABLE_find_method(INTERP, SELF, method));
871     }
875 =item C<INTVAL does(STRING *interface)>
877 Reports whether the PMC "does" perform C<interface>.
878 If the interface C<interface> is found in the PMC's interface list,
879 true (1) is returned; otherwise, false (0) is returned.
881 =cut
885     VTABLE INTVAL does(STRING *_interface) {
886         return does_isa(INTERP, _interface, SELF->vtable->provides_str);
887     }
891 =item C<INTVAL does_pmc(PMC *role)>
893 Reports whether the PMC "does" the C<role>.
895 =cut
899     INTVAL does_pmc(PMC *role) {
900         /* No C-level roles yet. */
901         return 0;
902     }
906 =item C<INTVAL isa_pmc(PMC *_class)>
908 Reports whether the PMC "isa" C<_class>.
909 If the class C<_class> is found in the PMC's class hierarchy,
910 true (1) is returned; otherwise, false (0) is returned.
912 =cut
916     VTABLE INTVAL isa_pmc(PMC *lookup) {
917         /* RT #46665 - walk mro */
918         return parrot_hash_exists(INTERP, SELF->vtable->isa_hash,
919                 (void *)VTABLE_get_string(interp, lookup));
920     }
924 =item C<INTVAL isa(STRING *_class)>
926 Reports whether the PMC "isa" C<_class>.
927 If the class C<_class> is found in the PMC's class hierarchy,
928 true (1) is returned; otherwise, false (0) is returned.
930 =cut
934     VTABLE INTVAL isa(STRING *_class) {
935         /* RT #46665 - walk mro */
936         return parrot_hash_exists(INTERP, SELF->vtable->isa_hash,
937                     (void *)_class);
938     }
942 =item C<PMC *inspect_str(STRING *what)>
944 Provides introspection of a specific piece of information about the PMC.
946 =cut
950     PMC *inspect_str(STRING *name) {
951         PMC *found;
952         if (string_equal(interp, name, CONST_STRING(interp, "flags")) == 0) {
953             found = pmc_new(interp, enum_class_Integer);
954             VTABLE_set_integer_native(interp, found, PObj_get_FLAGS(SELF));
955         }
956         else {
957             real_exception(interp, NULL, INVALID_OPERATION,
958                 "Unknown introspection value '%S'", name);
959         }
960         return found;
961     }
965 =item C<PMC *inspect()>
967 Returns a Hash describing the class, with key/value pairs as described in
968 inspect_str.
970 =cut
973     PMC *inspect() {
974         PMC    *metadata           = pmc_new(interp, enum_class_Hash);
975         STRING * const flags_str   = CONST_STRING(interp, "flags");
977         VTABLE_set_pmc_keyed_str(interp, metadata, flags_str,
978             VTABLE_inspect_str(interp, SELF, flags_str));
980         return metadata;
981     }
985 =item C<PMC *get_class()>
987 Returns SELF. A PMC is its own class.
989 =item C<PMC *get_attr_str(STRING *attr)>
991 Look for NCI methods and properties.
993 =cut
996     VTABLE PMC *get_class() {
997         PMC *ns     = VTABLE_get_namespace(interp, SELF);
998         PMC *_class = PMCNULL;
1000         if (!PMC_IS_NULL(ns))
1001             _class = VTABLE_get_class(interp, ns);
1003         if (PMC_IS_NULL(_class)) {
1004             INTVAL type      = VTABLE_type(interp, SELF);
1005             PMC   *type_num  = pmc_new(interp, enum_class_Integer);
1006             VTABLE_set_integer_native(interp, type_num, type);
1007             return pmc_new_init(interp, enum_class_PMCProxy, type_num);
1008         }
1010         return _class;
1012     }
1014     VTABLE PMC *get_attr_str(STRING *name) {
1015         PMC *p = PMCNULL;
1017         /* let's look for props first
1018          * RT #46667 do we need that in the default object system?
1019          */
1020         if (SELF->pmc_ext && PMC_metadata(SELF)) {
1021              const HashBucket * const b =
1022                 parrot_hash_get_bucket(INTERP, (Hash *)PMC_metadata(SELF), name);
1024              if (b)
1025                  p = (PMC *)b->value;
1026         }
1028         /* may be NCI? */
1029         if (PMC_IS_NULL(p))
1030             p = VTABLE_find_method(INTERP, SELF, name);
1032         if (PMC_IS_NULL(p))
1033             return PMCNULL;
1035         if (VTABLE_isa(INTERP, p, CONST_STRING(INTERP, "NCI"))) {
1036             PMC * const bound_meth = VTABLE_clone(INTERP, p);
1037             bound_meth->vtable     = interp->vtables[enum_class_Bound_NCI];
1038             VTABLE_set_pmc(INTERP, bound_meth, SELF);
1040             return bound_meth;
1041         }
1042         else if (p->vtable->base_type == enum_class_MultiSub) {
1043             PMC * const bound_meth      = pmc_new(INTERP, enum_class_Bound_NCI);
1044             VTABLE_set_pmc(INTERP, bound_meth, SELF);
1045             PMC_struct_val(bound_meth)  = p;
1046             PObj_get_FLAGS(bound_meth) |= PObj_private0_FLAG;
1048             return bound_meth;
1049         }
1051         /* RT #46671 bound user functions */
1052         return p;
1053     }
1057 =item C<PMC *get_attr_keyed(PMC *key, STRING *name)>
1059 Default version of keyed attribute lookups. Discards the key and does a lookup
1060 by the string name passed in.
1062 =item C<void set_attr_keyed(PMC *key, STRING *name, PMC *value)>
1064 Default version of keyed attribute set. Discards the key and does a set by
1065 the string name passed in.
1067 =cut
1070     VTABLE PMC *get_attr_keyed(PMC *key, STRING *name) {
1071         return VTABLE_get_attr_str(INTERP, SELF, name);
1072     }
1074     VTABLE void set_attr_keyed(PMC *key, STRING *name, PMC *value) {
1075         VTABLE_set_attr_str(INTERP, SELF, name, value);
1076     }
1080 =item C<void add_parent(PMC *parent)>
1082 Add class C<parent> to the list of our parents.
1084 =cut
1088     VTABLE void add_parent(PMC *parent) {
1089         if (!PObj_is_class_TEST(SELF))
1090             real_exception(interp, NULL, 1, "Only classes can be subclassed");
1092         real_exception(interp, NULL, 1, "All classes should override add_parent");
1093     }
1097 =item C<void visit(visit_info *info)>
1099 Used by DOD to mark the PMC.
1101 =cut
1105     VTABLE void visit(visit_info *info) {
1106         /* default - mark prop hash */
1107         if (SELF->pmc_ext && PMC_metadata(SELF) &&
1108             info->extra_flags != EXTRA_IS_PROP_HASH) {
1109             info->extra_flags = EXTRA_IS_PROP_HASH;
1110             info->extra       = PMC_metadata(SELF);
1112             /* place escape mark */
1113             (info->visit_pmc_now)(INTERP, SELF, info);
1115             /* place and the prop hash */
1116             (info->visit_pmc_now)(INTERP, PMC_metadata(SELF), info);
1117         }
1118     }
1122 =item C<PMC* clone()>
1124 Clones this PMC.  By default, this just does a freeze and thaw.
1126 =cut
1130     VTABLE PMC* clone() {
1131         return Parrot_thaw(interp, Parrot_freeze(interp, SELF));
1132     }
1136 =item C<void freeze(visit_info *info)>
1138 Does nothing.
1140 =cut
1144     VTABLE void freeze(visit_info *info) {
1145         /* default - no action */
1146     }
1150 =item C<void thaw(visit_info *info)>
1152 Initializes the PMC during unarchiving.
1154 =cut
1158     VTABLE void thaw(visit_info *info) {
1159         /* default - initialize the PMC */
1160         if (info->extra_flags == EXTRA_IS_PROP_HASH) {
1161             if (!SELF->pmc_ext)
1162                 add_pmc_ext(INTERP, SELF);
1164             info->thaw_ptr  = &PMC_metadata(SELF);
1165             info->container = SELF;
1167             (info->visit_pmc_now)(INTERP, PMC_metadata(SELF), info);
1168         }
1169         else
1170             SELF.init();
1171     }
1175 =item C<void thawfinish(visit_info *info)>
1177 Does nothing.
1179 =cut
1183     void thawfinish(visit_info *info) {
1184         /* default - no action */
1185     }
1191 =back
1193 =cut
1198  * Local variables:
1199  *   c-file-style: "parrot"
1200  * End:
1201  * vim: expandtab shiftwidth=4:
1202  */