Index: generic/nsf.c =================================================================== diff -u -N -r86becbe05373b722fe093ffe5a4a1c19d1ebd76d -r4e48f1044506977558e55e4e40138cf876b9609f --- generic/nsf.c (.../nsf.c) (revision 86becbe05373b722fe093ffe5a4a1c19d1ebd76d) +++ generic/nsf.c (.../nsf.c) (revision 4e48f1044506977558e55e4e40138cf876b9609f) @@ -13294,6 +13294,47 @@ subMethodCmd = NULL; } +#if 1 + if (subMethodCmd != NULL) { + unsigned long cmdFlags = (unsigned long)Tcl_Command_flags(subMethodCmd); + if (unlikely((cmdFlags & NSF_CMD_CALL_PROTECTED_METHOD) != 0u)) { + NsfObject *lastSelf; + Tcl_CallFrame *framePtr; + int withinEnsemble = ((cscPtr->frameType & NSF_CSC_TYPE_ENSEMBLE) != 0u); + + if (withinEnsemble) { + Tcl_CallFrame *framePtr1; + /* Alternatively: (void)NsfCallStackFindLastInvocation(interp, 0, &framePtr1); */ + (void)CallStackGetTopFrame(interp, &framePtr); + (void)CallStackFindEnsembleCsc(framePtr, &framePtr1); + /* NsfShowStack(interp); + fprintf(stderr, "framePtr %p\n", framePtr1);*/ + if (framePtr1 != NULL) { + lastSelf = GetSelfObj2(interp, framePtr1); + } else { + lastSelf = NULL; + } + } else { + lastSelf = GetSelfObj(interp); + } + + + /* fprintf(stderr, "'%s (%s) == %s == %s? for %s\n", lastSelf != NULL ? ObjectName(lastSelf): "n/a", + ObjectName(GetSelfObj(interp)), ObjectName(actualSelf), ObjectName(invokedObject), subMethodName); */ + + if (actualSelf != lastSelf) { + const char *path = withinEnsemble ? ObjStr(NsfMethodNamePath(interp, framePtr, methodName)) : methodName; + + NsfLog(interp, NSF_LOG_WARN, "'%s %s %s' fails since method %s.%s %s is protected", + ObjectName(actualSelf), path, subMethodName, (actualClass != NULL) ? + ClassName(actualClass) : ObjectName(actualSelf), path, subMethodName); + subMethodCmd = NULL; + } + } + } +#endif + + /* * Make sure, that the current call is marked as an ensemble call, both * for dispatching to the default-method and for dispatching the method Index: generic/nsfStack.c =================================================================== diff -u -N -r5b6d88f867023b304dd16a7d23895d5c80ae606e -r4e48f1044506977558e55e4e40138cf876b9609f --- generic/nsfStack.c (.../nsfStack.c) (revision 5b6d88f867023b304dd16a7d23895d5c80ae606e) +++ generic/nsfStack.c (.../nsfStack.c) (revision 4e48f1044506977558e55e4e40138cf876b9609f) @@ -316,9 +316,11 @@ /* *---------------------------------------------------------------------- - * GetSelfObj -- + * GetSelfObj, GetSelfObj2 -- * - * Return the currently active object from a method or object frame. + * Return the corresponding object from a method or from an object + * frame. GetSelfObj defaults to the top-most callframe, GetSelfObj2 allows + * one to set another frame. * * Results: * NsfObject * or NULL. @@ -338,6 +340,10 @@ # endif #endif +#define GetSelfObj(interp) \ + GetSelfObj2((interp), (Tcl_CallFrame *)Tcl_Interp_varFramePtr((interp))) + +#if 0 NSF_INLINE static NsfObject* GetSelfObj(const Tcl_Interp *interp) nonnull(1); NSF_INLINE static NsfObject* @@ -377,7 +383,48 @@ } return NULL; } +#endif +NSF_INLINE static NsfObject* GetSelfObj2(const Tcl_Interp *interp, Tcl_CallFrame *framePtr) nonnull(1) nonnull(2); + +NSF_INLINE static NsfObject* +GetSelfObj2(const Tcl_Interp *interp, Tcl_CallFrame *framePtr) { + register Tcl_CallFrame *varFramePtr; + + nonnull_assert(interp != NULL); + + /*fprintf(stderr, "GetSelfObj interp has frame %p and var-frame %p\n", + Tcl_Interp_framePtr(interp), Tcl_Interp_varFramePtr(interp));*/ + + for (varFramePtr = framePtr; + varFramePtr != NULL; + varFramePtr = +#if defined(SKIP_LEVELS) + Tcl_CallFrame_callerPtr(varFramePtr) +#else + NULL +#endif + ) { + register unsigned int flags; + + flags = (unsigned int)Tcl_CallFrame_isProcCallFrame(varFramePtr); + if (likely((flags & (FRAME_IS_NSF_METHOD|FRAME_IS_NSF_CMETHOD)) != 0u)) { + return ((NsfCallStackContent *)Tcl_CallFrame_clientData(varFramePtr))->self; + + } else if ((flags & FRAME_IS_NSF_OBJECT) != 0u) { + return (NsfObject *)Tcl_CallFrame_clientData(varFramePtr); + + } +#if defined(SKIP_LAMBDA) + if ((flags & FRAME_IS_LAMBDA) != 0u) { + continue; + } + break; +#endif + } + return NULL; +} + /* *---------------------------------------------------------------------- * CallStackGetTclFrame -- Index: tests/protected.test =================================================================== diff -u -N -r371cc41c32db500cb1d5bcab139ef65299ef4d6c -r4e48f1044506977558e55e4e40138cf876b9609f --- tests/protected.test (.../protected.test) (revision 371cc41c32db500cb1d5bcab139ef65299ef4d6c) +++ tests/protected.test (.../protected.test) (revision 4e48f1044506977558e55e4e40138cf876b9609f) @@ -868,6 +868,135 @@ ? {C private object property {d:integer 1}} {'property' is not a method defining method} } +nx::test case protected-ensembles { + + set ::o [nx::Object new { + set ::foo2faa [:protected object method "foo2 faa" {} {return protected}] + ? [list set _ [:foo2 faa]] "protected" + + set ::foo2baz [:public object method "foo2 baz" {} {:foo2 faa}] + ? [list set _ [:foo2 baz]] "protected" + + :object method m1 {} {:foo2 faa} + ? [list set _ [:m1]] "protected" + + :object method m2 {} {apply {{} {:foo2 faa}}} + ? [list set _ [:m2]] "protected" + + set ::foo2biz [:public object method "foo2 biz" {} {apply {{} {:foo2 faa}}}] + ? [list set _ [:foo2 biz]] "protected" + + }] + + ? {$::o foo2 faa fee} "unable to dispatch sub-method \"faa\" of $::o foo2; valid are: foo2 baz, foo2 biz" + + set C [nx::Class new { + set ::foo2faa [:protected method "foo2 faa" {} {return protected}] + set ::foo2baz [:public method "foo2 baz" {} {:foo2 faa}] + + set c [:new { + ? [list set _ [:foo2 faa]] "protected" + }] + + ? [list set _ [$c foo2 baz]] "protected" + + :public method m1 {} {:foo2 faa} + ? [list set _ [$c m1]] "protected" + + :public method m2 {} {apply {{} {:foo2 faa}}} + ? [list set _ [$c m2]] "protected" + + set ::foo2biz [:public method "foo2 biz" {} {apply {{} {:foo2 faa}}}] + ? [list set _ [$c foo2 biz]] "protected" + + ? [list $c foo2 faa] "unable to dispatch sub-method \"faa\" of $c foo2; valid are: foo2 baz, foo2 biz" + + set mixin [nx::Class new { + :public method m3 {} { + :foo2 faa + } + :public method "foo2 fee" {} { + :foo2 faa + } + :public method "foo2 faa" {} { + next + } + }] + + $c object mixins add $mixin + ? [list set _ [$c m3]] "protected" + ? [list set _ [$c foo2 fee]] "protected" + ? [list set _ [$c foo2 faa]] "protected" + $c object mixins clear + ? [list $c foo2 faa] "unable to dispatch sub-method \"faa\" of $c foo2; valid are: foo2 baz, foo2 biz" + + }] + + # ensemble + set ::o [nx::Object new { + set ::foo2faa [:protected object method "foo2 faa fee" {} {return protected}] + ? [list set _ [:foo2 faa fee]] "protected" + + set ::foo2baz [:public object method "foo2 baz" {} {:foo2 faa fee}] + ? [list set _ [:foo2 baz]] "protected" + + :object method m1 {} {:foo2 faa fee} + ? [list set _ [:m1]] "protected" + + :object method m2 {} {apply {{} {:foo2 faa fee}}} + ? [list set _ [:m2]] "protected" + + set ::foo2biz [:public object method "foo2 biz" {} {apply {{} {:foo2 faa fee}}}] + ? [list set _ [:foo2 biz]] "protected" + + }] + + ? {$::o foo2 faa fee} "unable to dispatch sub-method \"fee\" of $::o foo2 faa; valid are: " + + set ::C [nx::Class new { + set ::foo2faa [:protected method "foo2 faa fim" {} {return protected}] + set ::foo2baz [:public method "foo2 baz" {} {:foo2 faa fim}] + + set c [:new { + ? [list set _ [:foo2 faa fim]] "protected" + }] + + ? [list set _ [$c foo2 baz]] "protected" + + :public method m1 {} {:foo2 faa fim} + ? [list set _ [$c m1]] "protected" + + :public method m2 {} {apply {{} {:foo2 faa fim}}} + ? [list set _ [$c m2]] "protected" + + set ::foo2biz [:public method "foo2 biz" {} {apply {{} {:foo2 faa fim}}}] + ? [list set _ [$c foo2 biz]] "protected" + + ? [list $c foo2 faa fim] "unable to dispatch sub-method \"fim\" of $c foo2 faa; valid are: " + + set mixin [nx::Class new { + :public method m3 {} { + :foo2 faa fim + } + :public method "foo2 fee fuu" {} { + :foo2 faa fim + } + :public method "foo2 faa fim" {} { + next + } + }] + + $c object mixins add $mixin + ? [list set _ [$c m3]] "protected" + ? [list set _ [$c foo2 fee fuu]] "protected" + ? [list set _ [$c foo2 faa fim]] "protected" + $c object mixins clear + ? [list $c foo2 faa fim] "unable to dispatch sub-method \"fim\" of $c foo2 faa; valid are: " + + }] +} + + # # Local variables: # mode: tcl