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