Author: jonathan
Date: Sun Apr 15 14:25:48 2007
New Revision: 18230
Modified:
trunk/src/pmc/class.pmc
trunk/t/pmc/class.t
Log:
[PDD15]: Implement initializing attributes, methods, parents, roles and the
resolve_method list for both init_pmc and clone_pmc. Add a test for it in the
init case (clone calls the same code anyway).
Modified: trunk/src/pmc/class.pmc
==============================================================================
--- trunk/src/pmc/class.pmc (original)
+++ trunk/src/pmc/class.pmc Sun Apr 15 14:25:48 2007
@@ -183,6 +183,7 @@
Parrot_Class *class = PARROT_CLASS(self);
int have_name, have_ns;
PMC *old_ns;
+ int i;
/* Ensure we actually have some initialization info. */
if (PMC_IS_NULL(info))
@@ -260,8 +261,71 @@
Parrot_PCCINVOKE(interp, class->namespace,
string_from_const_cstring(interp, "set_class", 0),
"P->", self);
+
+ /* Initialize resolve_method. */
+ if (VTABLE_exists_keyed_str(interp, info,
+ string_from_const_cstring(interp, "resolve_method", 0))) {
+ /* Set it. */
+ class->resolve_method = VTABLE_get_pmc_keyed_str(interp, info,
+ string_from_const_cstring(interp, "resolve_method", 0));
+ }
+
+ /* Initialize parents, if we have any. */
+ if (VTABLE_exists_keyed_str(interp, info,
+ string_from_const_cstring(interp, "parents", 0))) {
+ /* Loop over parents array and add them. */
+ PMC *parent_list = VTABLE_get_pmc_keyed_str(interp, info,
+ string_from_const_cstring(interp, "parents", 0));
+ int parent_count = VTABLE_elements(interp, parent_list);
+ for (i = 0; i < parent_count; i++) {
+ PMC *parent = VTABLE_get_pmc_keyed_int(interp, parent_list, i);
+ VTABLE_add_parent(interp, self, parent);
+ }
+ }
+
+ /* Initialize roles, if we have any. */
+ if (VTABLE_exists_keyed_str(interp, info,
+ string_from_const_cstring(interp, "roles", 0))) {
+ /* Loop over roles array and compose them. */
+ PMC *role_list = VTABLE_get_pmc_keyed_str(interp, info,
+ string_from_const_cstring(interp, "roles", 0));
+ int role_count = VTABLE_elements(interp, role_list);
+ for (i = 0; i < role_count; i++) {
+ PMC *role = VTABLE_get_pmc_keyed_int(interp, role_list, i);
+ VTABLE_add_role(interp, self, role);
+ }
+ }
+
+ /* Initialize attributes, if we have any. */
+ if (VTABLE_exists_keyed_str(interp, info,
+ string_from_const_cstring(interp, "attributes", 0))) {
+ /* Loop over attributes array and add them. */
+ PMC *attrib_name_list = VTABLE_get_pmc_keyed_str(interp, info,
+ string_from_const_cstring(interp, "attributes", 0));
+ int attrib_count = VTABLE_elements(interp, attrib_name_list);
+ for (i = 0; i < attrib_count; i++) {
+ STRING *attrib_name = VTABLE_get_string_keyed_int(interp,
+ attrib_name_list, i);
+ VTABLE_add_attribute(interp, self, attrib_name, PMCNULL);
+ }
+ }
+
+ /* Initialize methods. */
+ if (VTABLE_exists_keyed_str(interp, info,
+ string_from_const_cstring(interp, "methods", 0))) {
+ /* Get the methods hash. */
+ PMC *methods = VTABLE_get_pmc_keyed_str(interp, info,
+ string_from_const_cstring(interp, "methods", 0));
- /* XXX TODO: initialize resolve, parents, roles, attributes, methods. */
+ /* Iterate over the list of methods. */
+ PMC *iter = VTABLE_get_iter(interp, methods);
+ while (VTABLE_get_bool(interp, iter)) {
+ /* Add the method. */
+ STRING *method_name = VTABLE_shift_string(interp, iter);
+ PMC *method_pmc = VTABLE_get_pmc_keyed_str(interp, methods,
method_name);
+ VTABLE_add_method(interp, self, method_name, method_pmc);
+ }
+ }
}
Modified: trunk/t/pmc/class.t
==============================================================================
--- trunk/t/pmc/class.t (original)
+++ trunk/t/pmc/class.t Sun Apr 15 14:25:48 2007
@@ -6,7 +6,7 @@
use warnings;
use lib qw( . lib ../lib ../../lib );
use Test::More;
-use Parrot::Test tests => 12;
+use Parrot::Test tests => 13;
=head1 NAME
@@ -404,6 +404,56 @@
ok 6 - can modify cloned class
OUT
+pir_output_is( <<'CODE', <<'OUT', 'new with initialization hash' );
+.sub 'test' :main
+ $P0 = new 'Hash'
+
+ # We'll have some attributes...
+ $P1 = new 'ResizablePMCArray'
+ $P1[0] = 'x'
+ $P1[1] = 'y'
+ $P0['attributes'] = $P1
+
+ # And a method.
+ $P1 = new 'Hash'
+ $P2 = find_global 'add'
+ $P1['add'] = $P2
+ $P0['methods'] = $P1
+
+ $P1 = new 'Class', $P0
+ print "ok 1 - created new class with attributes and methods supplied\n"
+
+ # Instantiate and try setting each attribute.
+ $P2 = $P1.'new'()
+ $P3 = new 'Integer'
+ $P3 = 37
+ setattribute $P2, 'x', $P3
+ print "ok 2 - set first attribute\n"
+ $P3 = new 'Integer'
+ $P3 = 5
+ setattribute $P2, 'y', $P3
+ print "ok 3 - set second attribute\n"
+
+ # Call method.
+ $P3 = $P2.add()
+ print $P3
+ print "\nok 4 - called method\n"
+.end
+.sub add :method
+ $P0 = getattribute self, "x"
+ $P1 = getattribute self, "y"
+ $P2 = new 'Integer'
+ $P2 = $P0 + $P1
+ .return($P2)
+.end
+CODE
+ok 1 - created new class with attributes and methods supplied
+ok 2 - set first attribute
+ok 3 - set second attribute
+42
+ok 4 - called method
+OUT
+
# Local Variables:
# mode: cperl
# cperl-indent-level: 4