Home

Abstract

The Forth programming language is known for it's simple and sparse syntax. For this experiment a Forth like language is constructed using a handful of symbols : ; . + * ? > & # $ and 3 stacks. The Input Stack, the Dictionary, and the Data Stack.

I've named this experiment Active Forth because of the fundamental distinction between passive/active mode which is similar to the compile/execute mode of the usual Forth.

Try it here
Source Code

Figure 1: Artistic Rendition of a Forth Interpreter

Words

When the enter key is pressed all words are pushed onto the input stack. All ASCII characters are valid for words, the space character is the delimiter. For example, the string:

: D* $ 3 & * 2 & ; : L3 D* -1 + $ 0 > ? L3 ; : FAC 1 2 & L3 1 # ; 20 FAC .
(A program which computes \(20!\) )

is fed from left to right into the Forth interpreter as shown in Figure 1. This Forth responds to 9 words in active mode and 1 word in passive mode.

When the Forth system is in Active mode it interprets the incoming words as described in the Active section. When it is in passive mode it does as described in the Passive section. Forth is always initialized to Active mode.

Active Words

In Active mode if a number is encountered it is pushed onto the data stack. If one of the following 9 words is encountered the effects described below will take place. If a word is encountered which matches the first word in a dictionary entry then the rest of the dictionary entry is copied onto the input stack.

1) . (PRINT) pops a number off the data stack and pushes it to the output.

2) + (ADD) pops two numbers off the data stack and pushes the sum back onto the data stack.

3) * (MULTIPLY) pops two numbers off the data stack and pushes the product onto the data stack.

4) ? (BRANCH) pops a number off the data stack, if it's 0 it drops the next input word.

5) > (COMPARE) pops two numbers off the data stack a,b and pushes \(a>b\) onto the data stack. 1 if true, 0 if false

6) & (FLIP) pops a number off the data stack, n, then cuts off the next n numbers from the data stack flips them around and reattaches them backwards.

7) # (DROP) pops a number off the data stack, n, and drops the next n numbers from the data stack.

8) $ (DUPLICATE) pops the top number off the data stack and pushes two identical copies back.

9) : (SWITCH TO PASSIVE) switches Forth into passive (copy) mode. Starts a new line on the dictionary stack.

Passive Words

There is only 1 passive word which is interpreted. All other words are copied into the current line of the dictionary stack without executing.

10) ; (SWITCH TO ACTIVE) Switches Forth back to active (execute) mode. Caps off the current dictionary entry.

Code Examples

A language is created by the new words copied during passive mode into the dictionary. The process of bootstrapping together a useful language occurs quickly. The following examples show off some of the capabilities of this arbitrary set of symbols.

Example 1: Postfix Arithmetic

Like in all Forths, numbers precede their operators.

2 4 + . 6  OK

Example 2: Function Definition

Usual Forth syntax for defining functions.

: PLUS1 1 + . ;  OK
1 PLUS1 2  OK
2 PLUS1 3  OK

Example 3: Fibonacci

: F0 $ -1 + FIB 2 & -2 + FIB + ;
: FIB $ 1 > ? F0 ;  OK
4 FIB . 3  OK
5 FIB . 5  OK
6 FIB . 8  OK
7 FIB . 13  OK
30 FIB . 832040  OK

Example 4: Factorial

: D* $ 3 & * 2 & ;
: L3 D* -1 + $ 0 > ? L3 ;
: ! 1 2 & L3 1 # . ;  OK
4 ! 24  OK
5 ! 120  OK
6 ! 720  OK
7 ! 5040  OK

Example 5: Multiplication

If the * word were removed could we define a MULT word to replace it? Easy!

: 4D+ 4 & 2 & $ 3 & + 4 & ;
: 2DUP 2 & $ 3 & $ 3 & 2 & ;
: L5 4D+ 1 + 2DUP > ? L5 ;
: MULT 0 3 & 0 4 & L5 3 # ;  OK
3 4 MULT . 12  OK
4 3 MULT . 12  OK
9 9 MULT . 81  OK
123 456 MULT . 56088  OK

Example 6: Collatz Sequence

$$ \begin{equation*} f(n) = \begin{cases} n/2 &\text{if} & n=0 \text{(mod 2)} \\ 3 \cdot n + 1 &\text{if} & n=1 \text{(mod 2)} \end{cases} \end{equation*} $$
: COL $ . $ 1 > ? L1 ;
: 2DIV .5 * COL ;
: 3NP1 3 * 1 + COL ;
: L1 $ ODD ? 2DIV $ 1 > ? 3NP1 ;

: ODD 2 + 2 L0 -1 + -1 * + ;
: L0 2 + 2DUP > ? L0 ;
: 2DUP 2 & $ 3 & $ 3 & 2 & ;  OK
  OK

27 COL 27 82 41 124 62 31 94 47 142 71 214 107 322 161 484 242 121 364 182 91 274 137 412
206 103 310 155 466 233 700 350 175 526 263 790 395 1186 593 1780 890 445 1336 668 334 167
502 251 754 377 1132 566 283 850 425 1276 638 319 958 479 1438 719 2158 1079 3238 1619 4858
2429 7288 3644 1822 911 2734 1367 4102 2051 6154 3077 9232 4616 2308 1154 577 1732 866 433
1300 650 325 976 488 244 122 61 184 92 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1  OK