Version 23 of TclForth

Updated 2014-07-02 12:42:02 by wej

wej - Several wiki pages describe how to handle Forth in Tcl ( RPN in Tcl, Trying FORTH in Tcl, A different Forth, f4t ). This page describes a different approach that, following f4t, aims "to integrate Forth and Tcl as harmonically as possible".

TclForth is a Forth system that uses Tcl as its native language. It has the following features.

Code words - The code words are Tcl procs without formal arguments. TclForth replaces the formal argument by a stack diagram that is used to add the appropriate stack handling.

Example: The Forth word

     code int { n1 -- n2 }  
          set n2 [expr int($n1)]  

is compiled to

      proc int {} {
          set n1 [pop];  set n2 [expr int($n1)]; push $n2 ;
     }

Colon words - TclForth is subroutine threaded. As a consequence, the high level colon words are also implemented as Tcl procedures. Example:

: Prompt { -- }
     depth 0> withStack and
     if   "$::stack ok>"
     else "ok>"
     then Console append update
;

becomes

proc Prompt {} {
     depth;  0>; push $::withStack; and;
     if [pop]  {
          push "$::stack ok>";
     } else {
          push "ok>";
     }
     $::Console insert end [pop]; update;
}

Code procs call Tcl commands, Colon procs call Forth words.

Inner interpreter - With subroutine threading the Tcl run time system is also the inner interpreter of TclForth.

The Forth words are collected in a dictionary implemented as the array words(). The indices are the Forth word names, the values are compiling scripts. For code and colon words the script inserts the word's name followed by the Tcl separator ";" .

Flow control is handled by Compiler words. The word Prompt above illustrates the compiling action of if, else and then. In similar ways TclForth implements all Forth flow words and adds foreach and switch (as a case-of-endof-endcase construct).

Other Tcl commands are made available in Forth as compiler words. Example:

Compiler doafter
     appendcode " after \[pop\] \[pop\];  "

If you miss a feature, add a compiler word.

Data words are implemented as objecttypes with separate message and method. The objecttypes are compiled as arrays with the messages as names and the methods as scripts. When an object is used in a definition the compiler substitutes the "obj" in the method code by the actual object's name. The default message {} is activated if the word following an object is not a valid message of this object. The object then delivers its value. - Definitions, reduced to the messages used in the following example:

objecttype variable 
     {}      {push $obj}
     set     {set obj [pop]}
     ...      ...

objecttype string  
     {}      {push $obj}
     ...      ...

objecttype list  
     append  {lappend obj [pop]}
     length  {push [llength $obj]}
     ...      ...

Example:

: SaveComline { comline -- }
     comline "" !=
     if   comline comhistory append      
          comhistory length  comindex set     
     then
;

is compiled to

proc SaveComline {} {
     set comline [pop]; push $comline; push "";  !=;
     if [pop]  {
          push $comline; lappend ::comhistory [pop]; push [llength $::comhistory]; set ::comindex [pop]; 
     }
} 

Stack Diagram - The stack diagram also defines stack-independent local variables for a definition. The syntax is { inputs | locals -- results } with any number of inputs, locals and results. The locals are compiled as objecttype variable and can then be casted to other types. Example:

: textword ( t | i j -- )  cast t string  i t length j set ...

Tk - Several attempts to use Tk widgets from a Forth system have been reported, TkForth is still the best documented. Tk has a clear syntax that can be handled in TclForth code words. There is no pressing need to invent a Forth syntax. However, TclForth provides some widgets as objecttypes that can be used in colon words. - Example:

objecttype tkcanvas  
        instance {uplevel #0 {set obj [pop]; canvas $obj} }
        {}       {push $obj}
        create   {eval $obj [concat create [pop]]}
        text     {3swap; eval $obj [concat create text [pop] [pop] -text \"[pop]\"]}
        config   {eval $obj [concat configure [pop]]}
        rectangle {6swap; eval $obj [concat create rect [pop] [pop] [pop] [pop] -fill [pop] -tag \"[pop]\"]} 
        delete   {$obj delete [pop]}
        polygon  {4swap; eval $obj [concat create poly \{[pop]\} -fill [pop] -outline [pop] -tag \"[pop]\"]} 
        ...

TclForth is available at [L1 ]. The system includes a version of Richard Suchenwirth's fine game Chess in Tcl as an example of a Tcl program in postfix syntax. -- The present version 0.5 has been carefully polished. 2014-07-02