Index: TODO =================================================================== diff -u -rbfdad656af33451da0213dd66789a3d0f625ba18 -rd8dcbc3ba475a4617d540b4499a9c41e8bf81b07 --- TODO (.../TODO) (revision bfdad656af33451da0213dd66789a3d0f625ba18) +++ TODO (.../TODO) (revision d8dcbc3ba475a4617d540b4499a9c41e8bf81b07) @@ -3545,6 +3545,9 @@ - nx.tcl: moved "properties" from nx::Class to nx::Object +- nsf.c: make ":" a full equivalent vor nsf::my + (i.e. support -local, -system and -intrinsic) +- extend regression test TODO: - NSF_WITH_OS_RESOLVER Index: generic/nsf.c =================================================================== diff -u -rc7686b76eff01e25abf042d5b4fa2dfa998b22f1 -rd8dcbc3ba475a4617d540b4499a9c41e8bf81b07 --- generic/nsf.c (.../nsf.c) (revision c7686b76eff01e25abf042d5b4fa2dfa998b22f1) +++ generic/nsf.c (.../nsf.c) (revision d8dcbc3ba475a4617d540b4499a9c41e8bf81b07) @@ -17504,20 +17504,69 @@ NsfColonCmd(Tcl_Interp *interp, int nobjc, Tcl_Obj *CONST nobjv[]) { CONST char *methodName = ObjStr(nobjv[0]); NsfObject *self = GetSelfObj(interp); + if (unlikely(self == NULL)) { return NsfNoCurrentObjectError(interp, methodName); } /*fprintf(stderr, "Colon dispatch %s.%s (%d)\n", ObjectName(self), ObjStr(nobjv[0]), nobjc);*/ - if (*methodName == ':' && *(methodName + 1) == '\0') { - if (nobjc > 1) { - return ObjectDispatch(self, interp, nobjc, nobjv, 0); - } else { - return DispatchDefaultMethod(interp, (NsfObject *)self, nobjv[0], 0); + if (likely(!(*methodName == ':' && *(methodName + 1) == '\0'))) { + return ObjectDispatch(self, interp, nobjc, nobjv, NSF_CM_NO_SHIFT); + } + /* + * first arg is a single colon + */ + if (nobjc <= 1) { + Tcl_SetObjResult(interp, self->cmdName); + return TCL_OK; + } + + /* + * multiple arguments were given + */ + methodName = ObjStr(nobjv[1]); + + if (*methodName != '-') { + /* + * no need to parse arguments (local, intrinsic, ...) + */ + return ObjectDispatch(self, interp, nobjc, nobjv, 0); + } else { + ParseContext pc; + int withIntrinsic, withLocal, withSystem, flags; + Tcl_Obj *methodObj; + + /* + * parse arguments, use definitions from nsf::my + */ + + if (ArgumentParse(interp, nobjc, nobjv, NULL, nobjv[0], + method_definitions[NsfMyCmdIdx].paramDefs, + method_definitions[NsfMyCmdIdx].nrParameters, 1, + &pc) != TCL_OK) { + return TCL_ERROR; } + + withIntrinsic = (int )PTR2INT(pc.clientData[0]); + withLocal = (int )PTR2INT(pc.clientData[1]); + withSystem = (int )PTR2INT(pc.clientData[2]); + methodObj = (Tcl_Obj *)pc.clientData[3]; + + assert(pc.status == 0); + + if ((withIntrinsic && withLocal) + || (withIntrinsic && withSystem) + || (withLocal && withSystem)) { + return NsfPrintError(interp, "flags '-intrinsic', '-local' and '-system' are mutual exclusive"); + } + + flags = NSF_CSC_IMMEDIATE; + if (withIntrinsic) {flags |= NSF_CM_INTRINSIC_METHOD;} + if (withLocal) {flags |= NSF_CM_LOCAL_METHOD;} + if (withSystem) {flags |= NSF_CM_SYSTEM_METHOD;} + return CallMethod(self, interp, methodObj, (nobjc-pc.lastObjc)+2, nobjv+pc.lastObjc, flags); } - return ObjectDispatch(self, interp, nobjc, nobjv, NSF_CM_NO_SHIFT); } /* Index: tests/methods.test =================================================================== diff -u -re529093e5930cb5c9de2bc81cef3eca2585f154f -rd8dcbc3ba475a4617d540b4499a9c41e8bf81b07 --- tests/methods.test (.../methods.test) (revision e529093e5930cb5c9de2bc81cef3eca2585f154f) +++ tests/methods.test (.../methods.test) (revision d8dcbc3ba475a4617d540b4499a9c41e8bf81b07) @@ -675,6 +675,42 @@ :class method unknown args {? [list set _ $args] "{hello world}"} } C {hello world} +} +# +# simple speed tests +# ensemble unknown tests are in submethods.test +# +nx::Test parameter count 100000 +nx::Test case speed-dispatch { + + # + # define various forms of simple dispatches + # + ::nx::Object create o { + :public method foo {} {return ::o} + :public method bar00 {} {self} + :public method bar01 {} {:} + :public method bar02 {} {[self]} + :public method bar03 {} {[:]} + :public method bar04 {} {:foo} + :public method bar05 {} {: foo} + :public method bar06 {} {my foo} + :public method bar07 {} {[self] foo} + :public method bar08 {} {: -system info methods foo} + :public method bar09 {} {my -system info methods foo} + } + + ? {o foo} ::o + ? {o bar00} ::o {self} + ? {o bar01} ::o {:} + ? {o bar02} ::o {[self]} + ? {o bar03} ::o {[:]} + ? {o bar04} ::o ":foo" + ? {o bar05} ::o ": foo" + ? {o bar06} ::o "my foo" + ? {o bar07} ::o "self foo" + ? {o bar08} foo ": -system info" + ? {o bar09} foo "my -system info" } \ No newline at end of file Index: tests/object-system.test =================================================================== diff -u -rc7686b76eff01e25abf042d5b4fa2dfa998b22f1 -rd8dcbc3ba475a4617d540b4499a9c41e8bf81b07 --- tests/object-system.test (.../object-system.test) (revision c7686b76eff01e25abf042d5b4fa2dfa998b22f1) +++ tests/object-system.test (.../object-system.test) (revision d8dcbc3ba475a4617d540b4499a9c41e8bf81b07) @@ -122,6 +122,7 @@ o public method bar4 {} {return bar4-[[self] foo]} o public method bar5 {} {return [self]::bar5} o public method bar6 {} {return [:]::bar6} +o public method bar7 {} {return bar7-[lsort [: -system info methods bar7]]} # dispatch without colon names ? {o foo} foo "simple method dispatch" @@ -131,6 +132,7 @@ ? {o bar4} bar4-foo "self dispatch" ? {o bar5} ::o::bar5 "self cmd" ? {o bar6} ::o::bar6 "colon cmd" +? {o bar7} bar7-bar7 "colon cmd dispatch args" o destroy # basic attributes tests Index: tests/protected.test =================================================================== diff -u -rac96e6ce975fe5864b64dee9d66bc701a31e113b -rd8dcbc3ba475a4617d540b4499a9c41e8bf81b07 --- tests/protected.test (.../protected.test) (revision ac96e6ce975fe5864b64dee9d66bc701a31e113b) +++ tests/protected.test (.../protected.test) (revision d8dcbc3ba475a4617d540b4499a9c41e8bf81b07) @@ -183,8 +183,8 @@ # methods are defined as private to avoid interference. # nx::Class create M { - :public method foo {} {my -local bar} - :private method bar {} {my -local baz} + :public method foo {} {: -local bar} + :private method bar {} {: -local baz} :private method baz {} {return "M.baz"} } @@ -214,17 +214,17 @@ :public method bar {} {return "B.bar [next]"} :public method baz {} {return "B.baz [next]"} :create b1 { - :public method foo {} {my -local bar} - :private method bar {} {my -local baz} + :public method foo {} {: -local bar} + :private method bar {} {: -local baz} :private method baz {} {return "b1.baz"} } } nx::Class create C -superclass B { :public method bar {} {return "C.bar [next]"} :public method baz {} {return "C.baz [next]"} :create c1 { - :public method foo {} {my -local bar} - :private method bar {} {my -local baz} + :public method foo {} {: -local bar} + :private method bar {} {: -local baz} :private method baz {} {return "c1.baz"} } } @@ -265,7 +265,7 @@ nx::Test case local+filter { nx::Class create C { :method f1 args { return "f1 [next]" } - :public method foo {} { return "C.foo [my -local bar]"} + :public method foo {} { return "C.foo [: -local bar]"} :private method bar {} { return "bar"} :public method baz {} { return "C.baz [next]"} } @@ -361,8 +361,8 @@ # add on B calls to local C eval { - :public method q1 {} {my -local p1} - :public method q3 {} {my -local p3} + :public method q1 {} {: -local p1} + :public method q3 {} {: -local p3} } # all chains start with C, since local resolve works ? {c1 q1} "C.p1 " @@ -390,17 +390,17 @@ # -# test "my -local" on classes +# test ": -local" on classes # nx::Test case class-my-local { nx::Class create Base { :private method baz {a b} { expr {$a + $b} } - :public method foo {a b} { my -local baz $a $b } + :public method foo {a b} {: -local baz $a $b} } nx::Class create Sub -superclass Base { - :public method bar {a b} { my -local baz $a $b } + :public method bar {a b} {: -local baz $a $b} :private method baz {a b} { expr {$a * $b} } :create s1 @@ -412,7 +412,7 @@ } # -# test "my -local" on objects +# test ": -local" on objects # nx::Test case object-my-local { nx::Class create M { @@ -422,7 +422,7 @@ nx::Object create o1 { :protected method foo {} {return o1} :public method foo2 {} {:foo} - :public method bar {} {my -local foo} + :public method bar {} {: -local foo} } ? {o1 foo} {::o1: unable to dispatch method 'foo'} @@ -438,17 +438,17 @@ } # -# test "my" + path instead of "my -local" on classes +# test "my" + path instead of ": -local" on classes # nx::Test case my+handle-instead-of-my-local { nx::Class create Base { :private method privateMethod {a b} { expr {$a + $b} } - :public method foo {a b} { my [Base info method handle privateMethod] $a $b } + :public method foo {a b} {: [Base info method handle privateMethod] $a $b} } nx::Class create Sub -superclass Base { - :public method bar {a b} { my [Sub info method handle privateMethod] $a $b } + :public method bar {a b} {: [Sub info method handle privateMethod] $a $b} :private method privateMethod {a b} { expr {$a * $b} } :create s1 @@ -459,7 +459,7 @@ } # -# test object::dispatch instead of "my -local" on classes +# test object::dispatch instead of ": -local" on classes # nx::Test case dispatch-instead-of-my-local { @@ -545,18 +545,18 @@ nx::Class create Base { :private method baz {a b} { expr {$a + $b} } :protected method baz2 {a b} { expr {$a + $b} } - :public method foo {a b} { my -local baz $a $b } + :public method foo {a b} {: -local baz $a $b} :create b1 } # we can call Base.baz only through Base.foo ? {b1 foo 4 5} 9 ? {b1 baz 4 5} {::b1: unable to dispatch method 'baz'} # Define and register a mixin class, where method "foo" is calling a - # private method via "my -local" + # private method via ": -local" nx::Class create Mix { :private method baz {a b} { expr {$a ** $b} } - :public method foo {a b} { my -local baz $a $b } + :public method foo {a b} {: -local baz $a $b} } b1 mixin add Mix @@ -571,8 +571,8 @@ nx::Class create Intermediate -superclass Base { :private method baz {a b} { next } :private method baz2 {a b} { next } - :public method foo {a b} { my -local baz $a $b } - :public method foo2 {a b} { my -local baz2 $a $b } + :public method foo {a b} {: -local baz $a $b} + :public method foo2 {a b} {: -local baz2 $a $b} :create i1 } @@ -583,7 +583,7 @@ ? {i1 foo2 4 5} 9 nx::Class create Sub -superclass Intermediate { - :public method bar {a b} { my -local baz $a $b } + :public method bar {a b} {: -local baz $a $b} :private method baz {a b} { expr {$a * $b} } :create s1