Skip to content

Know the FORTH programming language in one page

H.C. Chen edited this page Aug 4, 2020 · 7 revisions

Fundamentals

For a programmable python debugger, FORTH syntax is what I choose among shells and programming languages I know, put aside to define a my-way for the purpose.

FORTH is the easiest programming language.

Everything is a command in FORTH.

A number, say 123, is a command that dictates FORTH to push 123 onto the FORTH data stack. FORTH commands implicitly work on the data stack all the time.

Whether the number is an integer or a float, single or double precision, or even a complex is up to the the host environment, for peforth that's python.

+ is a command too that dictates FORTH to pop two operands out of the data stack and + them and push the result back to the data stack. As a convention, most FORTH commands consume their operands, like the + command mentioned here. Keep this in mind.

+ is a 'word' in FORTH. Anything in FORTH that is not a number is a 'word'.

The command line where you type in commands is TIB, terminal input buffer.

Some words get their operands from TIB instead of from the data stack. For example ." hello world! " prints "hello world!" where the word ." is of that kind that gets its operand from the TIB.

TIB can be given with an entire text file like the peforth source code peforth.f that build up the peforth system top on its kernel projectk.py that provides only two beginning words code and end-code.

FORTH has two working stats, interpret stat and compiling stat. I believe most of our debugging usages will be only in the interpret stat so you probably never need to know about the compiling stat. But it's easy! When we define a colon word like : hi ." Hello World!" cr ; between : and ; is in the compiling stat.

The FORTH programming language is the result of a set of words that work together. In contrast to other languages, 'while', 'repeat', 'if', 'then' and 'else' are not reserved words. They are as normal as other words. Variable, constant, for-loop, object oriented, or whatever future programming language concepts, ... etc, all of them are not from FORTH but from the specific FORTH system author who defined those words that bring out such meanings.

We have covered the most important points about FORTH already except words, words, and words. You can list all peforth words by the words command and view their help message and comments by help <word name>, or just help to list them all, and see their details through see <word name>. We're going to do exercises with words that are supposed would be used in your debuggings in the next section.

peforth one-liners

Not only a number pushes itself onto the data stack but also strings, booleans, ... etc. Try copy-paste this line to peforth:

  integer
    |         string                  boolean
    |           |    hex decimal        |       .---- pyhon's "nothing"
    |  float    |       |               |       |  .---- array or list
    |    |      |       |    binary     |       |  |  .--- null string
    |    |      |       |      |        |       |  |  |  .-- dict or set
    |    |      |       |      |        |       |  |  |  |
   --- ---- -------- ------ ------ ---------- ---- -- -- --
OK 123 45.6 s" abc " 0xabcd 0b0011 true false none [] "" {}

.s command dumps the data stack without consuming anything.

OK .s
      0:         123          7Bh (<class 'int'>)
      1:        45.6              (<class 'float'>)
      2: abc  (<class 'str'>)
      3:      43,981        ABCDh (<class 'int'>)
      4:           3           3h (<class 'int'>)
      5: True (<class 'bool'>)
      6: False (<class 'bool'>)
      7: None (<class 'NoneType'>)
      8: [] (<class 'list'>)
      9:  (<class 'str'>)
     10: {} (<class 'dict'>)
OK
OK dropall .s  <--------------- drop all cells from the data stack
empty  <--------------- so it's now empty

More complicated things are represented by in-line python directly:

            complex           dictionary          list (array)     set
              |                 |                   |               |
              |                 |                   |               |
           ----------  ---------------------  --------------  --------------
OK dropall py> 67+89j  py> {'aa':11,'bb':22}  py> [11,22,33]  py> {44,55,66} .s
      0:    (67+89j)              (<class 'complex'>)                        --
      1: {'aa': 11, 'bb': 22} (<class 'dict'>)                                |
      2: [11, 22, 33] (<class 'list'>)                                        |
      3: {66, 44, 55} (<class 'set'>)              dump data stack -----------'

Some peforth words are actually same thing represented by in-line python:

OK {} py> {} = . cr  \ the '=' command pops two operands
True                 \ compares them and pushes back a boolean

OK [] py> [] = . cr
True

OK "" py> "" = . cr
True

OK

In-line python, try copy-paste these lines together:

 .--------- Clear the screen
 |
 V
---
cls dropall py: print('hello')
py:~ print('hello world!')
.s py> 12+34j .s
dropall py>~ 12 + 34j
.s

The executed results of above lines:

            .------------ in-line python, no return value
            |             no space in the python statement
           ---
OK dropall py: print('hello')
hello

    .-------------- in-line phthon, no return value.
    |               The rest of the line are all python.
    |               Spaces are therefore allowed.
   ----
OK py:~ print('hello world!')
hello world!

OK .s py> 12+34j .s   <----- no space, py> is ok
empty

      0:    (12+34j)              (<class 'complex'>)

                    .----- with spaces, use py>~
                    |
                --------
OK dropall py>~ 12 + 34j
OK .s
      0:    (12+34j)              (<class 'complex'>)
OK

Use pop() and tos() in in-line python

OK dropall py> 12+34j py> tos().real py> pop(1).imag .s
      0:        12.0              (<class 'float'>)
      1:        34.0              (<class 'float'>)
OK

To understand the above example, let's do it again step by step commented with stack diagram:

                    "stack diagrams" are like these
                    they are actually comments
                    --------------------------------
dropall py> 12+34j  ( 12+34j )
py> tos().real      ( 12+34j 12.0 )
py> pop(1)          ( 12.0 12+34j )
:> imag             ( 12.0 34.0 )
.s
      0:        12.0              (<class 'float'>)
      1:        34.0              (<class 'float'>)
OK

The Fantastic Four members from the FORTH tradition: 'dup', 'swap', 'over', 'drop' and friends 'pick', 'roll', 'nip' and 'rot' are not used as often as traditional FORTH because in-line python is convenient enough. Copy-paste the below block to see their help messages at once:

cls
help dup
help swap
help over
help drop
help pick
help roll
help nip
help rot
help -rot

Results :

OK     help dup
( a -- a a ) Duplicate TOS.

OK     help swap
( a b -- b a ) stack operation

OK     help over
( a b -- a b a ) Stack operation.

OK     help drop
( x -- ) Remove TOS.

OK     help pick
( nj ... n1 n0 j -- nj ... n1 n0 nj ) Get a copy
        Use py> tos(n) is better I think

OK     help roll
( ... n3 n2 n1 n0 3 -- ... n2 n1 n0 n3 ) Make a rolling
        see rot -rot roll pick

OK     help nip
( a b -- b )

OK     help rot
( w1 w2 w3 -- w2 w3 w1 )
        see rot -rot roll pick

OK     help -rot
( w1 w2 w3 -- w3 w1 w2 )
        see rot -rot roll pick

OK

Object, dictionary, function, and list names are mostly appear with ., (...), or [...], for example:

py> print . cr         \ "print" is a function
py: print('hello')     \ it mostly followed with a (...)
py> print :: ('hello') \ same thing in peforth syntax

so :: is the peforth connector in between the name and the followings. Again, to involve spaces we use ::~ :

OK py> print ::~ ( " hello world ! ! " )
 hello world ! !
OK

Therefore :> , :>~ are easy now, they leave a return value at the TOS, top of the stack, after the execution:

OK py> {'aa':11,'bb':22}   \ now tos() is {'aa':11,'bb':22}
OK :> ['aa'] . cr          \ equivalent to: py> pop()['aa']
11
OK

If you find any question please open 'Issues' to the peforth GitHub. If you want to read a book, alough I wish that the aboves are enough for all python debuggings, I recommend OLPC's Forth Lessons or many other resources recommended there. If you find words mentioned in it are not existing in peforth then you can define them by yourself. No kidding, refer to peforth.f to see how to build an entire FORTH system from only two beginning words code and end-code, indeed FORTH is the easiest programming language ever.

May the FORTH be with you!

H.C. Chen @ FigTaiwan
hcchen5600@gmail.com
Just undo it!

Clone this wiki locally