Author: jonathan
Date: Sat Apr  7 14:51:37 2007
New Revision: 18030

Modified:
   trunk/src/pmc/role.pmc

Log:
[PDD15]: Move much Role PMC functionality into vtable methods to improve 
interoperability; implement inspect and inspect_str vtable methods.

Modified: trunk/src/pmc/role.pmc
==============================================================================
--- trunk/src/pmc/role.pmc      (original)
+++ trunk/src/pmc/role.pmc      Sat Apr  7 14:51:37 2007
@@ -115,50 +115,163 @@
             pobject_lives(interp, (PObj*)role->attrib_metadata);
     }
 
+/*
+
+=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_Role *role = PARROT_ROLE(SELF);
+        PMC *new_attribute = pmc_new(interp, enum_class_Hash);
+
+        /* 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, role->attrib_metadata, name, 
new_attribute);
+    }
 
 /*
 
-=item C<void attributes()>
+=item C<void add_method(STRING *name, PMC *sub)>
 
-Return a hash where the keys are attribute names and the values are hashes
-providing a set of key/value pairs describing the attribute.
+Adds the given sub PMC as a method with the given name.
 
 =cut
 
 */
-    PCCMETHOD void attributes() {
+    void add_method(STRING *name, PMC *sub)
+    {
         Parrot_Role *role = PARROT_ROLE(SELF);
-        PMC *ret_attrib_metadata = VTABLE_clone(interp, role->attrib_metadata);
-        PCCRETURN(PMC *ret_attrib_metadata);
+
+        /* If we have already added a method with this name... */
+        if (VTABLE_exists_keyed_str(interp, role->methods, name)) {
+            /* XXX Need to handle multi methods here. */
+            real_exception(interp, NULL, E_NotImplementedError,
+                "Currently, adding multiple methods of the same name is not 
supported.");
+        }
+        else {
+            /* Enter it into the table. */
+            VTABLE_set_pmc_keyed_str(interp, role->methods, name, sub);
+        }
     }
 
+/*
+
+=item C<void add_role(PMC *role)>
+
+Composes the supplied Role PMC into this role, provided there are no
+conflicts.
+
+=cut
+
+*/
+    void add_role(PMC *role)
+    {
+        Parrot_Role *this_role = PARROT_ROLE(SELF);
+
+        /* Do the composition. */
+        Parrot_ComposeRole(interp, role, PMCNULL, 0, PMCNULL, 0,
+                           this_role->methods, this_role->roles);
+    }
 
 /*
 
-=item C<void add_attribute()>
+=item C<PMC* inspect_str(STRING *what)>
 
-Add an attribute to the role. Requires a name and, optionally, a type.
+Provides introspection of a specific piece of information about the role. The
+available information is:
+
+=over 4
+
+=item name - String PMC containing the name of the role
+
+=item namespce - NameSpace PMC of the the namespace attached to the role
+
+=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 role.
 
 =cut
 
 */
-    PCCMETHOD void add_attribute(STRING *attribute_name,
-            STRING* attribute_type :optional, int got_type :opt_flag) {
+    PMC* inspect_str(STRING *what)
+    {
         Parrot_Role *role = PARROT_ROLE(SELF);
-        PMC *new_attribute = pmc_new(interp, enum_class_Hash);
 
-        /* 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);
+        /* What should we return? */
+        PMC *found;
+        if (string_equal(interp, what, CONST_STRING(interp, "name")) == 0) {
+            found = pmc_new(interp, enum_class_String);
+            VTABLE_set_string_native(interp, found, role->name);
+        }
+        else if (string_equal(interp, what, CONST_STRING(interp, "namespace")) 
== 0) {
+            found = role->namespace;
+        }
+        else if (string_equal(interp, what, CONST_STRING(interp, 
"attributes")) == 0) {
+            found = role->attrib_metadata;
+        }
+        else if (string_equal(interp, what, CONST_STRING(interp, "methods")) 
== 0) {
+            found = role->methods;
+        }
+        else if (string_equal(interp, what, CONST_STRING(interp, "roles")) == 
0) {
+            found = role->roles;
+        }
+        else {
+            real_exception(interp, NULL, INVALID_OPERATION,
+                "Unknown introspection value '%S'", what);
         }
 
-        /* Enter the attribute in the attributes array. */
-        VTABLE_set_pmc_keyed_str(interp, role->attrib_metadata, 
attribute_name, new_attribute);
+        /* Clone and return. */
+        return VTABLE_clone(interp, found);
+    }
+
+/*
+
+=item C<PMC* inspect()>
+
+Returns a Hash describing the role, with key/value pairs as described in
+inspect_str.
+
+*/
+    PMC* inspect()
+    {
+        /* Create a hash, then use inspect_str to get all of the data to
+         * fill it up with. */
+        PMC *metadata = pmc_new(interp, enum_class_Hash);
+        VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, 
"name"),
+            VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "name")));
+        VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, 
"namespace"),
+            VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, 
"namespace")));
+        VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, 
"attributes"),
+            VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, 
"attributes")));
+        VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, 
"methods"),
+            VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "methods")));
+        VTABLE_set_pmc_keyed_str(interp, metadata, CONST_STRING(interp, 
"roles"),
+            VTABLE_inspect_str(interp, SELF, CONST_STRING(interp, "roles")));
+        return metadata;
     }
 
+    /* **********************************************************************
+    /* Below here are non-vtable methods that eventually will go in a role
+     * that is composed into here to optionally give a nice interface from
+     * PIR (ParrotRole isa Role does RoleMethods or something like this).
+     * **********************************************************************/
+
 /*
 
 =item C<void name()>
@@ -225,17 +338,34 @@
 
 /*
 
-=item C<void roles()>
+=item C<void attributes()>
 
-Return the roles array PMC.
+Return a hash where the keys are attribute names and the values are hashes
+providing a set of key/value pairs describing the attribute.
 
 =cut
 
 */
-    PCCMETHOD void roles() {
-        Parrot_Role *role = PARROT_ROLE(SELF);
-        PMC *ret_roles = VTABLE_clone(interp, role->roles);
-        PCCRETURN(PMC *ret_roles);
+    PCCMETHOD void attributes() {
+        PMC *ret_attrib_metadata = VTABLE_inspect_str(interp, SELF,
+            CONST_STRING(interp, "attributes"));
+        PCCRETURN(PMC *ret_attrib_metadata);
+    }
+
+
+/*
+
+=item C<void add_attribute()>
+
+Add an attribute to the role. Requires a name and, optionally, a type.
+
+=cut
+
+*/
+    PCCMETHOD void add_attribute(STRING *attribute_name,
+            PMC* attribute_type :optional, int got_type :opt_flag) {
+        VTABLE_add_attribute(interp, SELF, attribute_name,
+            got_type ? attribute_type : PMCNULL);
     }
 
 /*
@@ -248,8 +378,8 @@
 
 */
     PCCMETHOD void methods() {
-        Parrot_Role *role = PARROT_ROLE(SELF);
-        PMC *ret_methods = VTABLE_clone(interp, role->methods);
+        PMC *ret_methods = VTABLE_inspect_str(interp, SELF,
+            CONST_STRING(interp, "methods"));
         PCCRETURN(PMC *ret_methods);
     }
 
@@ -264,18 +394,22 @@
 */
     PCCMETHOD void add_method(STRING *name, PMC *sub)
     {
-        Parrot_Role *role = PARROT_ROLE(SELF);
+        VTABLE_add_method(interp, SELF, name, sub);
+    }
 
-        /* If we have already added a method with this name... */
-        if (VTABLE_exists_keyed_str(interp, role->methods, name)) {
-            /* XXX Need to handle multi methods here. */
-            real_exception(interp, NULL, E_NotImplementedError,
-                "Currently, adding multiple methods of the same name is not 
supported.");
-        }
-        else {
-            /* Enter it into the table. */
-            VTABLE_set_pmc_keyed_str(interp, role->methods, name, sub);
-        }
+/*
+
+=item C<void roles()>
+
+Return the roles array PMC.
+
+=cut
+
+*/
+    PCCMETHOD void roles() {
+        PMC *ret_roles = VTABLE_inspect_str(interp, SELF,
+            CONST_STRING(interp, "roles"));
+        PCCRETURN(PMC *ret_roles);
     }
 
 /*

Reply via email to