Index: TODO =================================================================== diff -u -r0de05aaed50fced1cd80a9408560a38fb2454bcf -rf0d2956f16dfa49ff339729fe680bc0025111248 --- TODO (.../TODO) (revision 0de05aaed50fced1cd80a9408560a38fb2454bcf) +++ TODO (.../TODO) (revision f0d2956f16dfa49ff339729fe680bc0025111248) @@ -5934,6 +5934,33 @@ ======================================================================== TODO: +- IsObjectOfType(): the error messages provided could be improved: + + rather than saying + + "expected object of type ::C but got "::nsf::__#6" for parameter "s2"" + + one could report + + "expected object of type ::C but got "::nsf::__#6" of type ::D (::A ::B ::C ::nx::Object) for parameter "s2"" + Otherwise, the instance name ::nsf::__#6 can be easily confused for + the (sought) type name. + +- Refactoring option: Why not use ParameterCheck for setters? That is, + rather than ParamParse on setter definition time, call + ParameterCheck() when calling the setter (and have the param + structure build lazily, on first use). Tcl_Obj intrep will do good, + in most cases. And we gain a more unified interface (stripping away + one unique path to Param* machinery)? + +- nsf::proc should also have a -returns option, right? + +% ::nsf::proc x +required argument 'arguments' is missing, should be: + ::nsf::proc ?-ad? ?-checkalways? ?-debug? ?-deprecated? /procName/ /arguments/ /body/ +% nsf::proc x {-a:integer} -returns alnum {;} +invalid argument 'alnum', maybe too many arguments; should be "nsf::proc ?-ad? ?-checkalways? ?-debug? ?-deprecated? /procName/ /arguments/ /body/" + - nsf::parseargs would need some more love: * what is the intended behavior, in these edge cases? Index: generic/nsf.c =================================================================== diff -u -r7f58a3a3dd12990de3dfc8096a85d2341cf02075 -rf0d2956f16dfa49ff339729fe680bc0025111248 --- generic/nsf.c (.../nsf.c) (revision 7f58a3a3dd12990de3dfc8096a85d2341cf02075) +++ generic/nsf.c (.../nsf.c) (revision f0d2956f16dfa49ff339729fe680bc0025111248) @@ -351,7 +351,8 @@ unsigned int doCheckArguments, int isNamed, int doConfigureParameter, - Nsf_Param **paramPtrPtr) + Nsf_Param **paramPtrPtr, + const char *qualifier) nonnull(1) nonnull(2) nonnull(3); static void ParamDefsRefCountIncr(NsfParamDefs *paramDefs) nonnull(1); @@ -13868,10 +13869,13 @@ const NsfParamDefs *paramDefs = ParamDefsGet(cscPtr->cmdPtr, NULL); if ((paramDefs != NULL) && (paramDefs->returns != NULL)) { + NsfObject *ctx = (cscPtr->cl != NULL) ? (NsfObject *)cscPtr->cl : object; + Tcl_Namespace *nsPtr = Tcl_Command_nsPtr(ctx->id); Tcl_Obj *valueObj = Tcl_GetObjResult(interp); result = ParameterCheck(interp, paramDefs->returns, valueObj, "return-value:", - rst->doCheckResults, 0, 0, NULL); + rst->doCheckResults, 0, 0, NULL, + nsPtr != NULL ? nsPtr->fullName : NULL); } } else { /*fprintf(stderr, "We have no cmdPtr in cscPtr %p %s", cscPtr, ObjectName(object)); @@ -15740,16 +15744,18 @@ * *---------------------------------------------------------------------- */ - -static int ParamOptionParse(Tcl_Interp *interp, const char *argString, - size_t start, size_t optionLength, - unsigned int disallowedOptions, Nsf_Param *paramPtr, int unescape) - nonnull(1) nonnull(2) nonnull(6); - + + static int ParamOptionParse(Tcl_Interp *interp, const char *argString, + size_t start, size_t optionLength, + unsigned int disallowedOptions, Nsf_Param *paramPtr, int unescape, + const char *qualifier) + nonnull(1) nonnull(2) nonnull(6); + static int ParamOptionParse(Tcl_Interp *interp, const char *argString, size_t start, size_t optionLength, - unsigned int disallowedOptions, Nsf_Param *paramPtr, int unescape) { + unsigned int disallowedOptions, Nsf_Param *paramPtr, int unescape, + const char *qualifier) { const char *dotdot, *option = argString + start; char firstChar = *option; int result = TCL_OK; @@ -15773,7 +15779,7 @@ ) { paramPtr->flags |= NSF_ARG_SUBST_DEFAULT; paramPtr->flags |= NSF_ARG_SUBST_DEFAULT_ALL; - + } else if (firstChar == 's' && strncmp(option, "substdefaultoptions=", 20) == 0) { if ((paramPtr->flags & NSF_ARG_SUBST_DEFAULT) == 0u) { @@ -15956,7 +15962,7 @@ } else if (firstChar == 'p' && strncmp(option, "parameter", 9) == 0) { result = ParamOptionSetConverter(interp, paramPtr, "parameter", Nsf_ConvertToParameter); - + } else if (firstChar == 't' && optionLength >= 6 && strncmp(option, "type=", 5) == 0) { if (paramPtr->converter != Nsf_ConvertToObject && paramPtr->converter != Nsf_ConvertToClass ) { @@ -15965,12 +15971,29 @@ if (paramPtr->converterArg != NULL) { DECR_REF_COUNT(paramPtr->converterArg); } - paramPtr->converterArg = Tcl_NewStringObj(option + 5, (int)optionLength - 5); + const char* typeValue = option + 5; + int typeValueLength = (int)optionLength - 5; + + if (qualifier != NULL && !isAbsolutePath(typeValue) && + isAbsolutePath(qualifier)) { + Tcl_DString ds, *dsPtr = &ds; + Tcl_DStringInit(dsPtr); + Tcl_DStringAppend(dsPtr, qualifier, -1); + if (Tcl_DStringLength(dsPtr) > 2) { + Tcl_DStringAppend(dsPtr, "::", 2); + } + Tcl_DStringAppend(dsPtr, typeValue, typeValueLength); + paramPtr->converterArg = Tcl_NewStringObj(Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr)); + Tcl_DStringFree(dsPtr); + } else { + paramPtr->converterArg = Tcl_NewStringObj(typeValue, typeValueLength); + } + if (unlikely(unescape)) { Unescape(paramPtr->converterArg); } INCR_REF_COUNT(paramPtr->converterArg); - + } else if (firstChar == 's' && optionLength >= 6 && strncmp(option, "slot=", 5) == 0) { if (paramPtr->slotObj != NULL) {DECR_REF_COUNT(paramPtr->slotObj);} paramPtr->slotObj = Tcl_NewStringObj(option + 5, (int)optionLength - 5); @@ -16093,13 +16116,16 @@ *---------------------------------------------------------------------- */ - static int ParamDefinitionParse(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Obj *arg, unsigned int disallowedFlags, - Nsf_Param *paramPtr, int *possibleUnknowns, int *plainParams, int *nrNonposArgs) - nonnull(1) nonnull(3) nonnull(5) nonnull(6) nonnull(7) nonnull(8); +static int ParamDefinitionParse(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Obj *arg, + unsigned int disallowedFlags, + Nsf_Param *paramPtr, int *possibleUnknowns, int *plainParams, + int *nrNonposArgs, const char *qualifier) + nonnull(1) nonnull(3) nonnull(5) nonnull(6) nonnull(7) nonnull(8); static int ParamDefinitionParse(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Obj *arg, unsigned int disallowedFlags, - Nsf_Param *paramPtr, int *possibleUnknowns, int *plainParams, int *nrNonposArgs) { + Nsf_Param *paramPtr, int *possibleUnknowns, int *plainParams, int *nrNonposArgs, + const char *qualifier) { const char *argString, *argName; int result, npac, isNonposArgument, parensCount; size_t length, j; @@ -16200,7 +16226,8 @@ } /* skip space from end */ for (end = l; end > 0 && isspace((int)argString[end-1]); end--); - result = ParamOptionParse(interp, argString, start, end-start, disallowedFlags, paramPtr, unescape); + result = ParamOptionParse(interp, argString, start, end-start, disallowedFlags, paramPtr, unescape, + qualifier); unescape = 0; if (unlikely(result != TCL_OK)) { goto param_error; @@ -16214,7 +16241,8 @@ for (end = l; end > 0 && isspace((int)argString[end-1]); end--); /* process last option */ if (end-start > 0) { - result = ParamOptionParse(interp, argString, start, end-start, disallowedFlags, paramPtr, unescape); + result = ParamOptionParse(interp, argString, start, end-start, disallowedFlags, paramPtr, unescape, + qualifier); if (unlikely(result != TCL_OK)) { goto param_error; } @@ -16414,16 +16442,18 @@ * *---------------------------------------------------------------------- */ -static int ParamDefsParse(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Obj *paramSpecObjs, - unsigned int allowedOptions, int forceParamdefs, NsfParsedParam *parsedParamPtr) - nonnull(1) nonnull(3) nonnull(6); + + static int ParamDefsParse(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Obj *paramSpecObjs, + unsigned int allowedOptions, int forceParamdefs, NsfParsedParam *parsedParamPtr, + const char *qualifier) + nonnull(1) nonnull(3) nonnull(6); + + static int ParamDefsParse(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Obj *paramSpecObjs, + unsigned int allowedOptions, int forceParamdefs, NsfParsedParam *parsedParamPtr, + const char *qualifier) { + Tcl_Obj **argsv; + int result, argsc; -static int -ParamDefsParse(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Obj *paramSpecObjs, - unsigned int allowedOptions, int forceParamdefs, NsfParsedParam *parsedParamPtr) { - Tcl_Obj **argsv; - int result, argsc; - nonnull_assert(interp != NULL); nonnull_assert(paramSpecObjs != NULL); nonnull_assert(parsedParamPtr != NULL); @@ -16445,12 +16475,33 @@ for (i = 0; i < argsc; i++, paramPtr++) { result = ParamDefinitionParse(interp, procNameObj, argsv[i], allowedOptions, - paramPtr, &possibleUnknowns, &plainParams, &nrNonposArgs); + paramPtr, &possibleUnknowns, &plainParams, &nrNonposArgs, + qualifier); - if (result == TCL_OK && paramPtr->converter == ConvertToNothing && i < argsc-1) { - result = NsfPrintError(interp, - "parameter option \"args\" invalid for parameter \"%s\"; only allowed for last parameter", - paramPtr->name); + if (result == TCL_OK) { + if (paramPtr->converter == ConvertToNothing && i < argsc-1) { + result = NsfPrintError(interp, + "parameter option \"args\" invalid for parameter \"%s\"; only allowed for last parameter", + paramPtr->name); + } + + /* fprintf(stderr, "qual %s\n", qualifier); + if (qualifier != NULL && + (paramPtr->converter == Nsf_ConvertToObject || + paramPtr->converter == Nsf_ConvertToClass) && + paramPtr->converterArg != NULL) { + fprintf(stderr, "qual %s\n", qualifier); + const char *carg = ObjStr(paramPtr->converterArg); + if (*carg != ':') { + Tcl_Obj *qualifiedConverterArg = Tcl_NewStringObj(qualifier, -1); + Tcl_AppendToObj(qualifiedConverterArg, "::", 2); + Tcl_AppendObjToObj(qualifiedConverterArg, paramPtr->converterArg); + DECR_REF_COUNT(paramPtr->converterArg); + paramPtr->converterArg = qualifiedConverterArg; + INCR_REF_COUNT(qualifiedConverterArg); + fprintf(stderr, ">>> converterArg %s qualifier %s\n", ObjStr(paramPtr->converterArg), qualifier); + } + }*/ } if (unlikely(result != TCL_OK)) { ParamsFree(paramsPtr); @@ -16878,9 +16929,12 @@ result = CanRedefineCmd(interp, nsPtr, defObject, methodName, 0); if (likely(result == TCL_OK)) { /* Yes, we can! ...so obtain an method parameter definitions */ + Tcl_Namespace *nsPtr1 = Tcl_Command_nsPtr(defObject->id); + result = ParamDefsParse(interp, nameObj, args, NSF_DISALLOWED_ARG_METHOD_PARAMETER, 0, - &parsedParam); + &parsedParam, + nsPtr1 != NULL ? nsPtr1->fullName : NULL); } if (unlikely(result != TCL_OK)) { @@ -20992,7 +21046,7 @@ cd = (SetterCmdClientData *)clientData; object = cd->object; - + if (objc > 2) { return NsfObjWrongArgs(interp, "wrong # args", object->cmdName, NsfMethodNamePath(interp, CallStackGetTclFrame(interp, NULL, 1), @@ -25471,7 +25525,7 @@ */ result = ParamDefsParse(interp, nameObj, arguments, NSF_DISALLOWED_ARG_METHOD_PARAMETER, 0, - &parsedParam); + &parsedParam, NULL); if (unlikely(result != TCL_OK)) { return result; } @@ -26073,7 +26127,8 @@ (name != NULL) ? name : "value:", 1, (name != NULL), doConfigureParameter, - ¶mPtr); + ¶mPtr, + Tcl_GetCurrentNamespace(interp)->fullName); if (unlikely(paramPtr == NULL)) { /* @@ -26113,7 +26168,7 @@ result = ParamDefsParse(interp, NsfGlobalObjs[NSF_PARSE_ARGS], argspecObj, NSF_DISALLOWED_ARG_METHOD_PARAMETER, 1 /* force use of param structure, even for Tcl-only params */, - &parsedParam); + &parsedParam, Tcl_GetCurrentNamespace(interp)->fullName); if (unlikely(result != TCL_OK)) { return result; @@ -26918,16 +26973,21 @@ } } + cl = (withPer_object || ! NsfObjectIsClass(object)) ? NULL : (NsfClass *)object; + if (j < length) { /* looks as if we have a parameter specification */ int rc, possibleUnknowns = 0, plainParams = 0, nrNonposArgs = 0; + NsfObject *ctx = (cl != NULL) ? (NsfObject *)cl : object; + Tcl_Namespace *nsPtr = Tcl_Command_nsPtr(ctx->id); setterClientData->paramsPtr = ParamsNew(1u); rc = ParamDefinitionParse(interp, NsfGlobalObjs[NSF_SETTER], parameter, - NSF_DISALLOWED_ARG_SETTER|NSF_ARG_HAS_DEFAULT, - setterClientData->paramsPtr, &possibleUnknowns, - &plainParams, &nrNonposArgs); - + NSF_DISALLOWED_ARG_SETTER|NSF_ARG_HAS_DEFAULT, + setterClientData->paramsPtr, &possibleUnknowns, + &plainParams, &nrNonposArgs, + nsPtr != NULL ? nsPtr->fullName : NULL); + if (unlikely(rc != TCL_OK)) { SetterCmdDeleteProc(setterClientData); return rc; @@ -26937,7 +26997,6 @@ setterClientData->paramsPtr = NULL; } - cl = (withPer_object || ! NsfObjectIsClass(object)) ? NULL : (NsfClass *)object; if (cl != NULL) { result = NsfAddClassMethod(interp, (Nsf_Class *)cl, methodName, (Tcl_ObjCmdProc *)NsfSetterMethod, @@ -27540,8 +27599,8 @@ paramsObj = Tcl_NewListObj(1, ¶meterspec); INCR_REF_COUNT(paramsObj); result = ParamDefsParse(interp, NULL, paramsObj, - NSF_DISALLOWED_ARG_OBJECT_PARAMETER, 1, - &parsedParam); + NSF_DISALLOWED_ARG_OBJECT_PARAMETER, 1, + &parsedParam, NULL); DECR_REF_COUNT(paramsObj); if (unlikely(result != TCL_OK)) { @@ -27852,7 +27911,7 @@ */ result = ParamDefsParse(interp, nameObj, arguments, NSF_DISALLOWED_ARG_METHOD_PARAMETER, (with_Debug != 0), - &parsedParam); + &parsedParam, Tcl_GetCurrentNamespace(interp)->fullName); if (unlikely(result != TCL_OK)) { return result; } @@ -28659,7 +28718,8 @@ static void ParamFreeInternalRep(register Tcl_Obj *objPtr) nonnull(1); static int ParamSetFromAny(Tcl_Interp *interp, register Tcl_Obj *objPtr) nonnull(1) nonnull(2); static int ParamSetFromAny2(Tcl_Interp *interp, const char *varNamePrefix, - int configureParameter, register Tcl_Obj *objPtr) + int configureParameter, register Tcl_Obj *objPtr, + const char *qualifier) nonnull(1) nonnull(2) nonnull(4); static void @@ -28731,7 +28791,8 @@ Tcl_Interp *interp, /* Used for error reporting if not NULL. */ const char *varNamePrefix, /* shows up as varName in error message */ int allowParameter, /* allow object parameters */ - register Tcl_Obj *objPtr) /* The object to convert. */ + register Tcl_Obj *objPtr, + const char *qualifier) /* The object to convert. */ { Tcl_Obj *fullParamObj = Tcl_NewStringObj(varNamePrefix, -1); int result, possibleUnknowns = 0, plainParams = 0, nrNonposArgs = 0; @@ -28750,7 +28811,7 @@ result = ParamDefinitionParse(interp, NsfGlobalObjs[NSF_VALUECHECK], fullParamObj, (allowParameter == 1) ? NSF_DISALLOWED_ARG_OBJECT_PARAMETER : NSF_DISALLOWED_ARG_VALUECHECK, paramWrapperPtr->paramPtr, &possibleUnknowns, - &plainParams, &nrNonposArgs); + &plainParams, &nrNonposArgs, qualifier); /* * We treat currently unknown user level converters as error. */ @@ -28791,7 +28852,7 @@ nonnull_assert(interp != NULL); nonnull_assert(objPtr != NULL); - return ParamSetFromAny2(interp, "value:", 0, objPtr); + return ParamSetFromAny2(interp, "value:", 0, objPtr, NULL); } /* @@ -28846,7 +28907,7 @@ */ result = ParamDefsParse(interp, procNameObj, rawConfArgs, NSF_DISALLOWED_ARG_OBJECT_PARAMETER, 1, - parsedParamPtr); + parsedParamPtr, NULL); if (likely(result == TCL_OK)) { NsfParsedParam *ppDefPtr = NEW(NsfParsedParam); @@ -28984,7 +29045,7 @@ ParameterCheck(Tcl_Interp *interp, Tcl_Obj *paramObjPtr, Tcl_Obj *valueObj, const char *argNamePrefix, unsigned int doCheckArguments, int isNamed, int doConfigureParameter, - Nsf_Param **paramPtrPtr) { + Nsf_Param **paramPtrPtr, const char *qualifier) { Nsf_Param *paramPtr; NsfParamWrapper *paramWrapperPtr; Tcl_Obj *outObjPtr = NULL; @@ -28996,8 +29057,8 @@ nonnull_assert(paramObjPtr != NULL); nonnull_assert(valueObj != NULL); - /*fprintf(stderr, "ParameterCheck %s value %p %s\n", - ObjStr(paramObjPtr), valueObj, ObjStr(valueObj));*/ + /* fprintf(stderr, "ParameterCheck %s value %p %s\n", + ObjStr(paramObjPtr), valueObj, ObjStr(valueObj)); */ if (paramObjPtr->typePtr == ¶mObjType) { paramWrapperPtr = (NsfParamWrapper *) paramObjPtr->internalRep.twoPtrValue.ptr1; @@ -29007,7 +29068,7 @@ * of checking the type manually, but we want to pass the argNamePrefix * explicitly. */ - result = ParamSetFromAny2(interp, argNamePrefix, doConfigureParameter, paramObjPtr); + result = ParamSetFromAny2(interp, argNamePrefix, doConfigureParameter, paramObjPtr, qualifier); if (likely(result == TCL_OK)) { paramWrapperPtr = (NsfParamWrapper *) paramObjPtr->internalRep.twoPtrValue.ptr1; } else { Index: tests/parameters.test =================================================================== diff -u -r25212e40eb097eebcf48d54931bde2bc90e94e69 -rf0d2956f16dfa49ff339729fe680bc0025111248 --- tests/parameters.test (.../parameters.test) (revision 25212e40eb097eebcf48d54931bde2bc90e94e69) +++ tests/parameters.test (.../parameters.test) (revision f0d2956f16dfa49ff339729fe680bc0025111248) @@ -1673,7 +1673,7 @@ ? {o f11} 1 ? {o f12} 1 - ? {o f13} 1 + ? {o f13} 0 } # @@ -1684,7 +1684,7 @@ :create c1 :public method f21 {} {::nsf::dispatch c1 ::nsf::methods::object::info::hastype nx::Object} :public method f22 {} {::nsf::dispatch c1 ::nsf::methods::object::info::hastype C} - :public method f31 {} {::nsf::is object,type=Object c1} + :public method f31 {} {::nsf::is object,type=::nx::Object c1} :public method f32 {} {::nsf::is object,type=C c1} } @@ -1696,10 +1696,10 @@ :public object method f05 {} {::nsf::dispatch c1 ::nsf::methods::object::info::hastype C} :public object method f11 {} {::nsf::is object,type=::nx::Object c1} - :public object method f12 {} {::nsf::is object,type=nx::Object c1} - :public object method f13 {} {::nsf::is object,type=Object c1} - :public object method f14 {} {::nsf::is object,type=foo::C c1} - :public object method f15 {} {::nsf::is object,type=C c1} + :public object method f12 {} {::nsf::is object,type=nx::Object c1}; # resolves to ::foo::nx::Object + :public object method f13 {} {::nsf::is object,type=Object c1}; # resolves to ::foo::Object + :public object method f14 {} {::nsf::is object,type=C c1}; # resolves to ::foo::C + :public object method f15 {} {::nsf::is object,type=[namespace which C] c1}; # ::foo::C } ? {o f01} 1 @@ -1709,8 +1709,8 @@ ? {o f05} 1 ? {o f11} 1 - ? {o f12} 1 - ? {o f13} 1 + ? {o f12} 0 + ? {o f13} 0 ? {o f14} 1 ? {o f15} 1 @@ -3449,7 +3449,99 @@ } +nx::test case type-reform { + namespace eval :: { + + ::nsf::proc foo {p2:object,type=C} { + return [$p2 info class] + } + nx::Class create C + nx::Object create o { + :public object method foo {p1:object,type=C} { + return [$p1 info class] + } + :public object method faa {p1:object,type=C} -returns object,type=C { + return $p1 + } + } + + ::nsf::method::setter o s1:object,type=C + ::nsf::method::setter C s2:object,type=C + + ::proc bar args { + ::nsf::parseargs p1:object,type=C $args + return [$p1 info class] + } + ::proc baz {a} { + ::nsf::is object,type=C $a + return [$a info class] + } + namespace eval ns1 { + namespace eval ns2 { + nx::Class create C + nx::Class create A { + :public method foo {p1:object,type=C} { + return [$p1 info class] + } + :public method faa {p1:object,type=C} -returns object,type=C { + return $p1 + } + } + ::nsf::proc foo {p2:object,type=C} { + return [$p2 info class] + } + ::proc bar args { + ::nsf::parseargs p2:object,type=C $args + return [$p2 info class] + } + + ::proc baz {a} { + ::nsf::is object,type=C $a + return [$a info class] + } + + ::nsf::method::setter A s3:object,type=C + ::nsf::method::setter A -per-object s4:object,type=C + + } + } + } + + set ::C ::ns1::ns2::C + + ## In the intrep (param structure), unqualified names will be qualified; + ? {::o foo [::C new]} ::C + ? {[::o faa [::C new]] info class} ::C + ? {[::o s1 [::C new]] info class} ::C + ? {[[::C new] s2 [::C new]] info class} ::C + $::C create ::c1 + ? {[[::C new] s2 ::c1] info class} {expected object of type ::C but got "::c1" for parameter "s2"} + ## the stringrep remains untouched (to allow for cloning, serializing + ## method records more easily) + ? {nsf::parameter::info type [::o info object method parameters foo p1]} C + + ? {[::ns1::ns2::A new] foo [$::C new]} $::C + ? {nsf::parameter::info type [::ns1::ns2::A info method parameters foo p1]} C + ? {[[::ns1::ns2::A new] faa [$::C new]] info class} $::C + ? {[[::ns1::ns2::A new] s3 [$::C new]] info class} $::C + ? {[::ns1::ns2::A s4 [$::C new]] info class} $::C + + ? {::ns1::ns2::foo [$::C new]} $::C + + ? {::foo [::C new]} ::C + ? {::bar [::C new]} ::C + ? {::baz [::C new]} ::C + ? {::ns1::ns2::bar [$::C new]} $::C + ? {::ns1::ns2::baz [$::C new]} $::C + + ## error msgs now contain the qualified type names + ::C create ::c + ? {[::ns1::ns2::A new] foo ::c} \ + "expected object of type ::ns1::ns2::C but got \"::c\" for parameter \"p1\"" +} + + # # Local variables: # mode: tcl