Index: TODO =================================================================== diff -u -rdbd850e0318af673e5f576a8c6fddaa8fef26715 -r8465a13d65cb106deebded93f7fd4956dcb5f84a --- TODO (.../TODO) (revision dbd850e0318af673e5f576a8c6fddaa8fef26715) +++ TODO (.../TODO) (revision 8465a13d65cb106deebded93f7fd4956dcb5f84a) @@ -5872,8 +5872,7 @@ - Added Rosetta example: https://rosettacode.org/wiki/Inheritance/Single -- return from "nsf::current callinglevel" the value 0 (instead of 1), - when it is called outside of a frame, which has a nsf object associated. +- new subcommand "nsf::current level", returns empty, if we are not on a nsf frame/level. ======================================================================== TODO: Index: generic/nsf.c =================================================================== diff -u -rdbd850e0318af673e5f576a8c6fddaa8fef26715 -r8465a13d65cb106deebded93f7fd4956dcb5f84a --- generic/nsf.c (.../nsf.c) (revision dbd850e0318af673e5f576a8c6fddaa8fef26715) +++ generic/nsf.c (.../nsf.c) (revision 8465a13d65cb106deebded93f7fd4956dcb5f84a) @@ -27463,30 +27463,53 @@ /* cmd current NsfCurrentCmd { - {-argName "option" -required 0 -typeName "currentoption" -type "proc|method|methodpath|object|class|activelevel|args|activemixin|calledproc|calledmethod|calledclass|callingproc|callingmethod|callingclass|callinglevel|callingobject|filterreg|isnextcall|nextmethod" -default object} + {-argName "option" -required 0 -typeName "currentoption" -type "activelevel|activemixin|args|calledclass|calledmethod|calledproc|callingclass|callinglevel|callingmethod|callingobject|callingproc|class|filterreg|isnextcall|level|methodpath|method|nextmethod|object|proc" -default object} } */ static int NsfCurrentCmd(Tcl_Interp *interp, CurrentoptionIdx_t selfoption) { - NsfObject *object = GetSelfObj(interp); + NsfObject *object; NsfCallStackContent *cscPtr; - Tcl_CallFrame *framePtr; - int result = TCL_OK; + Tcl_CallFrame *framePtr; + int result = TCL_OK; nonnull_assert(interp != NULL); + object = GetSelfObj(interp); + + /* + * The first two clauses can succeed even it we are outside an nsf context + * (no object known). The commands are "nsf::current", "nsf::current + * object", "nsf::current level", and "nsf::current activelevel" + */ if (selfoption == CurrentoptionNULL || selfoption == CurrentoptionObjectIdx) { if (likely(object != NULL)) { Tcl_SetObjResult(interp, object->cmdName); - return TCL_OK; } else { - return NsfNoCurrentObjectError(interp, NULL); + result = NsfNoCurrentObjectError(interp, NULL); } + return result; } - if (unlikely(object == NULL && selfoption != CurrentoptionCallinglevelIdx)) { - return NsfNoCurrentObjectError(interp, NULL); + if (unlikely(object == NULL)) { + if (selfoption == CurrentoptionCallinglevelIdx) { + Tcl_SetIntObj(Tcl_GetObjResult(interp), 1); + } else if (selfoption == CurrentoptionLevelIdx) { + /* + * Return empty, if we are not on a nsf level. + */ + Tcl_ResetResult(interp); + } else { + result = NsfNoCurrentObjectError(interp, NULL); + } + return result; } + + /* + * From here on, we have to be on a valid nsf frame/level, object has to be + * know. + */ + assert(object != NULL); switch (selfoption) { case CurrentoptionMethodIdx: /* fall through */ @@ -27586,11 +27609,10 @@ break; case CurrentoptionCallinglevelIdx: - if (object == NULL) { - Tcl_SetIntObj(Tcl_GetObjResult(interp), 0); - } else { - Tcl_SetObjResult(interp, ComputeLevelObj(interp, CALLING_LEVEL)); - } + /* + * Special case of object==NULL handeled above. + */ + Tcl_SetObjResult(interp, ComputeLevelObj(interp, CALLING_LEVEL)); break; case CurrentoptionCallingobjectIdx: @@ -27618,6 +27640,14 @@ break; } + case CurrentoptionLevelIdx: + /* + * We have an "object", therefore we are on a nsf-frame/level. In this + * case, "nsf level" behaves like "info level" (without arguments). + */ + Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_CallFrame_level(Tcl_Interp_varFramePtr(interp)))); + break; + case CurrentoptionNextmethodIdx: result = FindSelfNext(interp); break; Index: generic/nsfAPI.decls =================================================================== diff -u -rdbd850e0318af673e5f576a8c6fddaa8fef26715 -r8465a13d65cb106deebded93f7fd4956dcb5f84a --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision dbd850e0318af673e5f576a8c6fddaa8fef26715) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision 8465a13d65cb106deebded93f7fd4956dcb5f84a) @@ -301,7 +301,7 @@ cmd current NsfCurrentCmd { - {-argName "option" -required 0 -typeName "currentoption" -type "proc|method|methodpath|object|class|activelevel|args|activemixin|calledproc|calledmethod|calledclass|callingproc|callingmethod|callingclass|callinglevel|callingobject|filterreg|isnextcall|nextmethod" -default object} + {-argName "option" -required 0 -typeName "currentoption" -type "activelevel|activemixin|args|calledclass|calledmethod|calledproc|callingclass|callinglevel|callingmethod|callingobject|callingproc|class|filterreg|isnextcall|level|methodpath|method|nextmethod|object|proc" -default object} } {-nxdoc 1} cmd self NsfSelfCmd { } {-nxdoc 1} Index: generic/nsfAPI.h =================================================================== diff -u -r308a9122fcd679ed416ce55670ea93aab4b87478 -r8465a13d65cb106deebded93f7fd4956dcb5f84a --- generic/nsfAPI.h (.../nsfAPI.h) (revision 308a9122fcd679ed416ce55670ea93aab4b87478) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision 8465a13d65cb106deebded93f7fd4956dcb5f84a) @@ -142,12 +142,12 @@ return result; } -typedef enum {CurrentoptionNULL, CurrentoptionProcIdx, CurrentoptionMethodIdx, CurrentoptionMethodpathIdx, CurrentoptionObjectIdx, CurrentoptionClassIdx, CurrentoptionActivelevelIdx, CurrentoptionArgsIdx, CurrentoptionActivemixinIdx, CurrentoptionCalledprocIdx, CurrentoptionCalledmethodIdx, CurrentoptionCalledclassIdx, CurrentoptionCallingprocIdx, CurrentoptionCallingmethodIdx, CurrentoptionCallingclassIdx, CurrentoptionCallinglevelIdx, CurrentoptionCallingobjectIdx, CurrentoptionFilterregIdx, CurrentoptionIsnextcallIdx, CurrentoptionNextmethodIdx} CurrentoptionIdx_t; +typedef enum {CurrentoptionNULL, CurrentoptionActivelevelIdx, CurrentoptionActivemixinIdx, CurrentoptionArgsIdx, CurrentoptionCalledclassIdx, CurrentoptionCalledmethodIdx, CurrentoptionCalledprocIdx, CurrentoptionCallingclassIdx, CurrentoptionCallinglevelIdx, CurrentoptionCallingmethodIdx, CurrentoptionCallingobjectIdx, CurrentoptionCallingprocIdx, CurrentoptionClassIdx, CurrentoptionFilterregIdx, CurrentoptionIsnextcallIdx, CurrentoptionLevelIdx, CurrentoptionMethodpathIdx, CurrentoptionMethodIdx, CurrentoptionNextmethodIdx, CurrentoptionObjectIdx, CurrentoptionProcIdx} CurrentoptionIdx_t; static int ConvertToCurrentoption(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param const *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { int index, result; - static const char *opts[] = {"proc", "method", "methodpath", "object", "class", "activelevel", "args", "activemixin", "calledproc", "calledmethod", "calledclass", "callingproc", "callingmethod", "callingclass", "callinglevel", "callingobject", "filterreg", "isnextcall", "nextmethod", NULL}; + static const char *opts[] = {"activelevel", "activemixin", "args", "calledclass", "calledmethod", "calledproc", "callingclass", "callinglevel", "callingmethod", "callingobject", "callingproc", "class", "filterreg", "isnextcall", "level", "methodpath", "method", "nextmethod", "object", "proc", NULL}; (void)pPtr; result = Tcl_GetIndexFromObj(interp, objPtr, opts, "currentoption", 0, &index); *clientData = (ClientData) INT2PTR(index + 1); @@ -265,7 +265,7 @@ {ConvertToCallprotection, "all|public|protected|private"}, {ConvertToMethodtype, "all|scripted|builtin|alias|forwarder|object|setter|nsfproc"}, {ConvertToFrame, "method|object|default"}, - {ConvertToCurrentoption, "proc|method|methodpath|object|class|activelevel|args|activemixin|calledproc|calledmethod|calledclass|callingproc|callingmethod|callingclass|callinglevel|callingobject|filterreg|isnextcall|nextmethod"}, + {ConvertToCurrentoption, "activelevel|activemixin|args|calledclass|calledmethod|calledproc|callingclass|callinglevel|callingmethod|callingobject|callingproc|class|filterreg|isnextcall|level|methodpath|method|nextmethod|object|proc"}, {ConvertToMethodproperty, "class-only|call-private|call-protected|debug|deprecated|exists|redefine-protected|returns"}, {ConvertToRelationtype, "object-mixin|class-mixin|object-filter|class-filter|class|superclass|rootclass"}, {ConvertToDefinitionsource, "all|application|system"},