Author: allison
Date: Mon Jun  4 15:02:03 2007
New Revision: 18812

Modified:
   trunk/src/pmc/class.pmc
   trunk/src/pmc/object.pmc
   trunk/t/pdd15oo/objects.t

Log:
Extend the functionality of the Class PMC to pass more of the core object test
suite:
* The 'get_string' vtable function of Class PMC returns a fully-qualified name
  joined by semi-colons.
* The type of a Class PMC is "Class" (this differs from the old implementation
  that gave the fully qualified name of the class itself).
* Refactored code for setting and retrieving Class names.
* Removed 'namespace' from the class init args (wasn't in the spec anyway). The
  'name' arg takes a string, a key, or a namespace object.
* Refine type registration to link type number and class's vtable, so classes
  can be instantiated from the type number.


Modified: trunk/src/pmc/class.pmc
==============================================================================
--- trunk/src/pmc/class.pmc     (original)
+++ trunk/src/pmc/class.pmc     Mon Jun  4 15:02:03 2007
@@ -88,31 +88,6 @@
 #include "pmc_namespace.h"
 #include "classobject.h"
 
-/* Build a string representing the fully qualified class name. */
-STRING* Parrot_Class_get_fq_classname(Parrot_Interp interp, Parrot_Class 
*class_info) {
-    STRING *fq_class = string_from_cstring(interp, "", 0);
-    STRING * const separator = string_from_const_cstring(interp, "::", 0);
-    if (!PMC_IS_NULL(class_info->_namespace)) {
-        /* If we have a namespace name, make a key from its name. */
-        /* XXX BAD AND WRONG! Need to call get_name method properly! */
-        PMC * const fq_name = Parrot_NameSpace_nci_get_name(interp, 
class_info->_namespace);
-        const int elements = VTABLE_elements(interp, fq_name);
-        int j;
-        for (j = 0; j < elements; j++) {
-            /* Append to class name. */
-            fq_class = string_append(interp, fq_class,
-                VTABLE_get_string_keyed_int(interp, fq_name, j));
-            fq_class = string_append(interp, fq_class, separator);
-        }
-    } else if (class_info->name != NULL) {
-        /* If we don't have a namespace but we do have a name,
-         * use that. XXX Is this sensible? */
-        fq_class = string_copy(interp, class_info->name);
-    }
-    return fq_class;
-}
-
-
 /* This function builds the attribute index (table to map class name and
  * attribute name to an index) for the current class. */
 static void build_attrib_index(Parrot_Interp interp, PMC *self) {
@@ -131,7 +106,8 @@
         PMC *iter = VTABLE_get_iter(interp, attribs);
 
         /* Build a string representing the fully qualified class name. */
-        STRING *fq_class = Parrot_Class_get_fq_classname(interp, class_info);
+        /* 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)) {
@@ -197,21 +173,18 @@
  */
 
 static INTVAL
-register_type(Parrot_Interp interp, STRING *name)
+register_type(Parrot_Interp interp, PMC *name)
 {
     INTVAL type;
-    PMC *classname_hash, *item, *name_pmc;
+    PMC *classname_hash, *item;
 
-    if (STRING_IS_NULL(name) || STRING_IS_EMPTY(name)) {
+    if (PMC_IS_NULL(name)) {
         real_exception(interp, NULL, INVALID_OPERATION,
                 "Can't register type without a name!\n");
     }
 
-    name_pmc = pmc_new(interp, enum_class_String);
-    VTABLE_set_string_native(interp, name_pmc, name);
-
     /* First check if the type already exists */
-    fail_if_type_exists(interp, name_pmc);
+    fail_if_type_exists(interp, name);
 
     /* Type doesn't exist, so go ahead and register it. Lock interpreter so
      * pt_shared_fixup() can safely do a type lookup. */
@@ -226,7 +199,7 @@
     /* set entry in name->type hash */
     item              = pmc_new(interp, enum_class_Integer);
     PMC_int_val(item) = type;
-    VTABLE_set_pmc_keyed_str(interp, classname_hash, name, item);
+    VTABLE_set_pmc_keyed(interp, classname_hash, name, item);
     UNLOCK_INTERPRETER(interp);
     return type;
 }
@@ -237,75 +210,54 @@
 static void init_class_from_hash(Parrot_Interp interp, PMC *self, PMC *info)
 {
     Parrot_Class *_class = PARROT_CLASS(self);
-    int have_name, have_ns;
     PMC *old_ns;
-    int i;
+    INTVAL i, type_num;
 
     /* Ensure we actually have some initialization info. */
     if (PMC_IS_NULL(info))
         return;
 
-    /* Check if we have a name and/or a namespace. */
-    have_name = VTABLE_exists_keyed_str(interp, info,
-        string_from_const_cstring(interp, "name", 0));
-    have_ns = VTABLE_exists_keyed_str(interp, info,
-        string_from_const_cstring(interp, "namespace", 0));
-
     /* Take a copy of the current namespace the class is attached to. */
     old_ns = _class->_namespace;
 
-    /* Otherwise, let's roll! If we have a namespace and a name, set both. */
-    if (have_name && have_ns) {
-        /* If we weren't passed a NameSpace PMC, assume it's something we have
-         * to look one up with and do so. */
-        PMC *_namespace = VTABLE_get_pmc_keyed_str(interp, info,
-            string_from_const_cstring(interp, "namespace", 0));
-        if (!VTABLE_isa(interp, _namespace, string_from_const_cstring(interp, 
"NameSpace", 0)))
-            _namespace = Parrot_make_namespace_autobase(interp, _namespace);
-
-        /* If we get something null back it's an error; otherwise, store it. */
-        if (!PMC_IS_NULL(_namespace))
-            _class->_namespace = _namespace;
-        else
-            real_exception(interp, NULL, E_NameError, "Namespace not found");
+    /* Check if we have a name/namespace. */
+    if (VTABLE_exists_keyed_str(interp, info,
+        string_from_const_cstring(interp, "name", 0))) {
 
-        /* Set a (string) name. */
-        _class->name = VTABLE_get_string_keyed_str(interp, info,
+        STRING *new_name;
+        PMC *new_namespace;
+        PMC *name_arg = VTABLE_get_pmc_keyed_str(interp, info,
             string_from_const_cstring(interp, "name", 0));
-        register_type(interp, _class->name);
-    }
 
-    /* Otherwise, we may just have a name. */
-    else if (have_name) {
-        /* Set the name. */
-        _class->name = VTABLE_get_string_keyed_str(interp, info,
-            string_from_const_cstring(interp, "name", 0));
+        /* If we were passed a namespace PMC, set the namespace attribute
+         * directly. Otherwise, lookup or create the appropriate namespace. */
+        if (VTABLE_isa(interp, name_arg,
+                    string_from_const_cstring(interp, "NameSpace", 0)))
+            new_namespace = name_arg;
+        else {
+            new_namespace = Parrot_make_namespace_autobase(interp, name_arg);
+        }
+        if (PMC_IS_NULL(new_namespace)) {
+            real_exception(interp, NULL, INVALID_OPERATION, "Failed to set 
namespace for class.");
+        }
 
-        /* Namespace is nested in the current namespace and with the name of
-         * the class. */
-        _class->_namespace = Parrot_make_namespace_keyed_str(interp,
-            CONTEXT(interp->ctx)->current_namespace, _class->name);
-        register_type(interp, _class->name);
-    }
-
-    /* Otherwise, we may just have a namespace. */
-    else if (have_ns) {
-        /* If we weren't passed a NameSpace PMC, assume it's something we have
-         * to look one up with and do so. */
-        PMC *_namespace = VTABLE_get_pmc_keyed_str(interp, info,
-            string_from_const_cstring(interp, "namespace", 0));
-        if (!VTABLE_isa(interp, _namespace, string_from_const_cstring(interp, 
"NameSpace", 0)))
-            _namespace = Parrot_make_namespace_autobase(interp, _namespace);
-
-        /* If we get something null back it's an error; otherwise, store it. */
-        if (!PMC_IS_NULL(_namespace))
-            _class->_namespace = _namespace;
-        else
-            real_exception(interp, NULL, E_NameError, "Namespace not found");
+        /* Set the name of the class to the name of the innermost namespace
+         * associated with the class.
+         */
+        new_name = VTABLE_get_string(interp, new_namespace);
+        if (STRING_IS_NULL(new_name) || STRING_IS_EMPTY(new_name)) {
+              real_exception(interp, NULL, INVALID_OPERATION, "Failed to set 
name for class.");
+        }
+
+        _class->_namespace = new_namespace;
+        _class->name       = new_name;
 
-        /* Name is that of the most nested part of the namespace. */
-        _class->name = VTABLE_get_string(interp, _namespace);
-        register_type(interp, _class->name);
+        /* Register a type number for the class. */
+        type_num = register_type(interp, name_arg);
+
+        /* Link the type number with the class's vtable. */
+        self->vtable->base_type = type_num;
+        interp->vtables[type_num] = self->vtable;
     }
 
     /* If we were attached to a namespace and are now attached to a new one,
@@ -433,7 +385,7 @@
         /* Set up the object. */
         _class = mem_allocate_zeroed_typed(Parrot_Class);
         _class->name            = CONST_STRING(interp, "");
-        _class->_namespace       = PMCNULL;
+        _class->_namespace      = PMCNULL;
         _class->instantiated    = 0;
         _class->parents         = pmc_new(interp, 
enum_class_ResizablePMCArray);
         _class->all_parents     = pmc_new(interp, 
enum_class_ResizablePMCArray);
@@ -455,6 +407,7 @@
         Parrot_Class *_class = NULL;
         PMC *arg;
         const INTVAL arg_type = VTABLE_type(interp, init_data);
+        STRING * const name_str = CONST_STRING(interp, "name");
 
         /* Set up the object. */
         SELF.init();
@@ -463,19 +416,12 @@
         switch (arg_type)
         {
             case enum_class_String:
-                {
-                  STRING * const nameStr = CONST_STRING(interp, "name");
-                  arg = pmc_new(interp, enum_class_Hash);
-                  VTABLE_set_pmc_keyed_str(interp, arg, nameStr, init_data);
-                }
-                break;
             case enum_class_Key:
-                {
-                  STRING * const nameStr = CONST_STRING(interp, "namespace");
-                  arg = pmc_new(interp, enum_class_Hash);
-                  VTABLE_set_pmc_keyed_str(interp, arg, nameStr, init_data);
-                }
+            case enum_class_NameSpace:
+                arg = pmc_new(interp, enum_class_Hash);
+                VTABLE_set_pmc_keyed_str(interp, arg, name_str, init_data);
                 break;
+
             case enum_class_Hash:
                 arg = init_data;
                 break;
@@ -483,20 +429,20 @@
             /* slow attempt to determine init_data type */
             default:
                 if (VTABLE_isa(interp, init_data, CONST_STRING(interp, 
"String"))) {
-                    STRING * const nameStr = CONST_STRING(interp, "name");
                     arg = pmc_new(interp, enum_class_Hash);
-                    VTABLE_set_pmc_keyed_str(interp, arg, nameStr, init_data);
+                    VTABLE_set_pmc_keyed_str(interp, arg, name_str, init_data);
                 }
                 else if (VTABLE_isa(interp, init_data, CONST_STRING(interp, 
"Key"))) {
-                    STRING *nameStr = CONST_STRING(interp, "namespace");
                     arg = pmc_new(interp, enum_class_Hash);
-                    VTABLE_set_pmc_keyed_str(interp, arg, nameStr, init_data);
+                    VTABLE_set_pmc_keyed_str(interp, arg, name_str, init_data);
                 }
+
                 if (VTABLE_isa(interp, init_data, CONST_STRING(interp, 
"Hash"))) {
                     arg = init_data;
                 }
                 else {
-                    return;
+                    arg = pmc_new(interp, enum_class_Hash);
+                    VTABLE_set_pmc_keyed_str(interp, arg, name_str, init_data);
                 }
                 break;
         }
@@ -552,20 +498,33 @@
 
 /*
 
-=item C<STRING* name()>
+=item C<STRING* get_string()>
 
-Return the classname.
+Return the fully qualified name of the class.
 
 =cut
 
 */
 
-    STRING* name() {
+    STRING* get_string() {
         Parrot_Class * const _class = PARROT_CLASS(SELF);
-        if (STRING_IS_NULL(_class->name) || STRING_IS_EMPTY(_class->name)) {
-            return SELF->vtable->whoami;
+        PMC * namespace = _class->_namespace;
+        PMC * names;
+        if (!PMC_IS_NULL(namespace)) {
+            /* Call the 'get_name' method on the class's associated namespace
+             * to retrieve a fully qualified list of names, then join the list
+             * with a semicolon.
+             */
+            STRING * ret_name;
+            names = Parrot_NameSpace_nci_get_name(interp, namespace);
+            if (!PMC_IS_NULL(names)) {
+                ret_name = string_join(interp, CONST_STRING(interp, ";"), 
names);
+                return ret_name;
+            }
         }
-        return _class->name;
+
+        /* Otherwise, copy the stored string name of the class. */
+        return string_copy(interp, _class->name);
     }
 
 /*

Modified: trunk/src/pmc/object.pmc
==============================================================================
--- trunk/src/pmc/object.pmc    (original)
+++ trunk/src/pmc/object.pmc    Mon Jun  4 15:02:03 2007
@@ -45,7 +45,7 @@
             Parrot_Class *class_info = PARROT_CLASS(cur_class);
 
             /* Build a string representing the fully qualified attribute name. 
*/
-            STRING *fq_name = Parrot_Class_get_fq_classname(interp, 
class_info);
+            STRING *fq_name = VTABLE_get_string(interp, cur_class);
             fq_name = string_append(interp, fq_name, name);
 
             /* Look up. */

Modified: trunk/t/pdd15oo/objects.t
==============================================================================
--- trunk/t/pdd15oo/objects.t   (original)
+++ trunk/t/pdd15oo/objects.t   Mon Jun  4 15:02:03 2007
@@ -69,8 +69,8 @@
     newpdd15class P1, ["Foo"; "Bar"]
 
     find_type I0, ["Foo"; "Bar"]
-    isgt I0, I0, 0
-    print I0
+    isgt I1, I0, 0
+    print I1
     print "\n"
 
     new P3, I0

Reply via email to