Leopold Toetsch <[EMAIL PROTECTED]> wrote:

[ I'd like to have that scheme in P6E2, *if* we use it ]

> Dan Sugalski <[EMAIL PROTECTED]> wrote:
>> Okay, here's a sketch of where I'm going with the initialization,
>> finalization, and fallback method locating.

> As the current init scheme isn't really flying (and not in sync with
> this proposal) here is a first hack to get it running.

>> CONSTRUCT is the method we call when we're building the object from
>> scratch. We call it on the object and if the object wants to
>> redispatch to parents, it better do so. We'll catch that it's being
>> redispatched and call the proper parent class method even if it has a
>> different name.

>> BUILD is the method we call when we're building the object. We call
>> this on *every* class in the object's hierarchy that it exists in. No
>> redispatching, it's all automatic.

> [ ... ]

>> Also, these properties are on *names*, not method PMCs. We get a
>> two-step "look up the property, then look up the method the property
>> names" thing,

> Here is a sample program:

> $ cat o.imc
> .sub _main
>     $P0 = newclass "A"
>     $P1 = new PerlString
>     $P1 = "_new"
>     setprop $P0, "BUILD", $P1
>     $I0 = find_type "A"
>     $P2 = new PerlString
>     $P2 = "argument\n"
>     .local pmc obj
>     obj = new $I0, $P2
>     print "done\n"
>     end
> .end

> .namespace ["A"]

> .sub _new method
>     .param pmc arg
>     print "new\n"
>     print arg
> .end
> .sub __init method
>     print "init\n"
> .end

> The new scheme is currently turned on only, if the environment variable
> CALL__BUILD is set so that old code isn't broken immediately:

> $ CALL__BUILD=1 parrot o.imc
> new
> argument
> done

> $ parrot o.imc
> init
> done

> The "obj = new Iclass" can now take an optional initializer which is
> passed as first PMC arument to the BUILD or CONSTRUCT method. It's up to
> the class what this is, but we should probably define some scheme for
> HLL interoperbility.

> Comments welcome,
> leo


> --- parrot/include/parrot/objects.h   Sat Apr  3 18:00:20 2004
> +++ parrot-leo/include/parrot/objects.h       Tue Apr  6 10:10:56 2004
>@@ -44,6 +44,7 @@
>  PMC *Parrot_remove_parent(Parrot_Interp, PMC *, PMC *);
>  PMC *Parrot_multi_subclass(Parrot_Interp, PMC *, STRING *);
>  void Parrot_instantiate_object(Parrot_Interp, PMC *);
> +void Parrot_instantiate_object_init(Parrot_Interp, PMC *, PMC *);
>  INTVAL Parrot_object_isa(Parrot_Interp interpreter, PMC *, PMC *);
>  PMC *Parrot_new_method_cache(Parrot_Interp);
>  PMC *Parrot_find_method_with_cache(Parrot_Interp, PMC *, STRING *);
> --- parrot/src/objects.c      Mon Apr  5 11:24:49 2004
> +++ parrot-leo/src/objects.c  Tue Apr  6 10:21:56 2004
>@@ -440,6 +440,7 @@

>      /* Reset the init method to our instantiation method */
>      new_vtable->init = Parrot_instantiate_object;
> +    new_vtable->init_pmc = Parrot_instantiate_object_init;
>      new_class->vtable = new_vtable;

>      /* Put our new vtable in the global table */
>@@ -458,16 +459,32 @@
>      return new_type;
> }

> +static PMC*
> +get_init_meth(Parrot_Interp interpreter, PMC *class, const char * init_name)
> +{
> +    PMC *prop;
> +    STRING *prop_s, *meth;
> +    prop_s = const_string(interpreter, init_name);
> +    prop = VTABLE_getprop(interpreter, class, prop_s);
> +    if (!VTABLE_defined(interpreter, prop))
> +        return NULL;
> +    meth = VTABLE_get_string(interpreter, prop);
> +    return Parrot_find_method_with_cache(interpreter, class, meth);
> +}

>  static void
> -do_initcall(Parrot_Interp interpreter, PMC* class, PMC *object)
> +do_initcall(Parrot_Interp interpreter, PMC* class, PMC *object, PMC *init)
>  {
> -
>      SLOTTYPE *class_data = PMC_data(class);
>      PMC *classsearch_array = get_attrib_num(class_data, PCD_ALL_PARENTS);
>      PMC *parent_class;
>      INTVAL i, nparents;
> +    int free_it;
> +    /*
> +     * XXX compat mode
> +     */

> +    if (!Parrot_getenv("CALL__BUILD", &free_it)) {
>      nparents = VTABLE_elements(interpreter, classsearch_array);
>      for (i = nparents - 1; i >= 0; --i) {
>          parent_class = VTABLE_get_pmc_keyed_int(interpreter,
>@@ -476,12 +493,60 @@
>                  object, parent_class);
>      }
>      Parrot_base_vtables[enum_class_delegate]->init(interpreter, object);
> +    }
> +    else {
> +        /*
> +         * 1) if class has a CONSTRUCT property run it on the object
> +         *    no redispatch
> +         */
> +        PMC *meth = get_init_meth(interpreter, class, "CONSTRUCT");
> +        if (meth) {
> +            /* XXX S0 isn't set - create runops_method */
> +            PMC *p2 = REG_PMC(2);       /* preserve current self */
> +            REG_PMC(2) = object;
> +            if (init)
> +                Parrot_runops_fromc_args_save(interpreter, meth, "vP", init);
> +            else
> +                Parrot_runops_fromc_save(interpreter, meth);
> +            REG_PMC(2) = p2;
> +        }
> +        /*
> +         * 2. if class has a BUILD property call it for all classes
> +         *    in reverse search order - this class last.
> +         */
> +        nparents = VTABLE_elements(interpreter, classsearch_array);
> +        for (i = nparents - 1; i >= 0; --i) {
> +            parent_class = VTABLE_get_pmc_keyed_int(interpreter,
> +                    classsearch_array, i);
> +            meth = get_init_meth(interpreter, parent_class, "BUILD");
> +            if (meth) {
> +                PMC *p2 = REG_PMC(2);       /* preserve current self */
> +                REG_PMC(2) = object;
> +                if (init)
> +                    Parrot_runops_fromc_args_save(interpreter, meth, "vP",
> +                            init);
> +                else
> +                    Parrot_runops_fromc_save(interpreter, meth);
> +                REG_PMC(2) = p2;
> +            }
> +        }
> +        meth = get_init_meth(interpreter, class, "BUILD");
> +        if (meth) {
> +            PMC *p2 = REG_PMC(2);       /* preserve current self */
> +            REG_PMC(2) = object;
> +            if (init)
> +                Parrot_runops_fromc_args_save(interpreter, meth, "vP", init);
> +            else
> +                Parrot_runops_fromc_save(interpreter, meth);
> +            REG_PMC(2) = p2;
> +        }
> +    }
> }

>  /*

> =item C<void
> -Parrot_instantiate_object(Parrot_Interp interpreter, PMC *object)>
> +Parrot_instantiate_object(Parrot_Interp interpreter, PMC *object, PMC *init)>

>  Creates a Parrot object. Takes a passed-in class PMC that has sufficient
>  information to describe the layout of the object and, well, makes the
>@@ -491,9 +556,24 @@

>  */

> +static void instantiate_object(Parrot_Interp, PMC *object, PMC *init);
> +
> +void
> +Parrot_instantiate_object_init(Parrot_Interp interpreter,
> +        PMC *object, PMC *init)
> +{
> +    instantiate_object(interpreter, object, init);
> +}
> +
>  void
>  Parrot_instantiate_object(Parrot_Interp interpreter, PMC *object)
>  {
> +    instantiate_object(interpreter, object, NULL);
> +}
> +
> +static void
> +instantiate_object(Parrot_Interp interpreter, PMC *object, PMC *init)
> +{
>      SLOTTYPE *new_object_array;
>      INTVAL attrib_count;
>      SLOTTYPE *class_array;
>@@ -536,7 +616,7 @@
>      /* We really ought to call the class init routines here...
>       * this assumes that an object isa delegate
>       */
> -    do_initcall(interpreter, class, object);
> +    do_initcall(interpreter, class, object, init);
> }

>  /*

leo

Reply via email to