A more humble approach is needed. In this vein, one can start by noting that Tcl's ``cmd arg arg arg'' style statements lend themselves to preparsing. This is because it is always possible to determine the arguments to a given command. At the very least, the compiler can break up the statement into string arguments, which will save some amount of parsing effort normally expended at runtime. Preparsing is very valuable in Tcl; a typical Tcl script spends most of its non-work-related execution time scanning and parsing statements.
However, preparsing statements into arg lists is not a panacea. Many important commands take arguments containing large amounts of data. For example, if, while, proc, for, and other commands all take ``command lists'' in one or more arguments. These cmdlists are often hundreds of bytes long; they effectively can contain entire scripts within them. Clearly, one would like to parse these internally as well. By the same token, we would like to also preparse the boolean expressions associated with for, if, and while, and the list structures used by lindex and the other list commands, and so on. In the following example, if arguments weren't individually parsed, the body of this for loop would remain in string form, and would require runtime parsing, and thus the compiler would provide little performance improvement.
for {set i 0} {$i<1000} {incr i} { <many lines of code> }
To accomplish this, a typing system for Tcl is needed, where one doesn't exist. Normally, the types are coerced from string data at runtime, on a per-command basis. It is happenstance that the list format is universal among list commands, for example. Thus, some way is needed to inform the compiler as to the argument types each command expects. Then, if a static string is found at compile-time, we can preparse this to be of that type. For example, since almost all cmdlists are surrounded by curly braces in Tcl source code, the contents are static (no substitution will occur prior to the argument being passed to the command). These can then be parsed at compile-time, and treated as a list of commands. In the case where variable substitution is allowed, such preparsing cannot happen, since the argument value depends on a variable's value, which is unknown at compile-time.