Version 4 of Tcl Command Evaluation: Layer by Layer

Updated 2004-08-24 17:37:36

A number of difficult questions have arisen, and continue to arise concerning the details about how Tcl commands are evaluated.

This page has been created to lay out the details of Tcl command evaluation in order to see the various points at which existing behavior might be modified, or new behavior might be attached.

I find it easiest to follow the details by working from the inside out.

Layer 0: Tcl_ObjCmdProc

The innermost core of any Tcl command is a Tcl_ObjCmdProc, a C routine that matches the prototype:

   typedef int (Tcl_ObjCmdProc) (
      ClientData clientData,
      Tcl_Interp *interp,
      int objc,
      struct Tcl_Obj * CONST * objv);

A new Tcl command gets created by writing a Tcl_ObjCmdProc, associating it with a ClientData, and with a command name in an interp, via a call to Tcl_CreateObjCommand.

The Tcl_ObjCmdProc gets passed the associated ClientData, the interp, and the full Tcl_Obj array of the words of the command being evaluated.

The objv1 ... objvobjc-1 values are the arguments to the command, and can influence the result. The Tcl_ObjCmdProc should avoid changing behavior based on the value of objv0 however, for a few reasons. First it is a property of Tcl commands that they can be renamed. Thus the value of objv0 may very well not be the command name originally passed to Tcl_CreateObjCommand.


The caller of the Tcl_ObjCmdProc must pass in the appropriate ClientData value as was previously registered (say, by, Tcl_CreateObjCommand). This indicates that the ClientData value and the Tcl_ObjCmdProc value ought to be stored in the same struct. The Tcl_CmdDeleteProc that will take care of any ClientData cleanup also belongs in that same struct.

The caller will also pass in the interp, objc, and objv values. In the usual case, these values come passed down, originating from the parser. The interp value will have contained within it information about the current namespace, and the current call frame.

Note that the caller of Tcl_ObjCmdProc doesn't have any need to know the command's (preferred) name.

The Tcl_ObjCmdProc can count on the result of the interp having been reset. It is expected to return a return code value. It may set the interp result, if the reset state is not correct. It may also set the errorInfo and/or errorCode values if it is returning TCL_ERROR.

Current Status

The Tcl_ObjCmdProc callers are currently:

   TclEvalObjvInternal
   TclInvokeObjectCommand
   TclObjInvoke
   Tcl_Import
   InvokeImportedCmd

They are not fully consistent with one another in how they manage command dispatch.

Possible Enhancements

I believe it would aid maintenance and improve consistency if refactoring allowed for only one Tcl_ObjCmdProc caller. For example, currently [trace execution] traces do not fire on [namespace import]ed commands.

Might need a C API to set values in the return options dictionary. Currently this is possible at the script level using [return], but there's no C API currently for that. Such a routine would cover errorInfo and errorCode setting, but would also be more general.


[ Category Internals ]