cvsuser     03/12/05 01:36:19

  Modified:    classes  parrotclass.pmc
               include/parrot objects.h
               ops      object.ops
               src      objects.c
               t/pmc    objects.t
  Log:
  objects-2
  * get rid of class and object magic numbers
  * change init sequence a bit - creation is with pmc_new so that
    thaw could work finally
  * implement more bits of isa() and search parents
  * test isa
  
  Revision  Changes    Path
  1.10      +23 -18    parrot/classes/parrotclass.pmc
  
  Index: parrotclass.pmc
  ===================================================================
  RCS file: /cvs/public/parrot/classes/parrotclass.pmc,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -w -r1.9 -r1.10
  --- parrotclass.pmc   3 Dec 2003 11:17:37 -0000       1.9
  +++ parrotclass.pmc   5 Dec 2003 09:36:10 -0000       1.10
  @@ -1,7 +1,7 @@
   /* parrotclass.pmc
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: parrotclass.pmc,v 1.9 2003/12/03 11:17:37 leo Exp $
  + *     $Id: parrotclass.pmc,v 1.10 2003/12/05 09:36:10 leo Exp $
    *  Overview:
    *     These are the vtable functions for the ParrotClass base class
    *  Data Structure and Algorithms:
  @@ -30,22 +30,29 @@
   pmclass ParrotClass need_ext {
   
     void init () {
  -    /* Hang an array off the data pointer, empty of course */
  -    PMC_data(SELF) = pmc_new(interpreter, enum_class_SArray);
  -    /* We will have five entries in this array */
  -    VTABLE_set_integer_native(interpreter, (PMC*)PMC_data(SELF), (INTVAL)5);
       /* No attributes to start with */
       SELF->cache.int_val = 0;
       /* But we are a class, really */
       PObj_is_class_SET(SELF);
       /* And, coincidentally, data points to a PMC. Fancy that... */
       PObj_flag_SET(is_PMC_ptr, SELF);
  +     /* s. Parrot_new_class() for more initialization */
     }
   
       INTVAL isa(STRING * classname) {
  -     PMC *class = Parrot_class_lookup(interpreter, classname);
  -     if (PMC_IS_NULL(class))
  +     PMC *class;
  +     /*
  +      * a bit tricky:
  +      * a ParrotClass has a Parrot_Object vtable but isn't an objecz
  +      */
  +     if (PObj_is_class_TEST(SELF) &&
  +             0 == string_equal(interpreter, classname,
  +                 string_from_cstring(interpreter, "ParrotObject", 0))) {
            return 0;
  +     }
  +     if (SUPER(classname))
  +            return 1;
  +     class = Parrot_class_lookup(interpreter, classname);
           return Parrot_object_isa(INTERP, SELF, class);
       }
   
  @@ -56,6 +63,4 @@
        PMC *class = VTABLE_get_pmc_keyed_int(INTERP, (PMC *)PMC_data(SELF), 0);
        return Parrot_find_method_with_cache(INTERP, class, name);
       }
  -
  -
   }
  
  
  
  1.10      +17 -2     parrot/include/parrot/objects.h
  
  Index: objects.h
  ===================================================================
  RCS file: /cvs/public/parrot/include/parrot/objects.h,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -w -r1.9 -r1.10
  --- objects.h 3 Dec 2003 11:17:41 -0000       1.9
  +++ objects.h 5 Dec 2003 09:36:13 -0000       1.10
  @@ -1,7 +1,7 @@
   /* objects.h
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: objects.h,v 1.9 2003/12/03 11:17:41 leo Exp $
  + *     $Id: objects.h,v 1.10 2003/12/05 09:36:13 leo Exp $
    *  Overview:
    *     Parrot class and object header stuff
    *  Data Structure and Algorithms:
  @@ -18,8 +18,23 @@
   #define PARROT_NAMESPACE_SEPARATOR "\0"
   #define PARROT_NAMESPACE_SEPARATOR_LENGTH 1
   
  +typedef enum {
  +    PCD_PARENTS,        /* An array of immediate parents */
  +    PCD_CLASS_NAME,     /* Perlstring */
  +    PCD_ALL_PARENTS,    /* array in search order */
  +    PCD_ATTRIB_OFFS,    /* class => offset hash */
  +    PCD_ATTRIBUTES,      /* class::attrib => offset hash */
  +    PCD_MAX
  +} PARROT_CLASS_DATA_ENUM;
  +
  +typedef enum {
  +    POD_CLASS,          /* class PMC of object */
  +    POD_CLASS_NAME,     /* Perlstring */
  +    POD_FIRST_ATTRIB    /* attributes start here */
  +} PARROT_OBJECT_DATA_ENUM;
  +
   PMC *Parrot_single_subclass(Parrot_Interp, PMC *, STRING *);
  -PMC *Parrot_new_class(Parrot_Interp, STRING *);
  +void Parrot_new_class(Parrot_Interp, PMC *, STRING *);
   PMC *Parrot_class_lookup(Parrot_Interp, STRING *);
   void Parrot_class_register(Parrot_Interp, STRING *, PMC *);
   PMC *Parrot_add_parent(Parrot_Interp, PMC *, PMC *);
  
  
  
  1.19      +12 -6     parrot/ops/object.ops
  
  Index: object.ops
  ===================================================================
  RCS file: /cvs/public/parrot/ops/object.ops,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -w -r1.18 -r1.19
  --- object.ops        3 Dec 2003 13:27:05 -0000       1.18
  +++ object.ops        5 Dec 2003 09:36:15 -0000       1.19
  @@ -25,6 +25,8 @@
   Call a method on an object as per Parrot's calling conventions. We assume
   that all the registers are properly set up.
   
  +All calls assume P2 = objects, S0 = method.
  +
   =cut
   
   =item B<callmethcc>
  @@ -49,7 +51,7 @@
       /* Pitch a fit */
     }
     REG_PMC(0) = method_pmc;
  -  dest = (opcode_t *)REG_PMC(0)->vtable->invoke(interpreter, REG_PMC(0), expr 
NEXT());
  +  dest = (opcode_t *)VTABLE_invoke(interpreter, REG_PMC(0), expr NEXT());
     goto ADDRESS(dest);
   }
   
  @@ -114,7 +116,8 @@
   =cut
   
   inline op newclass(out PMC, in STR) {
  -  $1 = Parrot_new_class(interpreter, $2);
  +  PMC* class = $1 = pmc_new(interpreter, enum_class_ParrotClass);
  +  Parrot_new_class(interpreter, class, $2);
     goto NEXT();
   }
   
  @@ -211,8 +214,11 @@
   =cut
   
   inline op class(out PMC, in PMC) {
  +    if (PObj_is_class_TEST($2))
     $1 = VTABLE_get_pmc_keyed_int(interpreter,
  -                  (PMC *)PMC_data($2), 0);
  +             (PMC *)PMC_data($2), POD_CLASS);
  +    else
  +     $1 = $2;
     goto NEXT();
   }
   
  @@ -226,7 +232,7 @@
     PMC* classname_pmc;
   
     classname_pmc = VTABLE_get_pmc_keyed_int(interpreter,
  -                  (PMC *)PMC_data($2), 1);
  +                  (PMC *)PMC_data($2), POD_CLASS_NAME);
     if (classname_pmc) {
         $1 = VTABLE_get_string(interpreter, classname_pmc);
     }
  
  
  
  1.23      +89 -56    parrot/src/objects.c
  
  Index: objects.c
  ===================================================================
  RCS file: /cvs/public/parrot/src/objects.c,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -w -r1.22 -r1.23
  --- objects.c 4 Dec 2003 13:56:20 -0000       1.22
  +++ objects.c 5 Dec 2003 09:36:17 -0000       1.23
  @@ -1,7 +1,7 @@
   /* objects.c
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: objects.c,v 1.22 2003/12/04 13:56:20 leo Exp $
  + *     $Id: objects.c,v 1.23 2003/12/05 09:36:17 leo Exp $
    *  Overview:
    *     Handles class and object manipulation
    *  Data Structure and Algorithms:
  @@ -36,23 +36,28 @@
       PMC *child_class;
       PMC *child_class_array;
       PMC *classname_pmc;
  -    PMC *temp_pmc;
  +    PMC *parents, *temp_pmc;
   
       if (!PObj_is_class_TEST(base_class)) {
           internal_exception(NO_CLASS, "Can't subclass a non-class!");
       }
   
       child_class = pmc_new(interpreter, enum_class_ParrotClass);
  -    child_class_array = PMC_data(child_class);
  +    /* Hang an array off the data pointer */
  +    child_class_array = PMC_data(child_class) =
  +        pmc_new(interpreter, enum_class_SArray);
  +    /* We will have five entries in this array */
  +    VTABLE_set_integer_native(interpreter, child_class_array, PCD_MAX);
   
       /* We have the same number of attributes as our parent */
       child_class->cache.int_val = base_class->cache.int_val;
   
       /* Our parent class array has a single member in it */
  -    temp_pmc = pmc_new(interpreter, enum_class_Array);
  -    VTABLE_set_integer_native(interpreter, temp_pmc, 1);
  -    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, 0, temp_pmc);
  -    VTABLE_set_pmc_keyed_int(interpreter, temp_pmc, 0, base_class);
  +    parents = pmc_new(interpreter, enum_class_Array);
  +    VTABLE_set_integer_native(interpreter, parents, 1);
  +    VTABLE_set_pmc_keyed_int(interpreter, parents, 0, base_class);
  +    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, PCD_PARENTS,
  +            parents);
   
       /* Set the classname, if we have one */
       classname_pmc = pmc_new(interpreter, enum_class_PerlString);
  @@ -70,34 +75,37 @@
                       11, NULL, 0, NULL));
       }
   
  -    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, 1, classname_pmc);
  +    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, PCD_CLASS_NAME,
  +            classname_pmc);
   
       /* Our penultimate parent list is a clone of our parent's parent
          list, with our parent unshifted onto the beginning */
       temp_pmc = pmc_new_noinit(interpreter, enum_class_Array);
       VTABLE_clone(interpreter,
               VTABLE_get_pmc_keyed_int(interpreter,
  -                (PMC *)PMC_data(base_class), 2),
  +                (PMC *)PMC_data(base_class), PCD_ALL_PARENTS),
               temp_pmc);
       VTABLE_unshift_pmc(interpreter, temp_pmc, base_class);
  -    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, 2, temp_pmc);
  +    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, PCD_ALL_PARENTS,
  +            temp_pmc);
   
       /* Our attribute list is our parent's attribute list */
       temp_pmc = pmc_new_noinit(interpreter, enum_class_OrderedHash);
       VTABLE_clone(interpreter,
               VTABLE_get_pmc_keyed_int(interpreter,
  -                (PMC *)PMC_data(base_class), 3),
  +                (PMC *)PMC_data(base_class), PCD_ATTRIB_OFFS),
  +            temp_pmc);
  +    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, PCD_ATTRIB_OFFS,
               temp_pmc);
  -    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, 3, temp_pmc);
   
       /* And our full keyed attribute list is our parent's */
       temp_pmc = pmc_new_noinit(interpreter, enum_class_OrderedHash);
       VTABLE_clone(interpreter,
               VTABLE_get_pmc_keyed_int(interpreter,
  -                (PMC *)PMC_data(base_class), 4),
  +                (PMC *)PMC_data(base_class), PCD_ATTRIBUTES),
  +            temp_pmc);
  +    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, PCD_ATTRIBUTES,
               temp_pmc);
  -    VTABLE_set_pmc_keyed_int(interpreter, child_class_array, 4, temp_pmc);
  -
   
       Parrot_class_register(interpreter, child_class_name, child_class);
   
  @@ -108,41 +116,33 @@
    *
    * Create a brand new class, named what we pass in.
    */
  -PMC *
  -Parrot_new_class(Parrot_Interp interpreter, STRING *class_name)
  +void
  +Parrot_new_class(Parrot_Interp interpreter, PMC *class, STRING *class_name)
   {
  -    PMC *new_class;
  -    PMC *new_class_array;
  +    PMC *class_array;
       PMC *classname_pmc;
   
  -    new_class = pmc_new(interpreter, enum_class_ParrotClass);
  -    new_class_array = PMC_data(new_class);
  -    /* We have the same number of attributes as our parent */
  -    new_class->cache.int_val = 0;
  +    /* Hang an array off the data pointer, empty of course */
  +    class_array = PMC_data(class) = pmc_new(interpreter, enum_class_SArray);
  +    /* We will have five entries in this array */
  +    VTABLE_set_integer_native(interpreter, class_array, PCD_MAX);
       /* Our parent class array has nothing in it */
  -    VTABLE_set_pmc_keyed_int(interpreter, new_class_array, 0,
  +    VTABLE_set_pmc_keyed_int(interpreter, class_array, PCD_PARENTS,
               pmc_new(interpreter, enum_class_Array));
  -    VTABLE_set_pmc_keyed_int(interpreter, new_class_array, 2,
  +    VTABLE_set_pmc_keyed_int(interpreter, class_array, PCD_ALL_PARENTS,
               pmc_new(interpreter, enum_class_Array));
  -    VTABLE_set_pmc_keyed_int(interpreter, new_class_array, 3,
  +    VTABLE_set_pmc_keyed_int(interpreter, class_array, PCD_ATTRIB_OFFS,
               pmc_new(interpreter, enum_class_OrderedHash));
  -    VTABLE_set_pmc_keyed_int(interpreter, new_class_array, 4,
  +    VTABLE_set_pmc_keyed_int(interpreter, class_array, PCD_ATTRIBUTES,
               pmc_new(interpreter, enum_class_OrderedHash));
   
       /* Set the classname, if we have one */
       classname_pmc = pmc_new(interpreter, enum_class_PerlString);
       VTABLE_set_string_native(interpreter, classname_pmc, class_name);
  -    VTABLE_set_pmc_keyed_int(interpreter, new_class_array, 1, classname_pmc);
  +    VTABLE_set_pmc_keyed_int(interpreter, class_array, PCD_CLASS_NAME,
  +            classname_pmc);
   
  -    /* Add ourselves to the interpreter's class hash */
  -    if(Parrot_class_lookup(interpreter, class_name) != PMCNULL) {
  -        internal_exception(1, "Class %s already registered!\n",
  -                string_to_cstring(interpreter, class_name));
  -    }
  -
  -    Parrot_class_register(interpreter, class_name, new_class);
  -
  -    return new_class;
  +    Parrot_class_register(interpreter, class_name, class);
   }
   
   
  @@ -166,20 +166,29 @@
   Parrot_class_register(Parrot_Interp interpreter, STRING *class_name,
           PMC *new_class)
   {
  -    /* Build a new vtable for this class and register it in the
  -     * global registry .
  -     * The child class PMC has a ParrotObject vtable, which is a
  +    INTVAL new_type;
  +    VTABLE *new_vtable;
  +
  +    /*
  +     * register the class in the PMCs name hash and in the
  +     * class_name hash
  +     */
  +    if ((new_type = pmc_type(interpreter, class_name)) > enum_type_undef) {
  +        internal_exception(1, "Class %s already registered!\n",
  +                string_to_cstring(interpreter, class_name));
  +    }
  +    new_type = pmc_register(interpreter, class_name);
  +    /* Build a new vtable for this class
  +     * The child class PMC gets a ParrotObject vtable, which is a
        * good base to work from
        */
  -    VTABLE *new_vtable = Parrot_clone_vtable(interpreter,
  +    new_vtable = Parrot_clone_vtable(interpreter,
               Parrot_base_vtables[enum_class_ParrotObject]);
  -    INTVAL new_type = pmc_register(interpreter, class_name);
   
       /* register the class */
       VTABLE_set_pmc_keyed_str(interpreter, interpreter->class_hash,
               class_name, new_class);
   
  -
       /* Set the vtable's type to the newly allocated type */
       Parrot_vtable_set_type(interpreter, new_vtable, new_type);
   
  @@ -220,14 +229,15 @@
       /* Build the array that hangs off the new object */
       new_object_array = pmc_new(interpreter, enum_class_Array);
       /* Presize it */
  -    VTABLE_set_integer_native(interpreter, new_object_array, attrib_count + 2);
  +    VTABLE_set_integer_native(interpreter, new_object_array,
  +            attrib_count + POD_FIRST_ATTRIB);
       /* 0 - class PMC, 1 - class name */
  -    VTABLE_set_pmc_keyed_int(interpreter, new_object_array, 0, class);
  -    VTABLE_set_pmc_keyed_int(interpreter, new_object_array, 1,
  -            VTABLE_get_pmc_keyed_int(interpreter, class_array, 1));
  +    VTABLE_set_pmc_keyed_int(interpreter, new_object_array, POD_CLASS, class);
  +    VTABLE_set_pmc_keyed_int(interpreter, new_object_array, POD_CLASS_NAME,
  +            VTABLE_get_pmc_keyed_int(interpreter, class_array, PCD_CLASS_NAME));
   
       /* Note the number of used slots */
  -    object->cache.int_val = 2;
  +    object->cache.int_val = POD_FIRST_ATTRIB;
   
       PMC_data(object) = new_object_array;
       PObj_flag_SET(is_PMC_ptr, object);
  @@ -256,15 +266,36 @@
   /*=for api objects Parrot_object_is
    *
    * Is the object an instance of class.
  - * XXX: This should check parent classes as well, but it currently doesn't.
    */
   INTVAL
  -Parrot_object_isa(Parrot_Interp interpreter, PMC *obj, PMC *cl) {
  +Parrot_object_isa(Parrot_Interp interpreter, PMC *pmc, PMC *cl) {
       PMC * t;
  -    PMC * object_array = PMC_data(obj);
  -    t = VTABLE_get_pmc_keyed_int(interpreter, object_array, 0);
  +    PMC * object_array = PMC_data(pmc);
  +    PMC* classsearch_array; /* The array of classes we're searching */
  +    INTVAL i, classcount;
  +
  +    /* if this is a class */
  +    if (PObj_is_class_TEST(pmc)) {
  +        t = pmc;
  +        /* check if this is self */
  +        if (pmc == cl)
  +            return 1;
  +    }
  +    else {
  +        /* else get the objects class and the data array */
  +        t = VTABLE_get_pmc_keyed_int(interpreter, object_array, POD_CLASS);
  +        object_array = PMC_data(t);
  +    }
       if(t == cl)
           return 1;
  +    /* If not, time to walk through the parent class array. Wheee */
  +    classsearch_array =
  +        VTABLE_get_pmc_keyed_int(interpreter, object_array, PCD_ALL_PARENTS);
  +    classcount = VTABLE_get_integer(interpreter, classsearch_array);
  +    for (i = 0; i < classcount; ++i) {
  +        if (VTABLE_get_pmc_keyed_int(interpreter, classsearch_array, i) == cl)
  +            return 1;
  +    }
       return 0;
   }
   
  @@ -333,7 +364,7 @@
       FQ_method = string_concat(interpreter,
               VTABLE_get_string(interpreter,
                   VTABLE_get_pmc_keyed_int(interpreter,
  -                    (PMC *)PMC_data(class), 1)),
  +                    (PMC *)PMC_data(class), PCD_CLASS_NAME)),
               shortcut_name, 0);
   
       method = find_global(interpreter, FQ_method);
  @@ -345,7 +376,8 @@
   
       /* If not, time to walk through the parent class array. Wheee */
       classsearch_array =
  -        VTABLE_get_pmc_keyed_int(interpreter, (PMC *)PMC_data(class), 2);
  +        VTABLE_get_pmc_keyed_int(interpreter, (PMC *)PMC_data(class),
  +                PCD_ALL_PARENTS);
       classcount = VTABLE_get_integer(interpreter, classsearch_array);
   
       for (searchoffset = 0; NULL == method && searchoffset < classcount;
  @@ -356,7 +388,8 @@
           FQ_method = string_concat(interpreter,
                   VTABLE_get_string(interpreter,
                       VTABLE_get_pmc_keyed_int(interpreter,
  -                        (PMC *)PMC_data(curclass), 1)), shortcut_name, 0);
  +                        (PMC *)PMC_data(curclass), PCD_CLASS_NAME)),
  +                shortcut_name, 0);
           method = find_global(interpreter, FQ_method);
       }
   
  
  
  
  1.9       +96 -1     parrot/t/pmc/objects.t
  
  Index: objects.t
  ===================================================================
  RCS file: /cvs/public/parrot/t/pmc/objects.t,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -w -r1.8 -r1.9
  --- objects.t 3 Dec 2003 11:17:50 -0000       1.8
  +++ objects.t 5 Dec 2003 09:36:19 -0000       1.9
  @@ -1,6 +1,6 @@
   #! perl -w
   
  -use Parrot::Test tests => 9;
  +use Parrot::Test tests => 12;
   use Test::More;
   
   output_is(<<'CODE', <<'OUTPUT', "findclass (base class)");
  @@ -183,4 +183,99 @@
   ok 1
   ok 2
   1
  +OUTPUT
  +
  +output_is(<<'CODE', <<'OUTPUT', "new object - classname");
  +    newclass P1, "Foo"
  +    find_type I0, "Foo"
  +    new P2, I0
  +    classname S0, P1 # class
  +    print S0
  +    print "\n"
  +    classname S0, P2 # object
  +    print S0
  +    print "\n"
  +    end
  +CODE
  +Foo
  +Foo
  +OUTPUT
  +
  +output_is(<<'CODE', <<'OUTPUT', "isa subclass");
  +    newclass P1, "Foo"
  +    subclass P2, P1, "Bar"
  +    isa I0, P1, "Foo"
  +    if I0, ok1
  +    print "not "
  +ok1:
  +    print "ok 1\n"
  +    isa I0, P2, "Bar"
  +    if I0, ok2
  +    print "not "
  +ok2:
  +    print "ok 2\n"
  +    isa I0, P2, "Foo"
  +    if I0, ok3
  +    print "not "
  +ok3:
  +    print "ok 3\n"
  +    isa I0, P2, "ParrotClass"
  +    if I0, ok4
  +    print "not "
  +ok4:
  +    print "ok 4\n"
  +    isa I0, P2, "ParrotObject"
  +    unless I0, ok5
  +    print "not "
  +ok5:
  +    print "ok 5\n"
  +    end
  +CODE
  +ok 1
  +ok 2
  +ok 3
  +ok 4
  +ok 5
  +OUTPUT
  +
  +output_is(<<'CODE', <<'OUTPUT', "isa subclass - objects");
  +    newclass P3, "Foo"
  +    subclass P4, P3, "Bar"
  +    find_type I0, "Foo"
  +    new P1, I0
  +    find_type I0, "Bar"
  +    new P2, I0
  +
  +    isa I0, P1, "Foo"
  +    if I0, ok1
  +    print "not "
  +ok1:
  +    print "ok 1\n"
  +    isa I0, P2, "Bar"
  +    if I0, ok2
  +    print "not "
  +ok2:
  +    print "ok 2\n"
  +    isa I0, P2, "Foo"
  +    if I0, ok3
  +    print "not "
  +ok3:
  +    print "ok 3\n"
  +    isa I0, P2, "ParrotObject"
  +    if I0, ok4
  +    print "not "
  +ok4:
  +    print "ok 4\n"
  +    isa I0, P2, "ParrotClass"
  +    if I0, ok5
  +    print "not "
  +ok5:
  +    print "ok 5\n"
  +    end
  +CODE
  +ok 1
  +ok 2
  +ok 3
  +ok 4
  +ok 5
   OUTPUT
  
  
  

Reply via email to