Command objects
A command object is a Tcl object which can be invoked as a command and therefore has a "feather::command" interface. The closest example to this from a Tcl users point of view is a widget or an interp although these differ from command objects in that the widget or interp name is really just a handle which has to be explicitly freed when finished with.
Feather has the following command objects.
Black magic
Adding support for command objects to Tcl involved a detailed analysis of how Tcl resolves commands and Tcl objects in general. Here is a description of how this process works.
Executing a command line (which is basically an array of Tcl objects).
Converting a Tcl object to a "cmdName" object. This is only done if the object is not already a "cmdName" object (which in the case of command objects it isn't) or if something has changed which could invalidate the cached information.
The main problem with implementing command objects is the fact that the internal representation of the object is freed when it is converted to a "cmdName" type.
This is how I solved this problem.
Converting a Tcl command object to a "cmdName" object.
Invoking a command object.
At this point the command object is a "cmdName" and not the original type so the object needs fixing up. This has to be done by the command object's invoke function.
The invoke function is called either through the "feather::command" interface or through the above mechanism. The command object only needs fixing up in the latter case so the invoke function needs to distinguish between the two cases and it does that by looking at the clientData.
In the first case the clientData is NULL because objv [0] is still of the correct type and so the internal representation is available.
In the second case the clientData points to the internal representation of the original command object because objv [0] is now of a different type ("cmdName").
All that the invoke function needs to do is free the internal representation of objv [0], change its type and reset the internal representation. Remembering of course to take into account the effects of the preservation function.
Unfortunate side effects
There is obviously a slight performance impact due to the extra command resolver function, however this is slight and would be removed if Tcl ever added this support natively.
It is also possible to do the following because the interp resolver uses the name to look up the command. This usage is totally and utterly unsupported and I will prevent it if I can.
% set a [lambda {a} {puts $a}] <feather::lambda 0x20102028> % "<feather::lambda 0x20102028>" 95 95 % eval [list $a] 95 95