Index: TODO =================================================================== diff -u -r50b5699927f9d34e2ab7a14e29ccf8dc1f569095 -r38de75d755e2a10fb0fb5a2b75bf08a751b4b5c0 --- TODO (.../TODO) (revision 50b5699927f9d34e2ab7a14e29ccf8dc1f569095) +++ TODO (.../TODO) (revision 38de75d755e2a10fb0fb5a2b75bf08a751b4b5c0) @@ -3322,7 +3322,15 @@ some redundancy ("class filter" and "class mixin"), but maybe this can be eliminated. +- nsf.c: + * fixed "nsf::my -local ..." (never worked in nsf) + * added regression test + + TODO: + - test next + dispatch + - test "my -local" vs dispatch + - nx: * maybe provide a replacement for -attributes, but without the magic variable. Index: generic/nsf.c =================================================================== diff -u -rb8c0176cfeae7f18490e9d6887ece97b713f0fe0 -r38de75d755e2a10fb0fb5a2b75bf08a751b4b5c0 --- generic/nsf.c (.../nsf.c) (revision b8c0176cfeae7f18490e9d6887ece97b713f0fe0) +++ generic/nsf.c (.../nsf.c) (revision 38de75d755e2a10fb0fb5a2b75bf08a751b4b5c0) @@ -18090,15 +18090,18 @@ } if (withLocal) { - NsfClass *cl = self->cl; CONST char *methodName = ObjStr(methodObj); - Tcl_Command cmd = FindMethod(cl->nsPtr, methodName); + NsfCallStackContent *cscPtr = CallStackGetTopFrame0(interp); + NsfClass *cl = cscPtr ? cscPtr->cl : NULL; + Tcl_Command cmd = cl ? FindMethod(cl->nsPtr, methodName) : FindMethod(self->nsPtr, methodName); if (cmd == NULL) { - return NsfPrintError(interp, "%s: unable to dispatch local method '%s' in class %s", - ObjectName(self), methodName, ClassName(cl)); + return NsfPrintError(interp, "%s: unable to dispatch local method '%s' in %s %s", + ObjectName(self), methodName, + cl ? "class" : "object", + cl ? ClassName(cl) : ObjectName(self)); } - result = MethodDispatch(self, interp, nobjc+2, nobjv, cmd, self, cl, - methodName, 0, 0); + result = MethodDispatch(self, interp, nobjc+1, nobjv-1, cmd, self, cl, + methodName, 0, NSF_CSC_IMMEDIATE); } else { #if 0 /* TODO attempt to make "my" NRE-enabled, failed so far (crash in mixinInheritanceTest) */ Index: tests/protected.test =================================================================== diff -u -ra24e1f836c3126d0a0e9467bde3a9fa8da901711 -r38de75d755e2a10fb0fb5a2b75bf08a751b4b5c0 --- tests/protected.test (.../protected.test) (revision a24e1f836c3126d0a0e9467bde3a9fa8da901711) +++ tests/protected.test (.../protected.test) (revision 38de75d755e2a10fb0fb5a2b75bf08a751b4b5c0) @@ -1,117 +1,170 @@ # -*- Tcl -*- package require nx package require nx::test -namespace import ::nx::* -Test parameter count 1 +nx::Test parameter count 1 -Class create C { - :public alias SET ::set - :public method foo {} {return [current method]} - :public method bar {} {return [current method]} - :public method bar-foo {} { - c1 foo +nx::Test case call-protected { + nx::Class create C { + :public alias SET ::set + :public method foo {} {return [current method]} + :public method bar {} {return [current method]} + :public method bar-foo {} { + c1 foo + } + :public method bar-SET {} { + c1 SET x 1 + } } - :public method bar-SET {} { - c1 SET x 1 - } -} + + C create c1 + C create c2 + + ? {c1 SET x 1} {1} + ? {c1 foo} {foo} + ? {c1 bar-SET} {1} + ? {c1 bar-foo} {foo} -C create c1 -C create c2 + ::nsf::method::property C SET call-protected true + ? {catch {c1 SET x 1} errorMsg; set errorMsg} {::c1: unable to dispatch method 'SET'} + ? {::nsf::object::dispatch c1 SET x 2} {2} "dispatch of protected methods works" + ? {c1 foo} {foo} + ? {c1 bar} {bar} + ? {c1 bar-SET} {1} + ? {c1 bar-foo} {foo} + ? {catch {c2 bar-SET} errorMsg; set errorMsg} {::c1: unable to dispatch method 'SET'} + ? {c2 bar-foo} {foo} -? {c1 SET x 1} {1} -? {c1 foo} {foo} -? {c1 bar-SET} {1} -? {c1 bar-foo} {foo} + ::nsf::method::property C foo call-protected true + ? {catch {c1 SET x 1} errorMsg; set errorMsg} {::c1: unable to dispatch method 'SET'} + ? {::nsf::object::dispatch c1 SET x 2} {2} "dispatch of protected methods works" + ? {c1 bar} {bar} "other method work" + ? {catch {c1 foo} errorMsg; set errorMsg} {::c1: unable to dispatch method 'foo'} + ? {c1 bar-SET} {1} "internal call of protected C implementend method" + ? {c1 bar-foo} {foo} "internal call of protected Tcl implemented method" + ? {catch {c2 bar-SET} errorMsg; set errorMsg} {::c1: unable to dispatch method 'SET'} + ? {catch {c2 bar-foo} errorMsg; set errorMsg} {::c1: unable to dispatch method 'foo'} -::nsf::method::property C SET call-protected true -? {catch {c1 SET x 1} errorMsg; set errorMsg} {::c1: unable to dispatch method 'SET'} -? {::nsf::object::dispatch c1 SET x 2} {2} "dispatch of protected methods works" -? {c1 foo} {foo} -? {c1 bar} {bar} -? {c1 bar-SET} {1} -? {c1 bar-foo} {foo} -? {catch {c2 bar-SET} errorMsg; set errorMsg} {::c1: unable to dispatch method 'SET'} -? {c2 bar-foo} {foo} + # unset call protected + ? {::nsf::method::property C SET call-protected} 1 + ::nsf::method::property C SET call-protected false + ? {::nsf::method::property C SET call-protected} 0 + ? {::nsf::method::property C foo call-protected} 1 + ::nsf::method::property C foo call-protected false + ? {::nsf::method::property C foo call-protected} 0 + + ? {c1 SET x 3} 3 + ? {::nsf::object::dispatch c1 SET x 2} {2} + ? {c1 foo} {foo} + ? {c1 bar} {bar} + ? {c1 bar-SET} {1} + ? {c1 bar-foo} {foo} + ? {c2 bar-SET} 1 + ? {c2 bar-foo} {foo} -::nsf::method::property C foo call-protected true -? {catch {c1 SET x 1} errorMsg; set errorMsg} {::c1: unable to dispatch method 'SET'} -? {::nsf::object::dispatch c1 SET x 2} {2} "dispatch of protected methods works" -? {c1 bar} {bar} "other method work" -? {catch {c1 foo} errorMsg; set errorMsg} {::c1: unable to dispatch method 'foo'} -? {c1 bar-SET} {1} "internal call of protected C implementend method" -? {c1 bar-foo} {foo} "internal call of protected Tcl implemented method" -? {catch {c2 bar-SET} errorMsg; set errorMsg} {::c1: unable to dispatch method 'SET'} -? {catch {c2 bar-foo} errorMsg; set errorMsg} {::c1: unable to dispatch method 'foo'} + # define a protected method + C protected method foo {} {return [current method]} + ? {::nsf::method::property C SET call-protected} 0 + ? {c1 SET x 3} 3 + ? {::nsf::object::dispatch c1 SET x 4} {4} + ? {catch {c1 foo} errorMsg; set errorMsg} {::c1: unable to dispatch method 'foo'} + ? {c1 bar} {bar} + ? {c1 bar-SET} {1} + ? {c1 bar-foo} foo + ? {c2 bar-SET} 1 + ? {catch {c2 bar-foo} errorMsg; set errorMsg} {::c1: unable to dispatch method 'foo'} +} -# unset protected -? {::nsf::method::property C SET call-protected} 1 - ::nsf::method::property C SET call-protected false -? {::nsf::method::property C SET call-protected} 0 -? {::nsf::method::property C foo call-protected} 1 - ::nsf::method::property C foo call-protected false -? {::nsf::method::property C foo call-protected} 0 +nx::Test case redefined-protected { + nx::Class create C { + :public alias SET ::set + :public method foo {} {return [current method]} + } + # + # Define SET and foo as redefined-protected + # + ? {::nsf::method::property C SET redefine-protected true} 1 + ? {::nsf::method::property C foo redefine-protected true} 1 + + ? {C method SET {a b c} {...}} \ + {Method 'SET' of ::C cannot be overwritten. Derive e.g. a sub-class!} \ + "redefine method SET" + + ? {C method foo {a b c} {...}} \ + {Method 'foo' of ::C cannot be overwritten. Derive e.g. a sub-class!} \ + "redefine method foo" + + # check a predefined protection + ? {::nx::Class method create {a b c} {...}} \ + {Method 'create' of ::nx::Class cannot be overwritten. Derive e.g. a sub-class!} \ + "redefine method create" + + # try to redefine predefined protected method via alias + ? {::nsf::method::alias nx::Class create ::set} \ + {Method 'create' of ::nx::Class cannot be overwritten. Derive e.g. a sub-class!} \ + "redefine alias create" + + # try to redefine via forward + ? {C forward SET ::set} \ + {Method 'SET' of ::C cannot be overwritten. Derive e.g. a sub-class!} \ + "redefine forward SET" -? {c1 SET x 3} 3 -? {::nsf::object::dispatch c1 SET x 2} {2} -? {c1 foo} {foo} -? {c1 bar} {bar} -? {c1 bar-SET} {1} -? {c1 bar-foo} {foo} -? {c2 bar-SET} 1 -? {c2 bar-foo} {foo} + # try to redefine via setter + ? {C property SET} \ + {Method 'SET' of ::C cannot be overwritten. Derive e.g. a sub-class!} \ + "redefine property SET" + + # redefine-protect object specific method + nx::Object create o + o method foo {} {return 13} + ::nsf::method::property o foo redefine-protected true + ? {o method foo {} {return 14}} \ + {Method 'foo' of ::o cannot be overwritten. Derive e.g. a sub-class!} +} -# define a protected method -C protected method foo {} {return [current method]} -? {::nsf::method::property C SET call-protected} 0 -? {c1 SET x 3} 3 -? {::nsf::object::dispatch c1 SET x 4} {4} -? {catch {c1 foo} errorMsg; set errorMsg} {::c1: unable to dispatch method 'foo'} -? {c1 bar} {bar} -? {c1 bar-SET} {1} -? {c1 bar-foo} foo -? {c2 bar-SET} 1 -? {catch {c2 bar-foo} errorMsg; set errorMsg} {::c1: unable to dispatch method 'foo'} - # -# Define SET and foo as redefined-protected +# test "nsf::my -local" on classes # -? {::nsf::method::property C SET redefine-protected true} 1 -? {::nsf::method::property C foo redefine-protected true} 1 -? {C method SET {a b c} {...}} \ - {Method 'SET' of ::C cannot be overwritten. Derive e.g. a sub-class!} \ - "redefine method SET" +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 } + } + + 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} } -? {C method foo {a b c} {...}} \ - {Method 'foo' of ::C cannot be overwritten. Derive e.g. a sub-class!} \ - "redefine method foo" + :create s1 + } -# check a predefined protection -? {::nx::Class method create {a b c} {...}} \ - {Method 'create' of ::nx::Class cannot be overwritten. Derive e.g. a sub-class!} \ - "redefine method create" + ? {s1 foo 3 4} 7 + ? {s1 bar 3 4} 12 +} -# try to redefine predefined protected method via alias -? {::nsf::method::alias Class create ::set} \ - {Method 'create' of ::nx::Class cannot be overwritten. Derive e.g. a sub-class!} \ - "redefine alias create" +# +# test "nsf::my -local" on objects +# +nx::Test case object-my-local { + nx::Class create M { + :public method foo {} {return "M [next]"} + :public method foo2 {} {return "M2 [next]"} + } + nx::Object create o1 { + :protected method foo {} {return o1} + :public method foo2 {} {:foo} + :public method bar {} {nsf::my -local foo} + } -# try to redefine via forward -? {C forward SET ::set} \ - {Method 'SET' of ::C cannot be overwritten. Derive e.g. a sub-class!} \ - "redefine forward SET" + ? {o1 foo} {::o1: unable to dispatch method 'foo'} + ? {o1 bar} o1 + ? {o1 foo2} o1 -# try to redefine via setter -? {C property SET} \ - {Method 'SET' of ::C cannot be overwritten. Derive e.g. a sub-class!} \ - "redefine property SET" + o1 mixin add M -# overwrite-protect object specific method -Object create o -o method foo {} {return 13} -::nsf::method::property o foo redefine-protected true -? {o method foo {} {return 14}} \ - {Method 'foo' of ::o cannot be overwritten. Derive e.g. a sub-class!} + ? {o1 foo} "M o1" + ? {o1 bar} "o1" + ? {o1 foo2} "M2 M o1" +} \ No newline at end of file