FOCAL-69 was the landmark version of the FOCAL programming language, more widely publicized than the original version of the language created in 1968. FOCAL-69, created by Richard Merrill is important because:
- It was the basis for all later derivatives of the language (some of which branched off from one another)
- It was the language the classic BASIC game Hamurabi was first written in
- It became a popular language on Russian microcomputers.
Variable names may start with any letter except F (F is reserved for functions) and may contain any sequence of letters and numbers. However, only the first two characters are significant. For instance, the following code sample from FOCAL: A New Conversational Language refers to the same variable as DESTINATION and then DES:
01.80 ASK DESTINATION 02.30 IF (DES-14) 2.4,3.1,2.4
Any variable may be treated as an array, taking subscripts from -2048 through 2047.
FOCAL-69 contained only five mathematical operators:
- Addition (+)
- Subtraction (-)
- Multiplication (*)
- Division (/)
- Exponent (^) - the exponent is converted to an integer
FOCAL-69 was unusual in that mathematical expressions could use (),  and <> interchangeably in matched pairs to establish precedence.
The language did not support any relative operators (e.g., greater than, .GT., >, etc.).
The language contained the following built-in functions:
- FABS() - Absolute value
- FATN() - Arctangent
- FCOS() - Cosine of argument in radians
- FEXP() - Natural base to the power of the argument
- FITR() - Integer part of the argument
- FLOG() - Naperian log
- FRAN() - Random number
- FSGN() - Sign of the argument; FSGN(0)=1 in FOCAL-69, but FSGN(0)=0 in FOCAL-71 as well as later versions
- FSIN() - Sine of an angle given in radians
- FSQT() - Square root
Every line in a FOCAL-69 program must start with a line number. As with JOSS, and unlike BASIC, line numbers are real numbers. In FOCAL-69, integers are not allowed. Line numbers may range from 1.01 through 31.99. The whole number is referred to as a "group number", the group number (from 1 to 31) is used by the DO command. The editor also allows a programmer to print out all the statements in a group (e.g., WRITE 2) or delete a group (e.g., ERASE 2).
Multiple statements can be placed on a single line. Usually behavior is no different than if the statements had been on separate lines, except in the case of FOR loops.
The ASK command (abbreviation A) will take a list of strings and variables, echo the strings and store the user input in variables.
01.01 ASK "NAME", NAME 01.02 ASK "COORDINATES", X, Y 01.03 ASK "A1",A1,"OMEGA",W,"T0",T0,"DAMPING FACTOR",DAMPINGFACTOR
If the user doesn't enter a number but enters text, the system will convert the initial character to a unique number.
The COMMENT command (abbreviation C) creates a remark.
01.01 COMMENT: THE SUMER GAME, BY RICHARD MERRILL
The DO command (abbreviation D) branches execution to a subroutine; the subroutine is referenced either by group number or line number. Execution is resumed at the next statement once a RETURN is encountered.
01.15 DO 7.24 01.16 DO 8
The FOR command (abbreviation F) provides for a loop. When three arguments are specified, the first is the initial value of the loop variable; the second is the increment (assumed to be 1, if omitted), and the third value is the terminating value for the loop.
01.01 FOR X=1,10; TYPE X,! 01.02 FOR X=0,10,100; DO 2
A sample FOR loop:
01.10 ASK "HOW MUCH MONEY DO YOU WANT TO BORROW ?",PRINCIPAL 01.20 ASK "FOR HOW MANY YEARS ?",TERM 01.30 FOR RATE=4.0,.5,10;DO 2.0 01.40 QUIT 02.10 SET INTEREST=PRINCIPAL*(RATE/100)*TERM 02.20 TYPE "RATE",RATE," ","INTEREST",INTEREST,!
The GO command (abbreviation G) jumps program execution to the specified line number. From the editor, the GO command can also be used to start the program from the beginning (or from the specified line number).
01.05 GOTO 1.01 02.90 TYPE !!,"TRY AGAIN.",!!!!!;GOTO 1.1
The IF command (abbreviation I) provides a conditional branch based on the sign of the expression. After the numeric expression, the IF command can take one to three line numbers. If the expression is less than zero, execution branches to the first line number; if equal to zero, to the second line number; if greater than zero, to the third line number. The language lacked relative operators such as greater than, equal or less than. To branch if X > 5, one must compare X - 5.
02.20 IF (Y2-Y1) 2.4,2.3,2.4 03.01 IF (X) 3.1,3.02,3.1
The QUIT command (abbreviation Q) terminates execution of the program and returns control to the editing environment.
01.10 FOR X=-10,1,10;TYPE X 01.20 QUIT
The RETURN command (abbreviation R) branches execution from a subroutine back to the calling location. The following is a sample subroutine for converting a yes/no prompt into a value.
22.78 COMMENT: 'YES OR NO' SUBROUTINE 22.80 ASK "ANSWER YES OR NO ? ",AN 22.82 IF (AN-0YES)22.84,22.86 22.84 IF (AN-0NO)22.8,22.88,22.8 22.86 SET X=2;RETURN 22.88 SET X=1;RETURN
The SET command (abbreviation S) assigns the results of an expression to the specified variable.
01.30 SET PI=3.14156 01.60 SET INTEREST=PRINCIPAL*(RATE/100)*TERM
The TYPE command (abbreviation T) provides for output, displaying each in item in a series. If the item consists of an exclamation mark (!) or group of exclamation marks (!!!) each is output as a carriage return and line feed; if the item consists of a hash mark (#), it is output as a carriage return without a line feed.
TYPE [NUMBERS, E1, "TEXT", !, #, :, $ OR %] ...OUTPUT 01.10 TYPE "HI THERE, GOOD LOOKING. HOW MUCH MONEY DO YOU WANT TO BORROW?",! 01.50 TYPE "INTEREST",INTEREST,! 01.80 TYPE "THE INTEREST FOR",TERM," YEARS",!,"IS",INTEREST, " DOLLARS.",!! 01.90 TYPE "NEW YORK",!,"WASHINGTON",!,"ATLANTA",!,"DALLAS",! 02.10 TYPE "X",X," ","X^2",X^2," ","SQRT",FSQT(X) 03.20 TYPE ".",# 02.20 TYPE !!!!!
New lines are entered into the program by simply beginning the command with a line number. The editing commands were ERASE (abbreviation E), MODIFY (abbreviation M) and WRITE (abbreviation W):
- ERASE - zeroes out all variables
- ERASE <line number> - deletes the statement at the specified line
- ERASE <group number> - deletes all statements in the specified group
- ERASE ALL - deletes the entire program
- MODIFY <line number> - allows the programmer to edit the specified line
- WRITE <line number> - display the statement at the specified line
- WRITE <group number> - display all statements in the specified group
- WRITE ALL - display the specified program
The file command was OPEN (abbreviation O):
- OPEN INPUT [device:][file][,ECHO] - prepare to read from the start of a file
- OPEN OUTPUT [device:][file][,ECHO] - prepare to write from the start of a file
- OPEN RESTORE INPUT[,ECHO] - resume input
- OPEN RESTORE OUTPUT[,ECHO] - resume output
- OUTPUT CLOSE - output the buffer and close the file
Unusual for an interactive system of its size, FOCAL-69 supported the ability to chain programs and use library commands. Program names could be six characters long. The LIBRARY command (abbreviation L):
- LIBRARY DELETE [device:]<program name> - delete a program
- LIBRARY LIST [device:][file name] - catalog
- LIBRARY RUN [device:]<program name> [line number] - chain the program, optionally resuming at the specified line number
- LIBRARY SAVE [device:]<program name> - save the program
- LIBRARY EXIT - return to the PDP-8 monitor program
- LIBRARY CALL [device:]<program name> - load a program
- LIBRARY GOSUB [device:]<program name> [group number] - call a subroutine in an external program
Since the interpreter lacked sufficient memory space to store error messages, Richard Merrill used a work-around. FOCAL reported the address of the error-detecting code as a pseudo floating-point number. For example, the division by zero error was detected by code at address 4333 so the error message was: ?28.73 @ 01.10 (where 01.10 referred to the line number).
Code Meaning ?00.00 Manual start given from console. ?01.00 Interrupt from keyboard via CTRL/C. ?01.40 Illegal step or line number used. ?01.78 Group number is too large. ?01.96 Double periods found in a line number. ?01.:5 Line number is too large. ?01.;4 Group zero is an illegal line number. ?02.32 Nonexistent group referenced by 'DO'. ?02.52 Nonexistent line referenced by 'DO'. ?02.79 Storage was filled by push-down-list. ?03.05 Nonexistent line number used after 'GOTO' or 'IF'. ?03.28 Illegal command used. ?04.39 Left of "=" in error in 'FOR' or 'SET'. ?04.52 Excess right terminators encountered. ?04.60 Illegal terminator for 'FOR' command. ?04.:3 Missing argument in Display command. ?05.48 Bad argument to 'MODIFY' ?06.06 Illegal use of function number. ?06.54 Storage is filled by variables. ?07.22 Operator missing in expression or double 'E'. ?07.38 No operator used before parenthesis. ?07.:9 No argument given after function call. ?07.;6 Illegal function name or double operators. ?08.47 Parenthesis do not match. ?09.11 Bad argument to 'ERASE'. ?10.:5 Storage was filled by text. ?11.35 Input buffer has overflowed. ?20.34 Logarithm of zero requested. ?23.36 Literal number is too large. ?26.99 Exponent is too large or negative. ?28.73 Division by zero requested. ?30.05 Imaginary square root requested. ?31.<7 Illegal character, unavailable command, or unavailable function used.
Influence of JOSS
Merrill clearly derived FOCAL-69 from JOSS:
- FOCAL-69 borrows the JOSS innovation of requiring every line of the program to have a line number. (Prior to that, FORTRAN had optional line numbers.)
- FOCAL-69 line numbers, like JOSS line numbers and unlike Dartmouth BASIC line numbers, were real numbers rather than integers.
- The DO, SET and TYPE commands are simplified versions of the corresponding JOSS commands.
FOCAL-69 was a concise simplification of JOSS, with the simplicity required for the PDP-8, a minicomputer as opposed to the mainframe that JOSS was developed for.
- The syntax is less wordy (e.g., "DO PART 20" becomes "DO 20").
- The syntax is simpler (e.g., the JOSS statement "SET S=P, P=Q, Q=S" requires three statements in FOCAL-69: "SET S=P; SET P=Q; SET Q=S").
- Shorter words are substituted for longer commands, and command words are designed to each have a unique first letter. So JOSS "DEMAND" becomes FOCAL-69 "ASK" (abbreviation A, as D would collide with DO) and JOSS "STOP" becomes "QUIT" (as "SET" was in use).
- IF statements may not be appended to other statements.
- FOCAL-69 had only a single built-in looping keyword ("FOR" as opposed to "WHILE").
- Some early (non-standard) MUMPS implementations took ideas from FOCAL before the ANSI Standardization of MUMPS.