2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/pmc/pmcproxy.pmc - proxy class object for a PMC enabling introspection
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.
18 This class stores its state in the Parrot_Class structure, using the
25 The type number of the PMC that is being described.
29 The name of the PMC -- a STRING.
33 The namespace the PMC is associated with, if any.
37 An array of immediate parent classes.
38 An empty ResizablePMCArray PMC is allocated during initialization.
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.
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"
66 pmclass PMCProxy extends Class need_ext {
72 Initializes a PMCProxy PMC.
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. */
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);
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. */
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);
150 =item C<PMC *instantiate(PMC *init)>
152 Creates an instance of the PMC.
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);
168 =item C<void destroy()>
170 Free the memory associated with the object's underlying struct.
176 VTABLE void destroy() {
177 mem_sys_free(PMC_data(SELF));
184 Mark any referenced strings and PMCs in the structure as live.
191 Parrot_Class * const _pmc = PARROT_CLASS(SELF);
194 pobject_lives(interp, (PObj *)_pmc->name);
195 if (_pmc->_namespace)
196 pobject_lives(interp, (PObj *)_pmc->_namespace);
198 pobject_lives(interp, (PObj *)_pmc->parents);
199 if (_pmc->all_parents)
200 pobject_lives(interp, (PObj *)_pmc->all_parents);
202 pobject_lives(interp, (PObj *)_pmc->roles);
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);
221 =item C<INTVAL isa_pmc(PMC *classname)>
223 Returns whether the class is or inherits from C<*classname>.
229 VTABLE INTVAL isa_pmc(PMC *lookup) {
230 Parrot_Class * const _proxy = PARROT_CLASS(SELF);
231 INTVAL i, num_classes;
235 if (PMC_IS_NULL(lookup))
241 classobj = Parrot_oo_get_class(interp, lookup);
243 if (PMC_IS_NULL(classobj))
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)
252 /* Check if the class object is the same as self's class object */
253 if (VTABLE_is_same(interp, SELF, classobj))
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)
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,
268 if (VTABLE_isa_pmc(interp, cur_class, lookup))
276 =item C<INTVAL isa(STRING *classname)>
278 Returns whether the class is or inherits from C<*classname>.
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)
290 return SUPER(classname);
295 =item C<INTVAL does(STRING *role_name)>
297 Returns whether the class does the role with the given C<*rolename>.
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))
311 return VTABLE_isa(interp, proxied, role_name);
317 =item C<INTVAL type()>
319 Returns the integer type of the class.
326 VTABLE INTVAL type() {
327 const Parrot_Class * const _class = PARROT_CLASS(SELF);
333 =item C<PMC *inspect()>
335 Returns a Hash describing the PMC, with key/value pairs as described in
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")));
360 =item C<STRING *name()>
362 Gets the name of the PMC.
368 Parrot_Class * const _pmc = PARROT_CLASS(SELF);
369 STRING * const ret_name = _pmc->name;
370 RETURN(STRING *ret_name);
375 =item C<void get_namespace()>
377 Gets the namespace that this class is attached to.
382 METHOD get_namespace() {
383 Parrot_Class * const _pmc = PARROT_CLASS(SELF);
384 PMC * const ret_namespace = _pmc->_namespace;
385 RETURN(PMC *ret_namespace);
390 =item C<void new(PMC *args)>
392 Creates an instance of the PMC.
397 METHOD new(PMC *args :optional, int got_args :opt_flag) {
398 PMC * const obj = VTABLE_instantiate(interp, SELF, args);
405 =item C<void methods()>
407 Return a hash where the keys are method names and the values are methods.
413 PMC * const ret_methods = VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "methods"));
414 RETURN(PMC *ret_methods);
419 =item C<void parents()>
421 Return the parents array PMC.
427 PMC * const ret_parents = VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "parents"));
428 RETURN(PMC *ret_parents);
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.
441 METHOD inspect(STRING *what :optional, int got_what :opt_flag) {
442 /* Just delegate to the appropriate vtable method. */
445 ? VTABLE_inspect_str(interp, SELF, what)
446 : VTABLE_inspect(interp, SELF);
453 =item C<STRING *get_string()>
455 Return the name of the low-level class (without the HLL namespace).
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);
477 F<docs/pdds/pdd17_pmc.pod>.
485 * c-file-style: "parrot"
487 * vim: expandtab shiftwidth=4: