Author: jonathan
Date: Fri Jun 8 08:30:57 2007
New Revision: 18879
Modified:
trunk/src/pmc/class.pmc
trunk/t/pmc/pmcproxy.t
Log:
[PDD17] Start working towards PDD15 classes being able to inherit from PMCs. A
PMCProxy PMC can now be added as a parent. Add a test for this. This involved
fixing build_attrib_index to be aware of non-PDD15 classes. Also we now
instantiate any PMCs we inherit from, paving the way for multiple inheritance
from PMCs, and store them at the end of the attribute store when instantiating
objects.
Modified: trunk/src/pmc/class.pmc
==============================================================================
--- trunk/src/pmc/class.pmc (original)
+++ trunk/src/pmc/class.pmc Fri Jun 8 08:30:57 2007
@@ -99,32 +99,37 @@
/* We will go over the list of all parents to construct the table. */
for (i = 0; i < num_classes; i++) {
- /* Get the class and its attribute metadata hash. */
+ /* Get the class and check it's from this class universe (if not we
+ * don't know how it stores it's attributes, so we'll have to delegate
+ * the lookup). */
PMC *cur_class = VTABLE_get_pmc_keyed_int(interp, _class->all_parents,
i);
- Parrot_Class *class_info = PARROT_CLASS(cur_class);
- PMC *attribs = class_info->attrib_metadata;
- PMC *iter = VTABLE_get_iter(interp, attribs);
-
- /* Build a string representing the fully qualified class name. */
- /* Retrieve the fully qualified class name for the class. */
- STRING *fq_class = VTABLE_get_string(interp, cur_class);
-
- /* Iterate over the attributes. */
- while (VTABLE_get_bool(interp, iter)) {
- /* Get attribute. */
- PMC *cur_attrib = VTABLE_get_pmc_keyed_str(interp, attribs,
- VTABLE_shift_string(interp, iter));
- STRING *attrib_name;
- STRING *full_key = string_copy(interp, fq_class);
-
- /* Get attribute name and append it to the key. */
- attrib_name = VTABLE_get_string_keyed_str(interp, cur_attrib,
- string_from_const_cstring(interp, "name", 0));
- full_key = string_append(interp, full_key, attrib_name);
-
- /* Insert into hash, along with index. */
- VTABLE_set_integer_keyed_str(interp, table, full_key, cur_index);
- cur_index++;
+ if (VTABLE_isa(interp, cur_class, string_from_const_cstring(interp,
"Class", 0))) {
+ /* The the attribute metadata hash. */
+ Parrot_Class *class_info = PARROT_CLASS(cur_class);
+ PMC *attribs = class_info->attrib_metadata;
+ PMC *iter = VTABLE_get_iter(interp, attribs);
+
+ /* Build a string representing the fully qualified class name. */
+ /* Retrieve the fully qualified class name for the class. */
+ STRING *fq_class = VTABLE_get_string(interp, cur_class);
+
+ /* Iterate over the attributes. */
+ while (VTABLE_get_bool(interp, iter)) {
+ /* Get attribute. */
+ PMC *cur_attrib = VTABLE_get_pmc_keyed_str(interp, attribs,
+ VTABLE_shift_string(interp, iter));
+ STRING *attrib_name;
+ STRING *full_key = string_copy(interp, fq_class);
+
+ /* Get attribute name and append it to the key. */
+ attrib_name = VTABLE_get_string_keyed_str(interp, cur_attrib,
+ string_from_const_cstring(interp, "name", 0));
+ full_key = string_append(interp, full_key, attrib_name);
+
+ /* Insert into hash, along with index. */
+ VTABLE_set_integer_keyed_str(interp, table, full_key,
cur_index);
+ cur_index++;
+ }
}
}
@@ -933,12 +938,12 @@
PMC *obj;
PMC *iter;
Parrot_Object *obj_guts = NULL;
+ int i, mro_length;
/* If we've not been instantiated before... */
if (!_class->instantiated) {
/* Check that we have all methods listed in resolve list. */
int resolve_count = VTABLE_elements(interp,
_class->resolve_method);
- int i;
for (i = 0; i < resolve_count; i++) {
STRING *check_meth = VTABLE_get_string_keyed_int(interp,
_class->resolve_method, i);
@@ -987,6 +992,27 @@
VTABLE_set_attr_str(interp, obj, attr_name, attr_value);
}
+ /* We may have parents that are out of this class universe. Check the
+ * MRO for them, and if so create instances of them. Would be nice to
+ * optimize this away, using a flag or something. */
+ mro_length = VTABLE_elements(interp, _class->all_parents);
+ for (i = 0; i < mro_length; i++) {
+ PMC *class_check = VTABLE_get_pmc_keyed_int(interp,
+ _class->all_parents, i);
+ if (!VTABLE_isa(interp, class_check, CONST_STRING(interp,
"Class"))) {
+ /* From another universe. Create instance... */
+ PMC *parent_ins;
+ int position;
+ (PMC *parent_ins) = PCCINVOKE(interp, class_check, "new");
+
+ /* ...and tack on end of the attribute store (after all the
+ * slots for attributes). */
+ position = VTABLE_elements(interp, obj_guts->attrib_store);
+ VTABLE_set_pmc_keyed_int(interp, obj_guts->attrib_store,
+ position, class_check);
+ }
+ }
+
PCCRETURN(PMC *obj)
}
Modified: trunk/t/pmc/pmcproxy.t
==============================================================================
--- trunk/t/pmc/pmcproxy.t (original)
+++ trunk/t/pmc/pmcproxy.t Fri Jun 8 08:30:57 2007
@@ -6,7 +6,7 @@
use warnings;
use lib qw( . lib ../lib ../../lib );
use Test::More;
-use Parrot::Test tests => 5;
+use Parrot::Test tests => 6;
=head1 NAME
@@ -149,6 +149,27 @@
ok 3 - created the Right Thing
OUT
+pir_output_is( <<'CODE', <<'OUT', 'can add_parent a ProxyPMC in a PDD15 class'
);
+.sub 'test' :main
+ $P0 = new 'Class'
+ print "ok 1 - created a PDD15 class\n"
+
+ $P1 = get_class 'Hash'
+ print "ok 2 - got the PMCProxy for Hash\n"
+
+ addparent $P0, $P1
+ print "ok 3 - added Hash's PMCProxy as a parent of the PDD15 class\n"
+
+ $P2 = $P0.'new'()
+ print "ok 4 - instantiated the class\n"
+.end
+CODE
+ok 1 - created a PDD15 class
+ok 2 - got the PMCProxy for Hash
+ok 3 - added Hash's PMCProxy as a parent of the PDD15 class
+ok 4 - instantiated the class
+OUT
+
# Local Variables:
# mode: cperl
# cperl-indent-level: 4