Index: generic/xotcl.c =================================================================== diff -u -r5a0750dc422574bc5ae91d9b58c64b8f5713d405 -r7afa0b7f3e63e10eb45a65a7360285ba9590f514 --- generic/xotcl.c (.../xotcl.c) (revision 5a0750dc422574bc5ae91d9b58c64b8f5713d405) +++ generic/xotcl.c (.../xotcl.c) (revision 7afa0b7f3e63e10eb45a65a7360285ba9590f514) @@ -6236,42 +6236,41 @@ static int convertToSwitch(Tcl_Interp *interp, Tcl_Obj *objPtr, XOTclParam CONST *pPtr, ClientData *clientData) { return convertToBoolean(interp, objPtr, pPtr, clientData); } -static int convertToObject(Tcl_Interp *interp, Tcl_Obj *objPtr, XOTclParam CONST *pPtr, ClientData *clientData) { - if (GetObjectFromObj(interp, objPtr, (XOTclObject **)clientData) == TCL_OK) - return TCL_OK; - return XOTclObjErrType(interp, objPtr, "object"); -} -static int convertToClass(Tcl_Interp *interp, Tcl_Obj *objPtr, XOTclParam CONST *pPtr, ClientData *clientData) { - if (GetClassFromObj(interp, objPtr, (XOTclClass **)clientData, 0) == TCL_OK) { - return TCL_OK; - } - return XOTclObjErrType(interp, objPtr, "class"); -} -static int convertToObjectOfType(Tcl_Interp *interp, Tcl_Obj *objPtr, XOTclParam CONST *pPtr, ClientData *clientData) { - XOTclObject *object; +static int objectOfType(Tcl_Interp *interp, XOTclObject *object, Tcl_Obj *objPtr, XOTclParam CONST *pPtr) { XOTclClass *cl; - Tcl_Obj *valueObj = pPtr->converterArg; Tcl_DString ds, *dsPtr = &ds; - - if (valueObj == NULL) - return XOTclVarErrMsg(interp, "No object type specified", (char *) NULL); - - if ((GetObjectFromObj(interp, objPtr, &object) == TCL_OK) - && (GetClassFromObj(interp, valueObj, &cl, 0) == TCL_OK) + + if (pPtr->converterArg == NULL) + return TCL_OK; + + if ((GetClassFromObj(interp, pPtr->converterArg, &cl, 0) == TCL_OK) && isSubType(object->cl, cl)) { - *clientData = object; return TCL_OK; } DSTRING_INIT(dsPtr); Tcl_DStringAppend(dsPtr, "object of type ", -1); - Tcl_DStringAppend(dsPtr, ObjStr(valueObj), -1); + Tcl_DStringAppend(dsPtr, ObjStr(pPtr->converterArg), -1); XOTclObjErrType(interp, objPtr, Tcl_DStringValue(dsPtr)); DSTRING_FREE(dsPtr); return TCL_ERROR; } +static int convertToObject(Tcl_Interp *interp, Tcl_Obj *objPtr, XOTclParam CONST *pPtr, ClientData *clientData) { + if (GetObjectFromObj(interp, objPtr, (XOTclObject **)clientData) == TCL_OK) { + return objectOfType(interp, (XOTclObject *)*clientData, objPtr, pPtr); + } + return XOTclObjErrType(interp, objPtr, "object"); +} + +static int convertToClass(Tcl_Interp *interp, Tcl_Obj *objPtr, XOTclParam CONST *pPtr, ClientData *clientData) { + if (GetClassFromObj(interp, objPtr, (XOTclClass **)clientData, 0) == TCL_OK) { + return objectOfType(interp, (XOTclObject *)*clientData, objPtr, pPtr); + } + return XOTclObjErrType(interp, objPtr, "class"); +} + static int convertToRelation(Tcl_Interp *interp, Tcl_Obj *objPtr, XOTclParam CONST *pPtr, ClientData *clientData) { /* XOTclRelationCmd is the real setter, which checks the values according to the relation type (Class, List of Class, list of @@ -6395,12 +6394,9 @@ paramPtr->flags |= XOTCL_ARG_RELATION; /*paramPtr->type = "tclobj";*/ } else if (length >= 6 && strncmp(option, "type=", 5) == 0) { - if (paramPtr->converter != NULL && - paramPtr->converter != convertToObject && + if (paramPtr->converter != convertToObject && paramPtr->converter != convertToClass) return XOTclVarErrMsg(interp, "option type= only allowed for object or class", (char *) NULL); - paramPtr->converter = NULL; - result = ParamOptionSetConverter(interp, paramPtr, option, convertToObjectOfType); paramPtr->converterArg = Tcl_NewStringObj(option+5, length-5); INCR_REF_COUNT(paramPtr->converterArg); } else { Index: tests/parameters.xotcl =================================================================== diff -u -r5a0750dc422574bc5ae91d9b58c64b8f5713d405 -r7afa0b7f3e63e10eb45a65a7360285ba9590f514 --- tests/parameters.xotcl (.../parameters.xotcl) (revision 5a0750dc422574bc5ae91d9b58c64b8f5713d405) +++ tests/parameters.xotcl (.../parameters.xotcl) (revision 7afa0b7f3e63e10eb45a65a7360285ba9590f514) @@ -53,21 +53,27 @@ # specified value is the first argument unless "noarg" is used # (example: -noinit). # -# parameter type multivalued required noarg arg= valueCheck methodParm objectParm -# substdefault NO NO NO NO NO YES YES (autmatically set by -parameter on []} -# initcmd NO YES NO NO NO NO/POSSIBLE YES -# method NO YES YES YES NO NO/POSSIBLE YES +# parameter type multivalued required noarg type= arg= valueCheck methodParm objectParm +# substdefault NO NO NO NO NO NO YES YES (autmatically set by -parameter on []} +# initcmd NO YES NO NO NO NO NO/POSSIBLE YES +# method NO YES YES NO YES NO NO/POSSIBLE YES # -# relation NO YES NO YES NO NO YES -# stringtype YES YES NO NO YES YES YES +# relation NO YES NO NO YES NO NO YES +# stringtype YES YES NO NO NO YES YES YES # -# switch NO NO NO NO NO YES YES -# integer YES YES NO NO YES YES YES -# boolean YES YES NO NO YES YES YES -# object YES YES NO NO YES YES YES -# class YES YES NO NO YES YES YES -# objectOfType YES YES NO NO YES YES YES -# userdefined YES YES NO YES YES YES YES +# switch NO NO NO NO NO NO YES YES +# integer YES YES NO NO NO YES YES YES +# boolean YES YES NO NO NO YES YES YES +# object YES YES NO YES NO YES YES YES +# class YES YES NO YES NO YES YES YES +# +# userdefined YES YES NO NO YES YES YES YES +# +# tclObj + converterArg (alnum..xdigit) Attribute ... -type alnum +# object + converterArg (some class, e.g. ::C) Attribute ... -type ::C Attribute -type object -arg ::C +# class + converterArg (some metaclass, e.g. ::M) Attribute -type class -arg ::M +# +# todo: get rid of convertToObjectOfType() merge to convertToClass/Object #::xotcl::Slot { # {name "[namespace tail [::xotcl::self]]"}