tagged release 0.6.4
[parrot.git] / src / pmc / pmcproxy.pmc
blobafc979457a8bf914b1a2cde6d94c6ab35d4bc9c2
1 /*
2 Copyright (C) 2001-2008, The Perl Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/pmcproxy.pmc - proxy class object for a PMC enabling introspection
9 =head1 DESCRIPTION
11 This class is used to describe a PMC. It can sit in an inheritance hierarchy
12 of a PDD15 class as well as allowing introspection of the PMC.
14 PMCProxy is not derived from any other PMC.
16 =head2 Structure
18 This class stores its state in the Parrot_Class structure, using the
19 following fields.
21 =over 4
23 =item C<id>
25 The type number of the PMC that is being described.
27 =item C<name>
29 The name of the PMC -- a STRING.
31 =item C<namespace>
33 The namespace the PMC is associated with, if any.
35 =item C<parents>
37 An array of immediate parent classes.
38 An empty ResizablePMCArray PMC is allocated during initialization.
40 =item C<all_parents>
42 A cached array of ourself and all parent classes, in MRO order.
43 A ResizablePMCArray PMC is allocated during initialization,
44 and is populated with the current class.
46 =back
48 NOTE: No doubt we will need other things later; this is a start.
52 #include "parrot/parrot.h"
53 #include "parrot/oo_private.h"
57 =head2 Functions
59 =over 4
61 =cut
66 pmclass PMCProxy extends Class need_ext {
70 =item C<void init()>
72 Initializes a PMCProxy PMC.
74 =cut
78     VTABLE void init() {
79         Parrot_Class * const _pmc          = mem_allocate_zeroed_typed(Parrot_Class);
80         PMC          * const new_attribute = pmc_new(interp, enum_class_Hash);
81         STRING       * const name          = CONST_STRING(interp, "proxy");
82         PMC_data(SELF)                     = _pmc;
84         /* Set flags for custom DOD mark and destroy. */
85         PObj_custom_mark_SET(SELF);
86         PObj_active_destroy_SET(SELF);
88         /* Set up the object. */
89         _pmc->id               = 0;
90         _pmc->name             = CONST_STRING(interp, "");
91         _pmc->_namespace       = PMCNULL;
92         _pmc->parents          = pmc_new(interp, enum_class_ResizablePMCArray);
93         _pmc->all_parents      = pmc_new(interp, enum_class_ResizablePMCArray);
94         _pmc->roles            = pmc_new(interp, enum_class_ResizablePMCArray);
95         _pmc->methods          = pmc_new(interp, enum_class_Hash);
96         _pmc->vtable_overrides = constant_pmc_new(interp, enum_class_Hash);
97         _pmc->parent_overrides = pmc_new(interp, enum_class_Hash);
98         _pmc->attrib_metadata  = pmc_new(interp, enum_class_Hash);
99         _pmc->attrib_index     = PMCNULL;
100         _pmc->attrib_cache     = PMCNULL;
101         _pmc->resolve_method   = pmc_new(interp, enum_class_ResizablePMCArray);
103         /* Set up the attribute storage for the proxy instance */
104         VTABLE_set_string_keyed_str(interp, new_attribute, CONST_STRING(interp, "name"), name);
105         VTABLE_set_pmc_keyed_str(interp, _pmc->attrib_metadata, name, new_attribute);
107         /* We put ourself on the all parents list. */
108         VTABLE_push_pmc(interp, _pmc->all_parents, SELF);
110         /* We are a class. */
111         PObj_is_class_SET(SELF);
112     }
114     VTABLE void init_pmc(PMC *init_data) {
115         const INTVAL type_num = VTABLE_get_integer(interp, init_data);
116         Parrot_Class *proxy_info;
118         /* Ensure that it's a valid type number. */
119         if (type_num > interp->n_vtable_max || type_num <= 0)
120             real_exception(interp, NULL, 1,
121                 "Attempt to create PMC Proxy for invalid type number!");
123         /* Set up the object. */
124         SELF.init();
126         /* Set up number, name and namespace. */
127         proxy_info             = PARROT_CLASS(SELF);
128         proxy_info->id         = type_num;
129         proxy_info->name       = interp->vtables[type_num]->whoami;
130         proxy_info->_namespace = interp->vtables[type_num]->_namespace;
132         /* XXX Parents and MRO still todo. */
134         if (!PMC_IS_NULL(proxy_info->_namespace) &&
135             PMC_IS_NULL(VTABLE_get_class(interp, proxy_info->_namespace))) {
137             /* Link the proxy and the namespace, caching the proxy object for
138              * later retrieval on class lookup. */
139              Parrot_PCCINVOKE(interp, proxy_info->_namespace,
140                 CONST_STRING(interp, "set_class"), "P->", SELF);
142             /* Extract any methods from the namespace */
143             Parrot_oo_extract_methods_from_namespace(interp, SELF,
144                     proxy_info->_namespace);
145         }
146     }
150 =item C<PMC *instantiate(PMC *init)>
152 Creates an instance of the PMC.
154 =cut
157     VTABLE PMC *instantiate(PMC *init) {
158         Parrot_Class * const _pmc = PARROT_CLASS(SELF);
160         if (!PMC_IS_NULL(init))
161             return pmc_new_init(interp, _pmc->id, init);
163         return pmc_new(interp, _pmc->id);
164     }
168 =item C<void destroy()>
170 Free the memory associated with the object's underlying struct.
172 =cut
176     VTABLE void destroy() {
177         mem_sys_free(PMC_data(SELF));
178     }
182 =item C<void mark()>
184 Mark any referenced strings and PMCs in the structure as live.
186 =cut
190     VTABLE void mark() {
191         Parrot_Class * const _pmc = PARROT_CLASS(SELF);
193         if (_pmc->name)
194             pobject_lives(interp, (PObj *)_pmc->name);
195         if (_pmc->_namespace)
196             pobject_lives(interp, (PObj *)_pmc->_namespace);
197         if (_pmc->parents)
198             pobject_lives(interp, (PObj *)_pmc->parents);
199         if (_pmc->all_parents)
200             pobject_lives(interp, (PObj *)_pmc->all_parents);
201         if (_pmc->roles)
202             pobject_lives(interp, (PObj *)_pmc->roles);
203         if (_pmc->methods)
204             pobject_lives(interp, (PObj *)_pmc->methods);
205         if (_pmc->vtable_overrides)
206             pobject_lives(interp, (PObj *)_pmc->vtable_overrides);
207         if (_pmc->parent_overrides)
208             pobject_lives(interp, (PObj *)_pmc->parent_overrides);
209         if (_pmc->attrib_metadata)
210             pobject_lives(interp, (PObj *)_pmc->attrib_metadata);
211         if (_pmc->attrib_index)
212             pobject_lives(interp, (PObj *)_pmc->attrib_index);
213         if (_pmc->attrib_cache)
214             pobject_lives(interp, (PObj *)_pmc->attrib_cache);
215         if (_pmc->resolve_method)
216             pobject_lives(interp, (PObj *)_pmc->resolve_method);
217     }
221 =item C<INTVAL isa_pmc(PMC *classname)>
223 Returns whether the class is or inherits from C<*classname>.
225 =cut
229     VTABLE INTVAL isa_pmc(PMC *lookup) {
230         Parrot_Class * const _proxy = PARROT_CLASS(SELF);
231         INTVAL        i, num_classes;
232         STRING       *classname;
233         PMC          *classobj;
235         if (PMC_IS_NULL(lookup))
236             return 0;
238         if (SUPER(lookup))
239             return 1;
241         classobj = Parrot_oo_get_class(interp, lookup);
243         if (PMC_IS_NULL(classobj))
244             return 0;
246         classname = VTABLE_get_string(interp, classobj);
248         /* Check if the passed name is the same as the stored short name. */
249         if (string_equal(interp, classname, _proxy->name) == 0)
250             return 1;
252         /* Check if the class object is the same as self's class object */
253         if (VTABLE_is_same(interp, SELF, classobj))
254             return 1;
256         /* Check if the passed name is the same as the fully qualified name. */
257         if (string_equal(interp, classname, VTABLE_get_string(interp, SELF)) == 0)
258             return 1;
260         /* Iterate over all the parents and check if they respond true
261          * for 'isa' on the original comparison. */
262         num_classes = VTABLE_elements(interp, _proxy->parents);
264         for (i = 0; i < num_classes; i++) {
265             PMC * const cur_class = VTABLE_get_pmc_keyed_int(interp,
266                 _proxy->parents, i);
268             if (VTABLE_isa_pmc(interp, cur_class, lookup))
269                 return 1;
270         }
272         return 0;
273     }
276 =item C<INTVAL isa(STRING *classname)>
278 Returns whether the class is or inherits from C<*classname>.
280 =cut
284     VTABLE INTVAL isa(STRING *classname) {
285         const STRING * const pmc_proxy = CONST_STRING(interp, "PMCProxy");
287         if (string_equal(INTERP, classname, pmc_proxy) == 0)
288             return 1;
290         return SUPER(classname);
291     }
295 =item C<INTVAL does(STRING *role_name)>
297 Returns whether the class does the role with the given C<*rolename>.
299 =cut
303     VTABLE INTVAL does(STRING *role_name) {
304         Parrot_Class *_class  = PARROT_CLASS(SELF);
305         INTVAL        id      = _class->id;
306         PMC          *proxied = pmc_new_noinit(interp, id);
308         if (VTABLE_does(interp, proxied, role_name))
309             return 1;
311         return VTABLE_isa(interp, proxied, role_name);
313     }
317 =item C<INTVAL type()>
319 Returns the integer type of the class.
321 =cut
326     VTABLE INTVAL type() {
327         const Parrot_Class * const _class = PARROT_CLASS(SELF);
328         return _class->id;
329     }
333 =item C<PMC *inspect()>
335 Returns a Hash describing the PMC, with key/value pairs as described in
336 inspect_str.
338 =cut
341     PMC *inspect()
342     {
343         /* Create a hash, then use inspect_str to get all of the data to
344          * fill it up with. */
345         PMC * const metadata = pmc_new(interp, enum_class_Hash);
347         VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, "name"),
348             VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "name")));
349         VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, "namespace"),
350             VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "namespace")));
351         VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, "methods"),
352             VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "methods")));
353         VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, "parents"),
354             VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "parents")));
355         return metadata;
356     }
360 =item C<STRING *name()>
362 Gets the name of the PMC.
364 =cut
367     METHOD name() {
368         Parrot_Class * const _pmc     = PARROT_CLASS(SELF);
369         STRING       * const ret_name = _pmc->name;
370         RETURN(STRING *ret_name);
371     }
375 =item C<void get_namespace()>
377 Gets the namespace that this class is attached to.
379 =cut
382     METHOD get_namespace() {
383         Parrot_Class * const _pmc          = PARROT_CLASS(SELF);
384         PMC          * const ret_namespace = _pmc->_namespace;
385         RETURN(PMC *ret_namespace);
386     }
390 =item C<void new(PMC *args)>
392 Creates an instance of the PMC.
394 =cut
397     METHOD new(PMC *args :optional, int got_args :opt_flag) {
398         PMC * const obj = VTABLE_instantiate(interp, SELF, args);
399         UNUSED(got_args);
400         RETURN(PMC *obj);
401     }
405 =item C<void methods()>
407 Return a hash where the keys are method names and the values are methods.
409 =cut
412     METHOD methods() {
413         PMC * const ret_methods = VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "methods"));
414         RETURN(PMC *ret_methods);
415     }
419 =item C<void parents()>
421 Return the parents array PMC.
423 =cut
426     METHOD parents() {
427         PMC * const ret_parents = VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "parents"));
428         RETURN(PMC *ret_parents);
429     }
433 =item C<void inspect(STRING *what :optional)>
435 Gets all introspection data for the PMC or, if the optional string
436 parameter is supplied, a particular item of introspection data.
438 =cut
441     METHOD inspect(STRING *what :optional, int got_what :opt_flag) {
442         /* Just delegate to the appropriate vtable method. */
443         PMC * const found =
444             got_what
445                 ? VTABLE_inspect_str(interp, SELF, what)
446                 : VTABLE_inspect(interp, SELF);
448         RETURN(PMC *found);
449     }
453 =item C<STRING *get_string()>
455 Return the name of the low-level class (without the HLL namespace).
457 =cut
461     VTABLE STRING *get_string() {
462         Parrot_Class * const proxy_info = PARROT_CLASS(SELF);
464         /* Copy the stored string name of the proxy. */
465         return string_copy(interp, proxy_info->name);
466     }
469 } /* END pmclass */
473 =back
475 =head1 SEE ALSO
477 F<docs/pdds/pdd17_pmc.pod>.
479 =cut
484  * Local variables:
485  *   c-file-style: "parrot"
486  * End:
487  * vim: expandtab shiftwidth=4:
488  */