Index: TODO =================================================================== diff -u -r88d8fd1e2b40d5797eb86a0be4c5cae7c595fac6 -r0595a14ffaf82764ce8bcc642741cd8ded14dc38 --- TODO (.../TODO) (revision 88d8fd1e2b40d5797eb86a0be4c5cae7c595fac6) +++ TODO (.../TODO) (revision 0595a14ffaf82764ce8bcc642741cd8ded14dc38) @@ -3331,8 +3331,17 @@ * test "my -local" vs my + method handle * test "my -local" vs dispatch + method handle +- nsf.c: + * added preliminary/minimal "private" support + * private can be called via "my -local", direct + dispatches are forbidden, ignored in mixins + and next; + * extended regression test TODO: + - private: + * make it mutual exclusive with protected. + * more tests - nx: * maybe provide a replacement for -attributes, but without the magic variable. Index: generic/nsf.c =================================================================== diff -u -r38de75d755e2a10fb0fb5a2b75bf08a751b4b5c0 -r0595a14ffaf82764ce8bcc642741cd8ded14dc38 --- generic/nsf.c (.../nsf.c) (revision 38de75d755e2a10fb0fb5a2b75bf08a751b4b5c0) +++ generic/nsf.c (.../nsf.c) (revision 0595a14ffaf82764ce8bcc642741cd8ded14dc38) @@ -2509,7 +2509,7 @@ if (result == TCL_OK) { Tcl_Obj *methodObj = Tcl_GetObjResult(interp); Tcl_Command cmd = Tcl_GetCommandFromObj(interp, methodObj); - if (cmd) { Tcl_Command_flags(cmd) |= NSF_CMD_PROTECTED_METHOD; } + if (cmd) { Tcl_Command_flags(cmd) |= NSF_CMD_CALL_PROTECTED_METHOD; } Tcl_ResetResult(interp); } else { NsfLog(interp, NSF_LOG_WARN, "Could not define alias %s for %s", @@ -6458,8 +6458,10 @@ static int CanInvokeMixinMethod(Tcl_Interp *interp, NsfObject *object, Tcl_Command cmd, NsfCmdList *cmdList) { int result = TCL_OK; + int cmdFlags = Tcl_Command_flags(cmd); - if (Tcl_Command_flags(cmd) & NSF_CMD_CLASS_ONLY_METHOD && !NsfObjectIsClass(object)) { + if ((cmdFlags & NSF_CMD_CALL_PRIVATE_METHOD) || + ((cmdFlags & NSF_CMD_CLASS_ONLY_METHOD) && !NsfObjectIsClass(object))) { /* * The command is not applicable for objects (i.e. might crash, * since it expects a class record); therefore skip it @@ -9398,16 +9400,23 @@ * treat it as unknown. */ - if (cmd && (Tcl_Command_flags(cmd) & NSF_CMD_PROTECTED_METHOD) && - (flags & (NSF_CM_NO_UNKNOWN|NSF_CM_NO_PROTECT)) == 0) { - NsfObject *lastSelf = GetSelfObj(interp); + if (cmd) { + int cmdFlags = Tcl_Command_flags(cmd); - if (unlikely(object != lastSelf)) { - NsfLog(interp, NSF_LOG_WARN, "'%s %s' fails since method %s.%s is protected", - ObjectName(object), methodName, - cl ? ClassName(cl) : ObjectName(object), methodName); + if (cmdFlags & NSF_CMD_CALL_PRIVATE_METHOD) { /* reset cmd, since it is still unknown */ cmd = NULL; + } else if ((cmdFlags & NSF_CMD_CALL_PROTECTED_METHOD) && + (flags & (NSF_CM_NO_UNKNOWN|NSF_CM_NO_PROTECT)) == 0) { + NsfObject *lastSelf = GetSelfObj(interp); + + if (unlikely(object != lastSelf)) { + NsfLog(interp, NSF_LOG_WARN, "'%s %s' fails since method %s.%s is protected", + ObjectName(object), methodName, + cl ? ClassName(cl) : ObjectName(object), methodName); + /* reset cmd, since it is still unknown */ + cmd = NULL; + } } } @@ -15881,7 +15890,7 @@ Tcl_ListObjAppendElement(interp, listObj, object->cmdName); if (withProtection) { Tcl_ListObjAppendElement(interp, listObj, - Tcl_Command_flags(cmd) & NSF_CMD_PROTECTED_METHOD + Tcl_Command_flags(cmd) & NSF_CMD_CALL_PROTECTED_METHOD ? Tcl_NewStringObj("protected", 9) : Tcl_NewStringObj("public", 6)); } @@ -16344,7 +16353,7 @@ static int ProtectionMatches(int withCallprotection, Tcl_Command cmd) { - int result, isProtected = Tcl_Command_flags(cmd) & NSF_CMD_PROTECTED_METHOD; + int result, isProtected = Tcl_Command_flags(cmd) & NSF_CMD_CALL_PROTECTED_METHOD; if (withCallprotection == CallprotectionNULL) { withCallprotection = CallprotectionPublicIdx; } @@ -17556,7 +17565,7 @@ {-argName "object" -required 1 -type object} {-argName "-per-object"} {-argName "methodName" -required 1 -type tclobj} - {-argName "methodproperty" -required 1 -type "class-only|protected|redefine-protected|returns|slotcontainer|slotobj"} + {-argName "methodproperty" -required 1 -type "class-only|call-private|call-protected|redefine-protected|returns|slotcontainer|slotobj"} {-argName "value" -type tclobj} } */ @@ -17586,12 +17595,14 @@ switch (methodproperty) { case MethodpropertyClass_onlyIdx: /* fall through */ + case MethodpropertyCall_privateIdx: /* fall through */ case MethodpropertyCall_protectedIdx: /* fall through */ case MethodpropertyRedefine_protectedIdx: /* fall through */ { switch (methodproperty) { case MethodpropertyClass_onlyIdx: flag = NSF_CMD_CLASS_ONLY_METHOD; break; - case MethodpropertyCall_protectedIdx: flag = NSF_CMD_PROTECTED_METHOD; break; + case MethodpropertyCall_privateIdx: flag = NSF_CMD_CALL_PRIVATE_METHOD; break; + case MethodpropertyCall_protectedIdx: flag = NSF_CMD_CALL_PROTECTED_METHOD; break; case MethodpropertyRedefine_protectedIdx: flag = NSF_CMD_REDEFINE_PROTECTED_METHOD; break; default: flag = 0; } Index: generic/nsfAPI.decls =================================================================== diff -u -ra467cf37f204cc977b7af7519a0994c65f9ed10f -r0595a14ffaf82764ce8bcc642741cd8ded14dc38 --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision a467cf37f204cc977b7af7519a0994c65f9ed10f) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision 0595a14ffaf82764ce8bcc642741cd8ded14dc38) @@ -93,7 +93,7 @@ {-argName "object" -required 1 -type object} {-argName "-per-object" -nrargs 0} {-argName "methodName" -required 1 -type tclobj} - {-argName "methodproperty" -required 1 -type "class-only|call-protected|redefine-protected|returns|slotcontainer|slotobj"} + {-argName "methodproperty" -required 1 -type "class-only|call-private|call-protected|redefine-protected|returns|slotcontainer|slotobj"} {-argName "value" -type tclobj} } cmd "method::registered" NsfMethodRegisteredCmd { Index: generic/nsfAPI.h =================================================================== diff -u -ra467cf37f204cc977b7af7519a0994c65f9ed10f -r0595a14ffaf82764ce8bcc642741cd8ded14dc38 --- generic/nsfAPI.h (.../nsfAPI.h) (revision a467cf37f204cc977b7af7519a0994c65f9ed10f) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision 0595a14ffaf82764ce8bcc642741cd8ded14dc38) @@ -129,12 +129,12 @@ return result; } -enum MethodpropertyIdx {MethodpropertyNULL, MethodpropertyClass_onlyIdx, MethodpropertyCall_protectedIdx, MethodpropertyRedefine_protectedIdx, MethodpropertyReturnsIdx, MethodpropertySlotcontainerIdx, MethodpropertySlotobjIdx}; +enum MethodpropertyIdx {MethodpropertyNULL, MethodpropertyClass_onlyIdx, MethodpropertyCall_privateIdx, MethodpropertyCall_protectedIdx, MethodpropertyRedefine_protectedIdx, MethodpropertyReturnsIdx, MethodpropertySlotcontainerIdx, MethodpropertySlotobjIdx}; static int ConvertToMethodproperty(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param CONST *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { int index, result; - static CONST char *opts[] = {"class-only", "call-protected", "redefine-protected", "returns", "slotcontainer", "slotobj", NULL}; + static CONST char *opts[] = {"class-only", "call-private", "call-protected", "redefine-protected", "returns", "slotcontainer", "slotobj", NULL}; (void)pPtr; result = Tcl_GetIndexFromObj(interp, objPtr, opts, "methodproperty", 0, &index); *clientData = (ClientData) INT2PTR(index + 1); @@ -191,7 +191,7 @@ {ConvertToFrame, "method|object|default"}, {ConvertToCurrentoption, "proc|method|methodpath|object|class|activelevel|args|activemixin|calledproc|calledmethod|calledclass|callingproc|callingmethod|callingclass|callinglevel|callingobject|filterreg|isnextcall|next"}, {ConvertToObjectkind, "class|baseclass|metaclass"}, - {ConvertToMethodproperty, "class-only|call-protected|redefine-protected|returns|slotcontainer|slotobj"}, + {ConvertToMethodproperty, "class-only|call-private|call-protected|redefine-protected|returns|slotcontainer|slotobj"}, {ConvertToRelationtype, "object-mixin|class-mixin|object-filter|class-filter|class|superclass|rootclass"}, {ConvertToSource, "all|application|baseclasses"}, {ConvertToConfigureoption, "debug|dtrace|filter|profile|softrecreate|objectsystems|keepinitcmd|checkresults|checkarguments"}, Index: generic/nsfInt.h =================================================================== diff -u -r2e7f0b2256363d70c78778c9ed401f9450622a6a -r0595a14ffaf82764ce8bcc642741cd8ded14dc38 --- generic/nsfInt.h (.../nsfInt.h) (revision 2e7f0b2256363d70c78778c9ed401f9450622a6a) +++ generic/nsfInt.h (.../nsfInt.h) (revision 0595a14ffaf82764ce8bcc642741cd8ded14dc38) @@ -360,11 +360,12 @@ * cmd flags */ -#define NSF_CMD_PROTECTED_METHOD 0x00010000 -#define NSF_CMD_REDEFINE_PROTECTED_METHOD 0x00020000 +#define NSF_CMD_CALL_PROTECTED_METHOD 0x00010000 +#define NSF_CMD_CALL_PRIVATE_METHOD 0x00020000 +#define NSF_CMD_REDEFINE_PROTECTED_METHOD 0x00040000 /* NSF_CMD_NONLEAF_METHOD is used to flag, if a Method implemented via cmd calls "next" */ -#define NSF_CMD_NONLEAF_METHOD 0x00040000 -#define NSF_CMD_CLASS_ONLY_METHOD 0x00080000 +#define NSF_CMD_NONLEAF_METHOD 0x00080000 +#define NSF_CMD_CLASS_ONLY_METHOD 0x00100000 /* * object flags ... */ Index: library/nx/nx.tcl =================================================================== diff -u -r50b5699927f9d34e2ab7a14e29ccf8dc1f569095 -r0595a14ffaf82764ce8bcc642741cd8ded14dc38 --- library/nx/nx.tcl (.../nx.tcl) (revision 50b5699927f9d34e2ab7a14e29ccf8dc1f569095) +++ library/nx/nx.tcl (.../nx.tcl) (revision 0595a14ffaf82764ce8bcc642741cd8ded14dc38) @@ -246,8 +246,8 @@ if {![info exists ::nsf::methodDefiningMethod([lindex $args 0])]} { error "'[lindex $args 0]' is not a method defining method" } - set r [::nsf::object::dispatch [::nsf::current object] {*}$args] - if {$r ne ""} {::nsf::method::property [::nsf::self] $r call-protected false} + set r [{*}:$args] + if {$r ne ""} {::nsf::method::property [self] $r call-protected false} return $r } @@ -257,9 +257,19 @@ error "'[lindex $args 0]' is not a method defining method" } set r [{*}:$args] - if {$r ne ""} {::nsf::method::property [::nsf::self] $r call-protected true} + if {$r ne ""} {::nsf::method::property [self] $r call-protected true} return $r } + + # method modifier "private" + :method private {args} { + if {![info exists ::nsf::methodDefiningMethod([lindex $args 0])]} { + error "'[lindex $args 0]' is not a method defining method" + } + set r [{*}:$args] + if {$r ne ""} {::nsf::method::property [self] $r call-private true} + return $r + } } # Provide a placeholder for objectparameter during the bootup Index: tests/protected.test =================================================================== diff -u -r88d8fd1e2b40d5797eb86a0be4c5cae7c595fac6 -r0595a14ffaf82764ce8bcc642741cd8ded14dc38 --- tests/protected.test (.../protected.test) (revision 88d8fd1e2b40d5797eb86a0be4c5cae7c595fac6) +++ tests/protected.test (.../protected.test) (revision 0595a14ffaf82764ce8bcc642741cd8ded14dc38) @@ -128,19 +128,20 @@ nx::Test case class-my-local { nx::Class create Base { - :protected method privateMethod {a b} { expr {$a + $b} } - :public method foo {a b} { nsf::my -local privateMethod $a $b } + :private method baz {a b} { expr {$a + $b} } + :public method foo {a b} { nsf::my -local baz $a $b } } nx::Class create Sub -superclass Base { - :public method bar {a b} { nsf::my -local privateMethod $a $b } - :public method privateMethod {a b} { expr {$a * $b} } + :public method bar {a b} { nsf::my -local baz $a $b } + :private method baz {a b} { expr {$a * $b} } :create s1 } ? {s1 foo 3 4} 7 ? {s1 bar 3 4} 12 + ? {s1 baz 3 4} {::s1: unable to dispatch method 'baz'} } #