Index: TODO =================================================================== diff -u -r528a87a8013672f9eae421f22f8ccba17c2fc838 -re0b2cf92c8e886f0a51e9d5233e636251edc45e7 --- TODO (.../TODO) (revision 528a87a8013672f9eae421f22f8ccba17c2fc838) +++ TODO (.../TODO) (revision e0b2cf92c8e886f0a51e9d5233e636251edc45e7) @@ -4985,6 +4985,9 @@ ======================================================================== TODO: +- forwarder: Turn switch -verbose in a valued nonpos arg which allows + to set the channel: stdout vs. stderr? + - forwarders/aliases: -checkalways is missing. Issues: 1) limit to -returns only? 2) cover value checkers of method parameters also, effectively overruling -checkalways settings of the Index: doc/forward.man.inc =================================================================== diff -u -ref17499c6911ca6b6712384f6793acc1d7cb856e -re0b2cf92c8e886f0a51e9d5233e636251edc45e7 --- doc/forward.man.inc (.../forward.man.inc) (revision ef17499c6911ca6b6712384f6793acc1d7cb856e) +++ doc/forward.man.inc (.../forward.man.inc) (revision e0b2cf92c8e886f0a51e9d5233e636251edc45e7) @@ -6,15 +6,15 @@ [call [arg [vset CMD]] [opt "public | protected | private"] [const [vset SCOPE]] [method forward] [arg methodName] [opt [option "-default [arg value]"]] [opt [option "-methodprefix [arg prefixName]"]] [opt [option "-objframe"]] [opt [option "-onerror [arg cmdName]"]] [opt [option "-returns [arg valueChecker]"]] [opt [option "-verbose"]] [arg arg] [opt "[arg arg] ..."]] Define a [term "forward method"] for the given [vset SCOPE]. The -resulting method registers a predefined, but changeable list of -forwarder arguments under the (forwarder) name [arg methodName]. Upon +definition of a [term "forward method"] registers a predefined, but +changeable list of forwarder arguments under the (forwarder) name [arg methodName]. Upon calling the [term "forward method"], the forwarder arguments are -evaluated as a Tcl command call. That is, the first argument [arg arg] -is interpreted as a Tcl command (e.g., a Tcl [cmd proc] or an object) -and the remainder of the forwarder arguments as arguments passed into -this command. The actual method arguments to the invocation of the -[term "forward method"] itself are appended to the list of forwarder -arguments. +evaluated as a Tcl command call. That is, the first +argument [arg arg] is interpreted as a Tcl command (e.g., a Tcl [cmd proc] or +an object) and the remainder of the forwarder arguments as arguments +passed into this command. The actual method arguments to the +invocation of the [term "forward method"] itself are appended to the +list of forwarder arguments. [para] @@ -28,11 +28,12 @@ [para] -The list of forwarder arguments [arg arg] can contain a mix of literal -values and placeholder values. Placeholders are prefixed with a -percent symbol (%) and substituted for concrete values upon calling -the [term "forward method"]. These placeholders allow for constructing -and for manipulating the list of forwarder arguments on the fly: +The list of forwarder arguments [arg arg] can contain as its elements +a mix of literal values and placeholder values. Placeholders are +prefixed with a percent symbol (%) and substituted for concrete values +upon calling the [term "forward method"]. These placeholders allow for +constructing and for manipulating the list of forwarder arguments on +the fly: [list_begin itemized] @@ -42,46 +43,52 @@ [item] [const %1] becomes substituted for the first method argument passed to the call of [term "forward method"]. -[item] {[const %@[arg index]] [arg value]} becomes substituted for the +[item] {[const %@][arg index] [arg value]} becomes substituted for the specified [arg value] at position [arg index] in the forwarder-arguments list, with [arg index] being either a positive integer, a negative integer, or the literal value [const end] (such as in Tcl's [cmd lindex]). Positive integers specify a list position -relative to the list head, negative integers give a position -relative to the list tail. +relative to the list head, negative integers give a position relative +to the list tail. Indexes for positioning placeholders in the definition of a +[term "forward method"] are evaluated from left to right and should be +used in ascending order. +[para] +Note that [arg value] can be a literal or any of the placeholders +(e.g., [const %proc], [const %self]). An exception are position +prefixes themselves which are evaluated according to the [const %][arg cmdName]-rule +(see below). [item] {[const %argclindex] [arg list]} becomes substituted for the [emph n]th element of the provided [arg list] , with [emph n] corresponding to the number of method arguments passed to the [term "forward method"] call. [item] [const %%] is substituted for a single literal percent (%) symbol. -[item] [const %[arg cmdName]] is substituted for the value returned -from executing the Tcl command [arg cmdName]. +[item] [const %][arg cmdName] is substituted for the value returned +from executing the Tcl command [arg cmdName]. To pass arguments to [arg cmdName], the placeholder should be wrapped into a Tcl [cmd list]: {[const %][arg cmdName] [opt "[arg arg] ..."]}. +[para] +Consider using fully-qualified Tcl command names for [arg cmdName] to +avoid possible name conflicts with the predefined placeholders, e.g., +[const %self] vs. %[cmd ::nx::self]. [list_end] -Additionally, any forwarder argument [arg arg] can be prefixed with -[const %@][arg index] to set the subsitition position in the resulting Tcl command list explicitly. [arg index] can be either a -positive integer, a negative integer, or [const end] (such as in Tcl's -[cmd lindex]). The positioning prefixes are evaluated from left to -right and should be used in ascending order. - [para] +[comment { +# @parameter -default Is used for default method names (only +# in connection with %1) +# @parameter -methodprefix Prepends the specified prefix to the second +# argument of the invocation. +}] - [para] To inspect and to debug the substitutions performed by the above placeholder values, setting the [term "switch"] [option "-verbose"] will have the resulting Tcl command (i.e., after substitution) printed to -[const stdout]. +[const stdout] upon calling the [term "forward method"]. [comment {# # @parameter method The name of the delegating or forwarder method -# @parameter -default Is used for default method names (only -# in connection with %1) -# @parameter -methodprefix Prepends the specified prefix to the second -# argument of the invocation. # @parameter -objframe Causes the target to be evaluated in # the scope of the object. # @parameter -onerror Register an error handler Index: tests/forward.test =================================================================== diff -u -r4bc60e16c10fdbbb640b3019d4bdebdc469fdf55 -re0b2cf92c8e886f0a51e9d5233e636251edc45e7 --- tests/forward.test (.../forward.test) (revision 4bc60e16c10fdbbb640b3019d4bdebdc469fdf55) +++ tests/forward.test (.../forward.test) (revision e0b2cf92c8e886f0a51e9d5233e636251edc45e7) @@ -255,6 +255,91 @@ ? {obj @end-13 1 2 3 } [list 13 1 ::obj 2 3] } +nx::test case placeholder-basics { + nx::Object create obj + obj public object forward foo list {%argclindex {A B C}} + ? {obj foo} A + ? {obj foo _} "B _" + ? {obj foo _ _} "C _ _" + ? {obj foo _ _ _ _} "forward: not enough elements in specified list of ARGC argument argclindex {A B C}" +} + +nx::test case positioning-arg-extended { + + nx::Object create obj + obj public object forward foo list {%@end %self} + ? {obj foo 1 2 3} [list 1 2 3 ::obj] + obj public object forward foo list {%@end %proc} + ? {obj foo 1 2 3} [list 1 2 3 foo] + + obj public object forward foo list {%@end %%} + ? {obj foo 1 2 3} [list 1 2 3 %] + + obj public object forward foo list {%obj foo} + ? {obj foo 1 2 3} "too many nested evaluations (infinite loop?)" + + obj public object forward foo list {%apply {{x} {return $x}} A} + ? {obj foo 1 2 3} [list A 1 2 3] + + ## positioning of "simple" cmd substitution works fine + obj public object forward foo list {%@end %obj} + ? {obj foo 1 2 3} [list 1 2 3 ::obj] + + ## lindex allows for omitting the index arg or passing {} as index value ... forward catches both cases nicely: + obj public object forward foo list {%@{} %obj} + ? {obj foo 1 2 3} "forward: invalid index specified in argument %@{} %obj" + + obj public object forward foo list {%@ %obj} + ? {obj foo 1 2 3} "forward: invalid index specified in argument %@ %obj" + + ## + ## resolving name conflicts between Tcl commands & predefined + ## placeholder names -> use fully qualified names + ## + + obj public object forward foo list {%@end %::proc} + ? {obj foo 1 2 3} {wrong # args: should be "::proc name args body"} + + obj public object forward foo list {%@end %::self} + ? {obj foo 1 2 3} [list 1 2 3 ::obj] + + obj public object forward foo list {%@end %::nx::self} + ? {obj foo 1 2 3} [list 1 2 3 ::obj] + + obj public object forward foo list {%@end %::1} + ? {obj foo 1 2 3} {invalid command name "::1"} + + ## + ## position prefixes are interpreted in a context-dependent manner: + ## + + obj public object forward foo list {%@1 %@1} + ? {obj foo 1 2 3} {invalid command name "@1"} + + if {![string length "ISSUES"]} { + + + ## list protection makes this fail + obj public object forward foo list {%@end {%argclindex {A B C D}}} + ? {obj foo 1 2 3} [list 1 2 3 D] + + ## positioned "complex" cmd substitution (cmd + args) not working because of list protection + obj public object forward foo list {%@end {%list 1}} + ? {obj foo 1 2 3} [list 1 2 3 A] + + ## Why not %1 not working with positioning working? + obj public object forward foo list {%@end %1} + ? {obj foo 1 2 3} [list 1 2 3 1] + + ## + ## Should this be caught somehow? How would this be treated when list protection would not interfere? + ## + obj public object forward foo list {%@1 {%@1 "x"}} + ? {obj foo 1 2 3} "forward: invalid index specified in argument %@{} %obj" + } +} + + ############################################### # substitution depending on number of arguments ###############################################