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