[Xotcl] Re: [Xotcl] RE: [Xotcl] Re: [Xotcl] Object mixin with passing init args ?

uwe.zdun@uni-essen.de uwe.zdun@uni-essen.de
Wed, 13 Dec 2000 11:39:02 +0100 (CET)


>>>>> "ZV" == Zoran Vasiljevic <zoran@munich.com> writes:

ZV> ------Original Message------
ZV> From: <uwe.zdun@uni-essen.de>
ZV> To: Zoran Vasiljevic <zoran@munich.com>
ZV> Sent: December 13, 2000 9:55:56 AM GMT


>> 2. However, in the "mixin" case we could enable argument passing,
>> because "mixin" has just one argument? The rest could be passed > to
ZV> "init". any objections?

ZV> obj mixin Foo arg1 arg2 arg3

ZV> would pass arg1-arg3 to init of Foo. Right?

yes

ZV> obj mixin [list Foo Bar] arg1 arg2 arg3

ZV> would pass arg1-arg3 to init of Foo AND of Bar. Right again?

yes

ZV> Is so, then I think it should be done, if possible. 0.85 ? 0.9 ?

if there are no objections we can include this right now (and
officially in 0.84) ... its just a little change ... Just exchange
the appended XOTclOMixinMethod in xotcl.c and re-compile to test it:

#################################################
Class A
A instproc init args {puts [self class]--$args;next}
Class C
C instproc init args {puts [self class]--$args;next}

Class B
B instproc init args {puts [self class]--$args;next}

B b
# every thing works
puts ++++++++++++++++++++++++++
b mixin A arg1 arg2 arg3
puts ++++++++++++++++++++++++++
b mixin {A C} arg1 arg2
puts ++++++++++++++++++++++++++
b mixin {A C} arg1
puts ++++++++++++++++++++++++++
b mixin {A C}

# but here we have to add the args ... because  "mixin"
# is called before "init"  
puts ++++++++++++++++++++++++++
B b2 a1 a2 a3 -mixin {A C} 
puts ++++++++++++++++++++++++++
B b2 a1 a2 a3 -mixin {A C} a1 a2 a3

#################################################

--Uwe

-- 
Uwe Zdun
Specification of Software Systems, University of Essen
Phone: +49 201 81 00 332, Fax: +49 201 81 00 398
zdun@xotcl.org, uwe.zdun@uni-essen.de

########################################################################

static int
XOTclOMixinMethod (ClientData cd, Tcl_Interp* in, int objc, Tcl_Obj *objv[]) {
  int oc; Tcl_Obj** ov;
  XOTclObject* obj = XOTclAsObject(in, cd);
  int i, result = TCL_OK;
  XOTclClass     *mcl=0;
  Tcl_ObjCmdProc *mproc = 0;
  Command        *mProcInfo =0;
  ClientData     mcp;
  int isDestroyed = 0;

  if (!obj) return XOTclObjErrType(in, obj->cmdName, "Object");
  if (objc < 2)
    return XOTclObjErrArgCnt(in, obj->cmdName, "mixin <classes> ?args?");

  if (Tcl_ListObjGetElements(in,objv[1], &oc, &ov)!= TCL_OK) return TCL_ERROR;

  MixinRemoveList(&obj->mixins);
  obj->mixinDefined = XOTCL_MIXINS_INVALID;

  for (i = 0; i < oc; i++) {
    char* av = ObjStr(ov[i]);
    XOTclClass* mixin = XOTclGetClass(in, av);
    if (!mixin)
      return XOTclErrBadVal(in, "a list of classes", ObjStr(objv[1]));
    if (!XOTclIsClass(in, (ClientData) mixin))
      return XOTclVarErrMsg(in, "Mixin for ", ObjStr(obj->cmdName),
				 " must be class, got: ", av, (char*)0);
    MixinAdd(in, &obj->mixins, mixin);
  }

  MixinComputeDefined(in, obj);

  /*
   * call "init" on the mixin
   */
  MixinStackPush(obj);
  obj->mixinStack->mixinInit = 1;
  obj->mixinStack->mixinChainOn = 1;

  mProcInfo = MixinSearchProc(in, obj, "init",
			      &mcl, &mproc, &mcp);
  if (mproc) {
    int oc = objc-1;
    DEFINE_NEW_TCL_OBJECTS_ON_STACK(oc,ov);
    ov[0] = global_objects[INIT];
    memcpy(ov+1, objv+2, sizeof(Tcl_Obj *)*(oc-1));
    /* set flag to prevent calling a mixin/the class constructor twice */
    result = callProcCheck(mcp, in, oc, ov, mProcInfo,
			   obj, mcl, "init", 0, 1 /*isMixinEntry*/, &isDestroyed);
    
    FREE_TCL_OBJECTS_ON_STACK(ov);
  }

  if (!isDestroyed && obj->mixinStack)
    MixinStackPop(obj);

  return result;
}