Author: jonathan
Date: Fri Apr 6 14:44:42 2007
New Revision: 18018
Modified:
trunk/src/pmc/class.pmc
Log:
[PDD15]: Move numerous items of class code into the new vtable methods, and
have the sugar methods call those. Includes starting to implement inspect_str.
Modified: trunk/src/pmc/class.pmc
==============================================================================
--- trunk/src/pmc/class.pmc (original)
+++ trunk/src/pmc/class.pmc Fri Apr 6 14:44:42 2007
@@ -220,6 +220,45 @@
/*
+=item C<void add_attribute(STRING *name, PMC *type)>
+
+Adds the given attribute with an optional type.
+
+=cut
+
+*/
+ void add_attribute(STRING *name, PMC *type)
+ {
+ Parrot_Class *class = PARROT_CLASS(SELF);
+ PMC *new_attribute = pmc_new(interp, enum_class_Hash);
+
+ /* If we've been instantiated already, need a new class. */
+ if (class->instantiated) {
+ /* XXX Unimplemented! */
+ real_exception(interp, NULL, E_NotImplementedError,
+ "Modifications to already instantiated classes not allowed
yet.");
+ }
+
+ /* If we've already got an attribute of this name, it's an error. */
+ if (VTABLE_exists_keyed_str(interp, class->attrib_metadata, name)) {
+ real_exception(interp, NULL, INVALID_OPERATION,
+ "An attribute of this name already exists.");
+ }
+
+ /* Set name and type. */
+ VTABLE_set_string_keyed_str(interp, new_attribute,
+ CONST_STRING(interp, "name"), name);
+ if (!PMC_IS_NULL(type)) {
+ VTABLE_set_pmc_keyed_str(interp, new_attribute,
+ CONST_STRING(interp, "type"), type);
+ }
+
+ /* Enter the attribute in the attributes array. */
+ VTABLE_set_pmc_keyed_str(interp, class->attrib_metadata, name,
new_attribute);
+ }
+
+/*
+
=item C<void add_method(STRING *name, PMC *sub)>
Adds the given sub PMC as a method with the given name.
@@ -243,6 +282,109 @@
}
}
+/*
+
+=item C<void add_parent(PMC *parent)>
+
+Adds the supplied PMC to the list of parents for the class.
+
+=cut
+
+*/
+ void add_parent(PMC *parent)
+ {
+ Parrot_Class *class = PARROT_CLASS(SELF);
+
+ /* If we've been instantiated already, need a new class. */
+ if (class->instantiated) {
+ /* XXX Unimplemented! */
+ real_exception(interp, NULL, E_NotImplementedError,
+ "Modifications to already instantiated classes not allowed
yet.");
+ return;
+ }
+
+ /* Ensure it really is a class. */
+ if (!PObj_is_class_TEST(parent)) {
+ real_exception(interp, NULL, E_TypeError,
+ "You can only add a class as a parent to another class.");
+ return;
+ }
+
+ /* XXX Check we don't already have this parent. */
+
+ /* Add to the list of our immediate parents. */
+ VTABLE_push_pmc(interp, class->parents, parent);
+ }
+
+/*
+
+=item C<void add_role(PMC *role)>
+
+Adds the supplied PMC to the list of roles for the class, provided there are
+no conflicts.
+
+=cut
+
+*/
+ void add_role(PMC *role)
+ {
+ Parrot_Class *class = PARROT_CLASS(SELF);
+
+ /* Do the composition. */
+ Parrot_ComposeRole(interp, role, PMCNULL, 0, PMCNULL, 0,
+ class->methods, class->roles);
+ }
+
+/*
+
+=item C<PMC* inspect_str(STRING *what)>
+
+Provides introspection of a specific piece of information about the class. The
+available information is:
+
+=over 4
+
+=item attributes - Hash keyed on attribute name, value is hash describing it
+
+=item methods - Hash keyed on method name, value is an invokable PMC. Includes
+methods composed in from roles.
+
+=item roles - Array of Role PMCs. Includes roles done by the roles that were
+composed into this class.
+
+=item parents - Array of Class PMCs representing the direct parents of this
+class.
+
+=cut
+
+*/
+ PMC* inspect_str(STRING *what)
+ {
+ Parrot_Class *class = PARROT_CLASS(SELF);
+
+ /* What should we return? */
+ PMC *found;
+ if (string_equal(interp, what, CONST_STRING(interp, "attributes")) ==
0) {
+ found = class->attrib_metadata;
+ }
+ else if (string_equal(interp, what, CONST_STRING(interp, "methods"))
== 0) {
+ found = class->methods;
+ }
+ else if (string_equal(interp, what, CONST_STRING(interp, "parents"))
== 0) {
+ found = class->parents;
+ }
+ else if (string_equal(interp, what, CONST_STRING(interp, "roles")) ==
0) {
+ found = class->roles;
+ }
+ else {
+ real_exception(interp, NULL, INVALID_OPERATION,
+ "Unknown introspection value '%S'", what);
+ }
+
+ /* Clone and return. */
+ return VTABLE_clone(interp, found);
+ }
+
/* **********************************************************************
/* Below here are non-vtable methods that eventually will go in a role
@@ -408,8 +550,8 @@
*/
PCCMETHOD void attributes() {
- Parrot_Class *class = PARROT_CLASS(SELF);
- PMC *ret_attrib_metadata = VTABLE_clone(interp,
class->attrib_metadata);
+ PMC *ret_attrib_metadata = VTABLE_inspect_str(interp, SELF,
+ CONST_STRING(interp, "attributes"));
PCCRETURN(PMC *ret_attrib_metadata);
}
@@ -423,34 +565,9 @@
*/
PCCMETHOD void add_attribute(STRING *attribute_name,
- STRING* attribute_type :optional, int got_type :opt_flag) {
- Parrot_Class *class = PARROT_CLASS(SELF);
- PMC *new_attribute = pmc_new(interp, enum_class_Hash);
-
- /* If we've been instantiated already, need a new class. */
- if (class->instantiated) {
- /* XXX Unimplemented! */
- real_exception(interp, NULL, E_NotImplementedError,
- "Modifications to already instantiated classes not allowed
yet.");
- }
-
- /* If we've already got an attribute of this name, it's an error. */
- if (VTABLE_exists_keyed_str(interp, class->attrib_metadata,
attribute_name)) {
- real_exception(interp, NULL, INVALID_OPERATION,
- "An attribute of this name already exists.");
- return;
- }
-
- /* Set name and type. */
- VTABLE_set_string_keyed_str(interp, new_attribute,
- CONST_STRING(interp, "name"), attribute_name);
- if (got_type) {
- VTABLE_set_string_keyed_str(interp, new_attribute,
- CONST_STRING(interp, "type"), attribute_type);
- }
-
- /* Enter the attribute in the attributes array. */
- VTABLE_set_pmc_keyed_str(interp, class->attrib_metadata,
attribute_name, new_attribute);
+ PMC* attribute_type :optional, int got_type :opt_flag) {
+ VTABLE_add_attribute(interp, SELF, attribute_name,
+ got_type ? attribute_type : PMCNULL);
}
/*
@@ -463,8 +580,8 @@
*/
PCCMETHOD void methods() {
- Parrot_Class *class = PARROT_CLASS(SELF);
- PMC *ret_methods = VTABLE_clone(interp, class->methods);
+ PMC *ret_methods = VTABLE_inspect_str(interp, SELF,
+ CONST_STRING(interp, "methods"));
PCCRETURN(PMC *ret_methods);
}
@@ -493,8 +610,8 @@
*/
PCCMETHOD void parents() {
- Parrot_Class *class = PARROT_CLASS(SELF);
- PMC *ret_parents = VTABLE_clone(interp, class->parents);
+ PMC *ret_parents = VTABLE_inspect_str(interp, SELF,
+ CONST_STRING(interp, "parents"));
PCCRETURN(PMC *ret_parents);
}
@@ -502,31 +619,13 @@
=item C<void add_parent(PMC *parent)>
-Return the parents array PMC.
+Adds the supplied PMC to the list of parents for the class.
=cut
*/
PCCMETHOD void add_parent(PMC *parent) {
- Parrot_Class *class = PARROT_CLASS(SELF);
-
- /* If we've been instantiated already, need a new class. */
- if (class->instantiated) {
- /* XXX Unimplemented! */
- real_exception(interp, NULL, E_NotImplementedError,
- "Modifications to already instantiated classes not allowed
yet.");
- return;
- }
-
- /* Ensure it really is a class. */
- if (!PObj_is_class_TEST(parent)) {
- real_exception(interp, NULL, E_TypeError,
- "You can only add a class as a parent to another class.");
- return;
- }
-
- /* Add to the list of our immediate parents. */
- VTABLE_push_pmc(interp, class->parents, parent);
+ VTABLE_add_parent(interp, SELF, parent);
}
/*
@@ -539,8 +638,8 @@
*/
PCCMETHOD void roles() {
- Parrot_Class *class = PARROT_CLASS(SELF);
- PMC *ret_roles = VTABLE_clone(interp, class->roles);
+ PMC *ret_roles = VTABLE_inspect_str(interp, SELF,
+ CONST_STRING(interp, "roles"));
PCCRETURN(PMC *ret_roles);
}