Inhaltsverzeichnis

The Evolution of FORTH, an Unusual Language

(In this 1980 article from Byte, Chuck Moore recounts the creation of Forth.)

Principles and goals of language design

By Charles H. Moore

When I invented FORTH … my goal was simply to make myself a more productive programmer. When I first worked with computers at MIT and Stanford in the early 1960s, I figured that in 40 years, a very good programmer could write forty programs. And I wanted to write more programs than that. There were things out in the world to be done, and I wanted a tool to help me do them. As I worked on programs that ranged from satellite orbits to chromatography to business systems, I developed FORTH in line with my overall goal. For several years now, I have been able to work at ten times my original rate.

As I began thinking of rather drastic improvements to programs, I think I was arrogant. I wanted to do things my way. I was not convinced that I should not be permitted to, and I was a bit hard to get along with. The arrogance was necessary because I felt insecure. I was promoting ideas that everyone said were wrong and that I thought were right. But, if I were right, that meant that all the other people would have been wrong, and there were many more of them than me. And it took a lot of arrogance to persist in the face of massive disinterest.

FORTH is a polarizing concept. There are people who love it and people who hate it. It's just like religion and politics. If you want to start an argument, say, „Boy, FORTH's really a great language.“

This is partly because FORTH is an amplifier. A good programmer can do a fantastic job with FORTH; a bad programmer can do a disastrous job. I have seen very bad FORTH code and have been unable to explain to the author exactly why it was bad. There are some visible characteristics of good FORTH, such as very short definitions (many of them). Bad FORTH often takes the form of one definition per block-big, long, and dense. It is quite apparent, but difficult to explain, why or how a FORTH program is bad.

BASIC and FORTRAN are less sensitive to the quality of the programmer. I was a good FORTRAN programmer; I thought that I was doing the best job possible with FORTRAN, but it was not much better than what everybody else was doing. In this sense, FORTH is an elitist language.

On the other hand, I think that FORTH is a language that a grade school child can learn to use quite effectively, if it is presented in bite-size pieces with the proper motivation.

FORTH is the first language that has come up from the grass roots. It is the first language that has been honed against the rock of experience before being standardized. I hesitate to say it is perfect; I will say that if you take anything away from FORTH, it is not FORTH any longer—the basic components are all essential to the viability of the language.

History

What might be called the prehistory of the FORTH language goes back much further than 10 years. The first element of FORTH to exist was the text interpreter, shown [here] in Listing 1.

Listing 1: An early version of the FORTH text interpreter (written in ALGOL).

IF ATOM ="DRIFT" THEN DRIFT
ELSE IF ATOM="QUAD" THEN QUAD
ELSE IF ATOM ="BEND" THEN BEND
ELSE IF ATOM ="FACE" THEN FACE(-I)
ELSE IF ATOM ="ROTATE" THEN ROTATE
ELSE IF ATOM="SOLENO" THEN SOLENOID
ELSE IF ATOM ="SEX" THEN SEX
ELSE IF ATOM ="ACC" THEN ACC
ELSE IF ATOM="MATRIX" THEN BEGIN IF NOT FITTING THEN BEGIN 
REAL A;
WRITEl(3,0,0,CORE[S]); LINE( -(8+42 x (ORDER -1ª);
FOR J-1 STEP 1 UNTIL 600 BEGIN
FOR K-1 STEP 1 UNTIL 600 WRITEl(2,8,R1(J,K]xUNIT[K]/UNIT(J],2); LINE(0) END;
IF ORDER = 2 THEN FOR C-1 STEP 1 UNTIL 6 DO BEGIN

This early version, programmed in ALGOL at the Stanford Linear Accelerator Center in the early 1960s, was part of a program called TRANSPORT, which designed electron-beam transport systems. Besides the text interpreter, this printout also shows an early version of the dictionary. The influence of LISP is evident in the indivisible entity {which in FORTH is called a word) named ATOM. As the interpreter reads a word from a punched card, it executes the associated routine, as for DRIFT in this example. The style resembles that of modern FORTH: there is no limit on the length of a word, as you can see by the length of the word SOLENOID, but only the first characters are significant and words are separated by spaces.

Other very early concepts have either changed in form or have evolved dramatically. In Listing 2, the word that has become { : } {colon) in modern FORTH is called DEFINE, while END has become { ; } (semicolon).

Listing 2: An early version of the FORTH words { : } (called DEFINE here) and { ; } (called END here).

"_" OPEN DEFINE MINUS + END ,
SEAL "< "OPEN DEFINE -< END BREAK
"NOT "OPEN DEFINE MINUS 1+ END
"> "OPEN DEFINE .< END
"AND "OPEN DEFINE x END
"OR "OPEN DEFINE NOT .NOT AND NOT END
"T 1 1 "REAL DECLARE
"= " OPEN DEFINE T- ; DUP T< .T> OR NOT END
"( " OPEN DEFINE = NOT END
"( "OPEN DEFINE > NOT END
"( "OPEN DEFINE < NOT END
"DUMP "OPEN DEFINE NAME 10 "ALPHA WRITE; 3 10 "REAL WRITE 0 LINE END''

This liming also shows stack operators being defined. As an example of a concept that has evolved, consider the dictionary being sealed by the word SEAL and broken by the word BREAK. Such sealing and breaking has since been replaced by the idea of vocabularies.

Listing 3 shows another prototype in ALGOL, this time of a FORTH text editor. Here ATOM has become W and I am looking up plus, minus, and the commands T, R, A, and I, to edit a deck program.

Listing 3: Another prototype of the FORTH text editor, again in ALGOL.

In this listing, the word ATOM (the predecessor of the basic unit in FORTH, the word) has been replaced by the word W.

120 CYCLE; FILL OUTPUT WITH BUFFER[1),BUFFER[2);
1 WHILE WORD NEQ "END " DO
2 IF W=GMI THEN REPLY("OK ")
3 ELSE IF NUMERIC THEN L: = MIN(W -1,$OF)
4 ELSE IF W="+ " THEN L:=MIN(L+WORD,EOF)
5 ELSE IF W="- " THEN L:=MAX(L-WORD,O)
6 ELSE IF W="T " THEN BEGIN
7 IF WORD=GMI THEN W:=1; W:=MIN(L+W-1,EOF);
8 FOR L: = L STEP 1 UNTIL W DO BEGIN
9 POSITION; TYPE END; L:=L-1 END
130 ELSE IF W="R " THEN BEGIN
1 POSITION; REPLACE END
2 ELSE IF W = " A " THEN BEGIN
3 L:=EOF:=EOF+1; REPLACE END
4 ELSE IF W="I " OR W="D " THEN BEGIN
5 IF NOT RECOPY THEN BEGIN
6 RECOPY: =TRUE; REWIND(CARD) END;
7 POSITION; IF W="I " THEN BEGIN
8 PLACE; REPLACE END
9 ELSE BEGIN EMPTY: =TRUE; IF WORD NEQ GMI THEN BEGIN 
140 L:=MIN(L+W-I,EOF); SPACE(CARD,L-LO+I); 10:=1+1
1 END END END

Another method of implementing a dictionary is shown in Listing 4. I am I looking up the words in a conditional statement and setting NEXT, the key routine of modern FORTH's address interpreter, to the index .

Listing 4: An early version of the FORTH dictionary.

8 PROCEDURE RELEVANCE; BEGIN REAL T ,KO;
9 J: =0; I: = -1; WHILE WORD NEQ "END " DO 
180 IFW="= "THENNEXT:=3
1 ELSE IF W="GT " THEN NEXT: =4
2 ELSE IF W="LT " THEN NEXT: =5
3 ELSE IF W = "NOT " THEN NEXT: = 6
4 ELSE IF W="AND " THEN NEXT:=7
5 ELSE IF W="OR " THEN NEXT: =8
6 ELSE IF W="+ " THEN NEXT: =9
7 ELSE IF W="- " THEN NEXT: = 10
8 ELSE IF W="* " THEN NEXT: = 11
9 ELSE IF W="/ " THEN NEXT: = 12
190 ELSE IF KO: =SEARCHl(W) GEQ 0 THEN BEGIN I NEXT:=I; NEXT:=K:=KO END
2 ELSE BEGIN
3 NEXT: =2;
4 IF BASE[K] = " " THEN NEXT: = WORDS[0]
5 ELSE NEXT: =W END;
6 NEXT: =0 END;

Listing 5 shows an early implementation of a stack. Since it is written in BALGOL, which allows assignment I statements inside other statements,) could replace STACK(J) with (J+l1 in order to push items onto the stack. I did this so that I could manipulate parameters that were interpreted from the card deck as arguments to the routines. When I wanted, for instance, to convert angular measure from one unit to another, this added the ability to use arithmetic operators.

Listing 5: An early implementation of the FORTH stack, written in BALGOL.

7 BOOLEAN PROCEDURE RELEV ANT; BEGIN
8 I: =J: = -1; STACK[0]: = 1; DO CASE NEXT OF BEGIN
9 J: = -1;
210 STACK[J: =J+ I]: =CONTENT;
1 STACK[J:=J+1]:=NEXT;
2 STACK[J: =J-1]: =REAL(STACK[J] =STACK[J + 1]);
3 STACK[J:=J-1]:=REAL(STACK[J] GTR STACK[J+1);
4 STACK[J:=J-1]:=REAL(STACK[J] LSS STACK[J+1]);
5 STACK[J]: =REAL(NOT BOOLEAN(STACK[J]);
6 STACK[J: =J-1]: =REAL(BOOLEAN(STACK[J]) AND BOOLEAN(STACK[J+1]); 
7 STACK[J: =J-1]: =REAL(BOOLEAN(STACK[J]) OR BOOLEAN(STACK[J+1]);
8 STACK[J:=J-1]:=STACK[J]+STACK[J+1];
9 STACK[J: =J-1]: =STACK[J]-STACK[J + 1];
220 STACK[J: =J-1]: =STACK[J] xSTACK[J + 1];
1 STACK[J: =J -1]: =STACK[J]/STACK[J + I];
2 END UNTIL J LSS 0;
3 RELEVANT: =BOOLEAN(STACK[0]) END;

From Stanford I moved to the East Coast, where I programmed on a free-lance basis for several years. Some of you probably remember that, in the 1960s, a programmer at a typical computer center needed to I learn about nineteen languages in order to function adequately: JCL (Job Control Language); languages to control utilities and facilities, such as the linking loader; assembly language and the assembler's control language; plus several high-level languages and the methods for controlling their compilers.

Listing 6 shows two of these languages, a PL/1 program and the JCL necessary to run it. Note the obvious difference in syntaxes. FORTH developed in response to such conditions. In terms of modern FORTH, the importance of this example lies in the use of NEXT as a procedure that goes off to get the next word and do something with it.

Listing 6: The NEXT procedure in PL/I and its associated ICL (Job Control Language) statements (lines 1 thru 8).

1 // UTILITY JOB SYSTEM,OVERHEAD
2 // EXEC PGM=IEBUPDTE,PARM=NEW
3 // SYSPRINT DD SYSOUT = A
4 // SYSUT2 DD DSNAME=OUTLIB,UNIT=2314,DISP=(NEW,KEEP),
5 // VOLUME=SER=MOORE,SPACE=(TRK,(100,,10)),
6 // DCB=(RECFM=F,RECL=80,BLKSIZE=80)
7 //SYSIN DD DATA
8 ./ ADD NAME=WORD,LEVEL=00,SOURCE=O,LIST=ALL
9 DECLARE KEYBOARD STREAM INPUT,PRINTER STREAM OUTPUT PRINT;
10 NEXT: PROCEDURE CHARACTER(4);
1 DECLARE (1 TEXT CHARACTER(81) INITIAL((81)" "),
2 2 C(81) CHARACTER(1), I INITlAL(81), W CHARACTER(4),
3 WORD CHARACTER(32) VARYING BASED(P),P,NUMERIC BIT(1)) EXTERNAL; 4 DO WHILE C(I)=" "; I=I+1;
5 IF 1=82 THEN BEGIN; I= 1;
6 READ FILE(KEYBOARD) INTO(TEXT); END; END;
7 P=ADDR(C(I);
8 IF C(I)="-" OR C(I)="." OR "0" LE C(I) THEN BEGIN; NUMERIC="1"B;
9 IF C(I) NOT = "." THEN DO I = I + 1 BY 1 WHILE "0" LE C(I); END;
20 IF C(I) = "0" THEN DO I = I + 1 BY 1 WHILE "0" LE C(I); END; END;
1 ELSE DO; NUMERIC = "0"B;
2 IF "A" LE C(I) THEN DO 1=1+1 BY 1 WHILE "A" LE C(I) OR C(I)="-";
3 END; ELSE I=1+ 1; END;
4 W = WORD; RETURN(W);

Listing 7 shows a version of FORTH coded for the IBM System/360 with the routines PUSH and POP, which executed in about 15 (s. They include stack limit checking, which doubled the cost and was one of the things that led me to believe that execution-time stack checking is not desirable. This was coded in a macroassembler that did not have stack operations, which led to the deck full of statements like L19 DC AL2(*-L18), which gave me a link have the foggiest notion of what to do from L19 to the previous label. It worked but it was not pleasant.

Listing 7: The FORTH words PUSH and POP written in IBM 360 assembly language.

0056 830 LI8 DC AL2(* -LI7) 
831 NAME 3,X'445550',0 DUP  
03445550 832 + DC ALI(3)'X'445550' 
00 833 + DC X'O' 
834 + ORG *-2- VO 
835 + DS OH 
836 + ORG *+ V0+ I 
400004 837 + DC ALI(0*X'40'+X'40'),AL2(4) 
5AC0 C000 00014 838 PUSH A SP,MFOUR COSTS 15 US 
5040 C000 00000 839 ST T ,0(,SP) 
19CB 840 CR SP,DP 
0729B 841 BCR 2,NEXT BHR 
47FO 667C 0067C 842 B ABORT 
00IA 843 L19 DC AL2(* -L18)
0444D2CF50400008 844 DC ALI(4),X'44D2CF50',X'40',AL2(8) D 
41CO C004 00004 845 LA SP,4(,SP) 
5840 C004 00004 846 POP L T ,4(,SP) COSTS 21 US
41CO C004 00004 847 LA SP ,4(,SP) 
59CO 602C 0002C 848 C SP,SPOO 
07C9 849 BCR 12,NEXT BNHR
47F0667C 0067C 850 B ABORT 

Listing 8 shows a similar routine, called { ;: } (semicolon-colon), this time coded in COBOL. I am setting up a table of identified words had to do what { ;CODE} did, and At Mohasco I also worked directly that will be interpreted from an input stream. Since COBOL does not allow parameters for subroutines, it is awkward to do anything meaningful.

Listing 8: A structured table routine, in COBOL.

1 MOVE "CONFIGURATION" TO IDENTIFY(4); MOVE "DATA" TO IDENTIFY(5);
2 MOVE "FILE" TO IDENTIFY(6);
3 MOVE "FD" TO IDENTIFY(7);
4 MOVE "MD" TO IDENTIFY(8);
5 MOVE "SD" TO IDENTIFY(9);
6 MOVE "WORKING-STORAGE" TO IDENTIFYI MOVE "CONSTANT" TO IDENTIFY(11);
7 MOVE "PROCEDURE" TO IDENTIFY(12); MOVE "INPUT -OUTPUT" TO IDENTIFY(13);

New Concepts

About this time, I began to think of defining a word that would define other words; and at that time, this idea was staggering. For example, { ;CODE} was a very esoteric word. I explained it to people, but I could not express the potential I thought it had. It took time to find out exactly what { ;CODE} should do (it specified the code to be executed for a previously defined word). I do not have the records, but I think the initial code for { ;CODE} was three or four lines long; to simplify that code was one of the driving forces behind the address interpreter—to make it possible to code cleanly. This had implications as to what registers should be available.

The fact that W should be saved in a register for defining words led to indirect, rather than direct, threaded code. That was the most complicated concept I had coded in this evolving program—probably deserving of a patent in its own right.

A little bit later, it seemed that there ought to be an analog of { ;CODE} that specified the code to be interpreted when you executed a word. It seemed the natural balance, but when the idea first arose, I did not have the foggiest notion of what to do or what the implementation should be. The first definition of this analog, called { ;: } (semicolon-colon), had to do what { ;CODE} did, and then more.

Out of that came the distinction between compile-time action and execute-time action. It was convenient for words to be coded to act this way, but it was expensive. It required not only the address of the code to be executed, but the address of the code to be interpreted so you could something useful.

Late in the 1960s I went to work for Mohasco Industries, where I put something strongly resembling FORTH on a Burroughs 5500, cross-compiled to the 5500 from an IBM 1130. (There is no assembler on the 5500; there is a dialect of ALGOL called SBOL that Burroughs used to compile operating systems, not available to users. ) Listing 9 shows the code definitions of stack operations on the 5500, which was a stack-oriented processor at a time when stack machines were not popular. The names of some FORTH stack operators stem from that machine's operations; see, for example, DUP. The symbol ¢ stands for CODE and distinguishes the assembler's OR from the FORTH OR. (Vocabularies were not yet available.)

Listing 9: Code definitions of FORTH stack operations on the Burroughs 5500, written in SBOL.

LIST
0001 ( 'PRIMITIVES' 26 LAST = 30 SIZE=)
0002 ¢ = _S RETURN
0003 ¢ @ 
0004 ¢ + V 241, RETURN
0005
0006 ¢ OR ¢OR RETURN
0007 ¢ AND ¢AND RETURN
0008 ¢ NOT 115, RETURN
0009 ¢ DUP ¢DUP RETURN
000A ¢ SWAP ¢SWAP RETURN 
000B ¢ DROP ¢DROP RETURN 
000C ¢ + +1 RETURN
000D ¢ - -1 RETURN
000E ¢ MINUS ¢MINUS RETURN 
000F ¢ * *1 RETURN
0010 ¢ / /1 RETURN
0011 ¢ MOD ¢MOD RETURN

Listing 10 gives an example of FIND (a dictionary search routine) coded for the 5500. Notice the word SCRAMBLE, a colon definition making a hashed search. Apparently I had eight threads to the dictionary here, a concept we added back to FORTH when we developed polyFORTH last year.

Listing 10: A dictionary search routine, FIND, written for the Burroughs 5500.

0013 ¢SM ¢FIND SCRAMBLE < SD ~DUP
0014 41 >A 41 >B ¢BEGIN V 
0015 ¢BEGIN VO 
0016 1 
0017 ¢THEN -ADDR ¢DUP I 
0018 OS'WORD 
0019 V1 _U OS RESULT
001A ¢THEN ¢DUP < SD ¢BACK
001B ¢THEN GET ¢BACK
oo1c : FIND TOP ¢FIND ¢IF UR < UD ¢B ¢THEN;

FORTH and the IBM 1130

At Mohasco I also worked directly on an IBM 1130 interfaced with IBM 2250 graphics display. The 1130 was a very important computer; had the first cartridge disk, as we1l a card reader, a card punch backup for the disk), and a console typewriter. The 1130 let the progra,mer, for the first time, totally control the computer interactively.

FORTH first appeared as an entity on that 1130. It was call F-O-R-T-H, a five-letter abbreviation of „FOURTH,“ standing for „fourth-generation computer language.“ That was the day, you may remember, of third-generation computers and I was going to leapfrog. But because FORTH ran on the 1130 (which permitted only five-character identifiers), the name was shortened.

What came out of the 1130 was cross-assembler that assembled the instructions, which were then to be executed by the 2250. I think the 2250 had its own memory, and these things had to be programmed carefully. What I accomplished was that the 1130 in FORTRAN in 32 K bytes could draw pictures on the 2250, fairly slowly; and FORTH, in 8 K bytes, could draw three-dimensional moving pictures on the 2250—but it could do that only if every cycle was accounted for and if the utmost was squeezed out. That is why FORTRAN had to go—I required an assembler and could not do an impressive enough job with FOTRAN.

But high-Ievel or colon definitions were not yet compiled—the compil :cme much later. The text was stored in the body of the definition, and the text interpreter reinterpreted the text in order to discover what it was to do. This contradicts the efficiency of the language, but I had big words that put up pictures and I did not have to interpret too much. The cleverness was limited to squeezing out extraneous blanks as a compression medium. I am told that this is the way that BASIC acts today in many instances.

This machine had a disk drive, an I am almost certain that the word BLOCK existed in order to access records off the disk. I do remember that I had use the FORTRAN I/O (input/output) package and that it would not put the blocks where I wanted them; it put the blocks where it wanted them, and I had to pick them up and move them into my buffers.

At Mohasco I also implemented FORTH on a Univac 1108, interfacing it with their COBOL compiler. Listing 11 displays a set of record descriptions in a Dun and Bradstreet reference file (for looking up bad debts). The layout shows named fields followed by the number of bytes allocated.

Listing 11: ProtDtype of a file layout. running under FORTH on a Univac 1108. This version of FORTH was written in COBOL.

3 DBI DBI/MOORE 33 33
4 DUNS 8 NAME 24 STREET 19 CITY 15 STATE 4 ZIP 5
5 PHONE 10 BORN 3 PRODUCT 19 OFFICER 24 SIC 4 SICI 4 SIC2 4
6 SIC3 4 SIC4 4 SIC5 4 TOTAL 5.0 EMPL 5.0 WORTH 9.0 
7 SUBS 1 HDQ 1 HEAD 8 PARENT 8 MAIL 19 CITY1 15 STATE1 4
8 NAME1 19
9 END

The Mohasco programs mark the transition point between something that could be called FORTH and something that could not. All the essential features except the compiler were present by 1968.

The First Modern FORTHs

The first modern FORTH was coded in FORTRAN. Shortly thereafter it was recoded in assembler. Much later it was coded in FORTH. It took a long time before I thought that FORTH was complete enough to code itself. The first thing to be added to what had already existed was the return stack. That was an important development; the recognition that there had to be exactly two stacks, no more, no less.

The next thing to be added was even more important—the full-fledged dictionary, that is, the dictionary in the form of a linked list. Up until then, flags had been set or computed GOTOs had been executed to provide some mechanism for associating a subroutine with a word. The replacement of all that by a code file containing the address of the routine made an incredibly fast way of implementing a word once it was identified.

The first use of modern FORTH occurred when it was written for a Honeywell H316 at the NRAO (National Radio Astronomy Observatory). In 1971 I was hired by George Conant to write a radio-telescope data-acquisition program: that led to the next step, the compiler. This meant the recognition that, rather than reinterpret a string of text, words could be compiled and an average of 5 characters per word could be replaced by 2 bytes per word. This gave a compression factor of 2 or 3, not drastic but appreciable. But execution speed would be much faster. Again I asked myself, as I had done when I first began modifying programs: if it was that easy, why hadn't anyone else done it? It took me a long time to convince myself that you could compile anything and everything.

Interrupts came around this time. It was important to utilize the interrupt capability of the computer, but it had not been done by me before that-I did not know anything about interrupts. I/O, however, was not yet interrupt-driven. Interrupts were available for the application if it wanted them-FORTH did not bother. The multiprogrammer came along a couple of years later when we developed an improved version of the system for NRAO's telescope at Kitt Peak. This computer was a PDP-ll; the multiprogrammer had four tasks. Input was still not interrupt-driven, which was unfortunate.

The Second FORTH Programmer

Ten years ago there was one FORTH programmer, me. The second FORTH programmer, Elizabeth Rather, came along in 1971. That is quite a quantum jump, from one to two; the next step was four {the next two came out of Kitt Peak National Observatory); the growth can be traced from there to the several thousand today. The first FORTH user was Ned Conklin, head of the NRAO station at Kitt Peak, Arizona. NRAO runs a millimeter-wave radio telescope that is in great demand by observers, in part because it is responsible over the last 10 years for discovering half of the interstellar molecules that are known to exist. FORTH is still running on that telescope at Kitt Peak and on a lot of other telescopes.

Given interest from other astronomers, a few believers split off from NRAO in 1973 and formed FORTH Inc. We were deluged by requests for FORTH systems from astronomers and went into business to try to exploit that market. It would still be our principal line of business today except that there are so few new telescopes in the world that you cannot support a company on that market.

We developed miniFORTHTM (FORTH on minicomputers) with the idea of having a programming tool. An important implementation of the tool came when we put an LSI-11 and FORTH into a suitcase. I think I became the first computer-aided programmer-computer-aided in that I had my computer and took it around with me. I talked to my computer, my computer talked to your computer, and we could communicate much more efficiently than I could communicate directly with your computer before it could run FORTH. Using this tool, we have put FORTH on many computers.

We added the feature of interrupt-driven I/O when FORTH Inc produced its first multiterminal system. It did not speed things up particularly from the user's point of view, but it did prevent any loss of characters when several people were typing at the same time. You did not have to look quickly to get the character before the next one came along. They were all buffered and waiting for you, which is an important distinction for multiprogrammed systems.

Database management came along at this time. It has been extensively changed, just as FORTH has. But fundamentally, nothing has changed. The concept of files, records, fields, and relational pointers that polyFORTHTM offers dates back from 1974 or so—years and years ago. Listing 12 shows a recent application of the FORTH Inc database management system.

Listing 12: Field and record layouts for a recent FORTH Inc database management system.

64 LIST

0 ( GLOSSARY FILE)
1 2 ( LINK) 12 BYTES WORD 12 BYTES VOC
2 NUMBER SOURCE NUMBER STACKS 70 BYTES PHRASE
3 210 FILLER ( 4 LINES) 32 FILLER ( 340 B/R. 3/BLOCK) DROP 
4 2 24 BYTES WORD + VOC DROP

With microFORTHTM in 1976 came the first version of our current target compilers. They are very complex things, much more so than I expected them to be. At about the same time, we worked out the current implementation of DOES>.

This new form of { ;: } does not require the address of the code to be interpreted. Since that is supplied by a different mechanism, the parameter can occupy the parameter field as it is supposed to. You can „tick“ it and change its value, which is nice. [The FORTH word { ' } (called „tick“ above) places the address of the word that follows it onto the stack. GW] But we save 2 bytes for every DOES> word, 2 bytes for very common words—and for 3 years, we did not realize that we had missed the optimum by so much.

I know no way of speeding this process from initial thought to development, except to let a certain amount of time pass. We could sit, we did sit and debate this thing endlessly, and we missed the obvious. I think that completes the capabilities that I think of as FORTH today. You see how they dribbled in—at no point did I sit down to design a programming language. I solved the problems as they arose. When demands for improved performance came along, I would sit and worry and come up with a way of providing improved performance.

polyFORTH is a condensation of everything that we at FORTH Inc have learned in the last 10 years of developing FORTH. I think it is a very good package. I foresee no fundamental changes in the design of the language except for accommodation to FORTH standards, which are becoming increasingly important.

Implementations of FORTH

I would like to review the implementations of FORTH of which I am aware. It is actually a tour through the history of computers and it is fascinating that this could all have happened in 10 years.

FORTH has been programmed in FORTRAN, ALGOL, PL/I, COBOL, assembler, and FORTH; and I am sure some of you can come up with other languages with the same history My list is strictly personal.

FORTH has been implemented on the Burroughs 5500; the IBM 1130; the Univac 1108; the Honeywell 316; the IBM 360; the Data General Nova; the HP 2100 (not by me but by Paul Scott at Kitt Peak); the PDP-10 and PDP-11 (by Marty Ewing at the California Institute of Technology); the PDP-l1 (by FORTH Inc); the Varian 620; the Mod-Comp II; the GA SPC-16; the CDC-6400 (by Kitt Peak); the PDP-8; the IV-Phase; the Computer Automation LSI-4; the RCA 1802; the Honeywell Level 6; the IBM Series 1; the Interdata; the 6800; the 8080; the 8086; the TI-9900; and soon the 68000, the 28000, the 6809, and a Child Inc computer. Some independent groups have 65025, ILLIAC, and others running FORTH. I raise the question—is it the case that FORTH has been put on machine can and must be exploited. You do not need any particular number of registers or stacks or anything. All can be simulated, but if you neglect the abilities of the machine, you can end up a factor of 2 down in performance from where you might otherwise be.

FORTH-in-Hardware Computers

The first FORTH computer I know of was built at Jodrell Bank in England around 1973. It is a redesign of an English Ferranti computer that went out of production. The observatory at Jodrell Bank was going to build their own bit-slice version; they discovered FORTH about the same time, modified the instruction set to accommodate FORTH, and built what I am told is a very fast FORTH computer. I have never seen it, but have talked to its competent designer, John Davies, who is one of the early FORTH enthusiasts.

In 1973, before Dean Sanderson came to FORTH Inc to develop microFORTH, he had a FORTH computer at a company called General Logic. It qualifies as a FORTH computer because it has a FORTH instruction. And there is a story there. Dean showed me his instruction set, and there was this funny instruction that I could not see any reason for—I figured it was some kind of no-op or catchall or something; it had the weirdest properties, and it could not possibly be useful. It was NEXT. It was a one-instruction NEXT which was beautiful. And it was a very simple modification (this was a bit-slice computer) to the instruction set—a few wires here and there—and that is the first time I saw a FORTH computer, if you will. I call it a FORTH computer because it had the ability to change itself from an ordinary computer into a FORTH computer.

I think that hardware today is in the same shape as software was 20 years ago. No offense, but it is time that the hardware people learned something about software. There is an order or two of magnitude improvement in performance possible with existing technology. We do not need picosecond computers to make really substantial improvements in execution speed. Faced with that realization, there is no point in trying to optimize the software any further until we have taken the first crack at the hardware. The hardware redesign has to be as complete as the software redesign was. The standard microprocessors did not have FORTH in mind. Those minicomputers that can be microprogrammed cannot be microprogrammed well enough to even be worth doing. The improvements available are much greater than you can achieve by these half measures.

I have built a small FORTH computer. The design changes as fast as the chips can be plugged into the board. But it is not difficult to do. Here are the characteristics of a FORTH computer:

It does not need a lot of memory (16 K bytes is about right-half programmable read-only memory, half user programmable memory, maybe). It does not need a lot of I/O ports; in fact, it does not need any I/O ports except for the application requirements. A serial line and interface to a disk drive are useful but not required.

We have put FORTH on an 8080-based machine with a virtual disk in memory, enough memory to hold eight blocks. The system is quite viable and has no particular problem with system crashes. Bubble memories are coming. A FORTH computer does not need much mass storage; 100 K bytes are adequate, and 250 K bytes are plenty. The fact that FORTH can exist quite happily on a machine that is very small by contemporary standards should be exploited.

Organizations

Finally, I would like to run through the history of the organizations that have been involved with FORTH. They have formed another thread of the tapestry. It began with Mohasco, of course, followed by NRAO and Kitt Peak National Observatory: then came FORTH Inc.

The next step was probably DECUS (Digital Equipment Computer Users' Group). Marty Ewing gave his' PDP-ll FORTH system to DECUS. FORTH Inc was not sure whether free FORTHs floating around was a good idea at the time. But it turned out that a lot of people were exposed to FORTH who otherwise would not have been. Cybek came along and provided an entry into the business-systems market. Art Gravina, the president of Cybek, is the person who designed our database management system. He provided us the opportunity to do commercial systems and the ability to handle ten times as many terminals as he could with the BASIC program that preceded it. In about 1976, a committee of the International Astronomical Union met and adopted FORTH as a standard language. That was a boost in the world of astronomy, although the world of astronomy was no longer the major driving force in the popularity of FORTH.

I think EFUG (the European FORTH Users' Group) came along about that time (1976). It turned out to our surprise that Europe was a hotbed of FORTH activity that we were largely unaware of (and perhaps still are, in that we are not involved in that world and do not appreciate the level of interest). An international FORTH Standards Team probably grew from their first meetings. A couple of years later, the FORTH Interest Group started. Now we have FORML—FORTH Modification Laboratory, an idea-generating organization.

Conclusion

The tendency seems to be for people to organize themselves in groups. Some of these groups are companies, others are associations. It looks like FORTH is going to be a communal activity in that sense—that it will grow from the work of unstructured clusterings of like-minded people. The suggestion is that this whole world of FORTH is going to be quite disorganized, uncentralized, and uncontrollable. It's not bad, perhaps it's good.

My view of the future is more unsettled today than it has been for years: promising, confusing, perplexing. The implications are perhaps as staggering now as they were 20 years ago. The promise of realization is much higher. My original goal was to write more than forty programs in my life. I think I have increased my throughput by a factor of 10. I do not think that that throughput is program-language limited any longer. So I have accomplished what I set out to do: I have a tool that is very effective in my hands. It seems it is very effective in others' hands as well. I am happy and proud that this is true.