Jump to content

FOCAL (programming language)

From Alfawiki
FOCAL
Company typeProgramming language
IndustryComputer software
Founded1968
FounderRichard Merrill
ProductsFOCAL-8, FOCAL-11, FOCAL-69, FOCAL-71
ParentDigital Equipment Corporation (DEC)

FOCAL (an acronym for Formulating On-line Calculations in Algebraic Language or alternatively FOrmula CALculator) is an interactive, interpreted programming language derived from JOSS. It was mainly utilized on Digital Equipment Corporation (DEC) PDP series computers.

Created with an emphasis on simplicity, FOCAL shares many similarities with JOSS but deliberately excludes complex features such as ranges and user-defined functions. This streamlining facilitated easier parsing and lowered memory consumption—an essential consideration for memory-constrained platforms like the PDP-8. Additionally, the language’s keywords were assigned unique initial letters, allowing commands to be abbreviated to single characters, which further conserved memory resources.

FOCAL implementations, including FOCAL-8, incorporated integrated line editors, interpreters, and input/output routines, operating on PDP-5, PDP-8, and PDP-12 systems. The variant known as FOCAL-11 targeted the PDP-11 and utilized the RT-11 operating system to provide file handling and editing capabilities. The language underwent updates through versions such as FOCAL-69 and FOCAL-71, and was also adapted for the Intel 8080 processor.

Significantly, early video games like Hamurabi and Lunar Lander were initially created in FOCAL before being ported to BASIC, which helped increase their visibility. Although FOCAL's popularity diminished with the advent of the VAX-11, it found renewed use in the Soviet Union on PDP-11 clones employed in academic settings and personal computing (BK series).

JOSS

JOSS debuted in May 1963 on the unique JOHNNIAC computer at RAND Corporation. Its adoption expanded rapidly; however, JOHNNIAC—constructed in 1953—soon reached operational limits. After its retirement in 1966, JOSS was reimplemented on a newly acquired PDP-6, DEC’s first large-scale system. By 1970, the language supported between 500 and 600 users nationwide and spurred developments such as portable computer terminals for immediate access.

JOSS played a pivotal role during the rise of time-sharing. Unlike typical time-sharing operating systems that concentrated on managing user accounts and files, JOSS uniquely integrated file editing within its programming environment, enhancing interactive computing. RAND extensively promoted this system throughout the industry.

FOCAL

The PDP-6 represented DEC’s initial foray into mainframe computing, enabling JOSS to utilize its advanced processing power and ample memory. Nevertheless, most DEC machines lacked sufficient resources to run JOSS effectively. To address this limitation, Richard Merrill developed FOCAL by simplifying JOSS’s feature set to fit within the constrained memory of the PDP-8 and other 12-bit DEC models. One such simplification involved restricting conditionals to branch instructions only, unlike JOSS’s more versatile conditional expressions, thereby reducing temporary data needed during parsing.

FOCAL also restructured its command vocabulary so each keyword began with a distinct letter. This design allowed the parser to interpret commands based solely on their initial character, which minimized both parsing complexity and source code length since users could enter just one letter instead of full keywords.

The inaugural version of FOCAL appeared in 1968 for the PDP-8, followed by an improved FOCAL-69 release in 1969. These versions were collectively termed FOCAL-8 when adapted to other 12-bit platforms such as the PDP-5 and PDP-12. Due to its efficient use of limited memory—often only a few kilobytes of RAM—FOCAL gained considerable popularity. A related variant named FOCAL-11 operated on the PDP-11 running under the RT-11 operating system.

Processor Technology provided an 8k version of FOCAL bundled with Lunar Lander for the Intel 8080-powered Altair 8800, distributing source code at no cost with purchases while charging solely for tape duplication.

BASIC

Although FOCAL gained traction on DEC hardware, BASIC became the favored choice on many other systems. By the late 1960s, competitors such as the HP 2100 series, equipped with HP Time-Shared BASIC, began to challenge DEC’s stronghold in the minicomputer market by offering time-sharing BASIC environments.

David H. Ahl, who joined DEC’s PDP-8 Group during its educational initiatives, encountered difficulties promoting FOCAL despite its advantages, primarily because BASIC was already widely adopted and supported by extensive software collections from organizations like the Minnesota Educational Computing Consortium. Ahl noted that DEC’s decision not to license FOCAL restricted its dissemination, unlike BASIC, which was licensed broadly by firms including GE, Honeywell, and HP.

To overcome this limitation, Ahl commissioned a BASIC interpreter for the 4 kWord PDP-8, which eventually led to DEC marketing bundled PDP-8 systems combined with terminals and BASIC under the "EduSystem" brand. Larger EduSystem configurations featured enhanced versions of BASIC and occasionally included FOCAL and FORTRAN. EduSystems were also developed for the PDP-11 platform.

Ahl adapted significant FOCAL programs into BASIC, such as The Sumer Game (originally titled Hamurabi) and a version of Lunar Lander, supplemented by externally submitted software. This initiative culminated in DEC releasing 101 BASIC Computer Games in 1973, achieving commercial success with multiple editions printed through 1975.

By the mid-1970s, BASIC had become the standard language across all DEC machines, leading to a decline in FOCAL usage.

Rebirth in the Soviet Union

During the 1970s, the Soviet Union produced clones of the PDP-11 for military applications. In the 1980s, single-chip derivatives resembling the LSI-11 gave rise to PDP-11 compatible home computer models, notably the Electronika BK series introduced in 1985. Early versions utilized FOCAL on ROM cartridges with BASIC available as an optional addition; later models made BASIC the default programming language.

Language

The following overview is based on FOCAL-69 as described in the FOCAL-8 language reference guide.

Direct and indirect modes

FOCAL followed the JOSS paradigm by providing a command line interface where commands could be executed instantly in "direct mode" or stored within a program when prefixed by a line number. New lines with unique numbers add code; lines with duplicate numbers replace existing ones. This is similar to BASIC’s immediate versus program mode but differs from JOSS, where all commands—whether program or direct—are retained in memory. Unlike JOSS, FOCAL did not support saving commands without line numbers; such instructions were handled as options attached to program-mode commands like .

Program statements

In FOCAL, each program line begins with a fixed-point line number consisting of two two-digit integers separated by a period, ranging from 1.01 to 31.99 in FOCAL-8. When displayed using (analogous to BASIC’s ), leading zeros are added so that all line numbers align to five characters (for example, 1.10 is printed as ). However, references to line numbers do not require these leading zeros (for instance ).

The number before the decimal point is called the "group number," which organizes code segments and enables subroutines to be invoked via (e.g., jumps execution to group 5). Editing commands also operate based on groups—for example, lists group 2 and deletes group 4.

Each line must start with a command keyword; unlike BASIC, there is no implicit default command such as optional . Multiple statements can be placed on a single line separated by semicolons; these generally act like separate lines except when used inside FOR loops.

ASK

The ASK command (shortened to A) requests input from users by displaying prompts and saving their responses into variables, functioning similarly to BASIC's INPUT statement.

01.01 ASK "NAME", NAME  
01.02 ASK "COORDINATES", X, Y  
01.03 ASK "A1", A1, "OMEGA", W, "T0", T0, "DAMPING FACTOR", DAMPINGFACTOR

When a non-numeric character is entered, the system converts the first letter into a numerical value, where "A" corresponds to 1, "B" to 2, and so forth.

COMMENT

The COMMENT command (abbreviated C) inserts remarks within the code, serving the same purpose as BASIC's REM. The original documentation indicates that an empty COMMENT line is synonymous with a blank line but does not alter program behavior.

01.01 COMMENT: THE SUMER GAME, BY RICHARD MERRILL

DO

The DO command (abbreviated D) directs program flow to a subroutine, analogous to BASIC's GOSUB. Subroutines can be specified either by group or line number. Providing a line number causes execution of that single line followed by an automatic return; omitting the line number initiates execution at the subroutine block’s first line and continues through its end. An optional RETURN statement may be used for early exit but is not mandatory at the block conclusion.

01.15 DO 7.24  
01.16 DO 8

FOR

The FOR command (abbreviated F) implements a for loop structure. When three parameters are given, they represent the starting value, step increment, and ending value; if only two are specified, the increment defaults to one. This syntax aligns with FORTRAN's style rather than BASIC's. Unlike other language constructs where multiple commands on a single line execute independently, all statements following a FOR on the same line run before looping or proceeding to the next line. Loops must be contained within one line or utilize subroutines via DO, as there is no equivalent to BASIC's multi-line loop blocks.

01.01 FOR X=1,10; TYPE X,!  
01.02 FOR X=0,10,100; DO 2  

Example of a 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,!

GOTO

The GOTO command (abbreviated G) transfers control directly to a specified line number, functioning identically to BASIC’s GOTO. In FOCAL, this command also initiates execution at that line similar to BASIC’s RUN, although this usage is referred to as GO in documentation despite being the same instruction.

01.05 GOTO 1.01  
02.90 TYPE !!,"TRY AGAIN.",!!!!!; GOTO 1.1

IF

The IF command (abbreviated I) enables conditional branching based on the sign of an evaluated expression. It accepts one to three target line numbers: if the expression is negative, control jumps to the first; if zero, to the second; and if positive, to the third. This language does not support relational operators like greater-than-or-equal-to directly; instead, comparisons must be performed via subtraction (e.g., testing if X > 5 requires evaluating X - 5).

02.20 IF (25-25) 2.4,2.3,2.4  
03.01 IF (X) 3.1,3.02,3.1

Abbreviated forms allow placing a semicolon or end-of-line immediately after the first target line number:

02.20 IF (X)1.8; TYPE "Q"  
02.30 IF (X)1.8,2.50  
02.40 TYPE "P"  

In these examples: at line 2.20, if negative it jumps to line 1.8; otherwise it continues and outputs "Q." At line 2.30 it branches to either line 1.8 or 2.5 if negative or zero respectively; otherwise it proceeds to print "P."

QUIT

The QUIT command (shortened to Q) halts program execution and returns control back to the editing interface. It functions similarly to BASIC's END or STOP commands. Example usage:

01.10 FOR X=-10,1,10;TYPE X  
01.20 QUIT  

RETURN

The RETURN command (abbreviated as R) exits a subroutine and resumes execution at the point where the subroutine was invoked. Including RETURN at the end of a subroutine is optional, as control automatically returns after the final line. Below is an example subroutine that converts a yes/no response into a numeric 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  

SET

The SET command (abbreviated S) assigns the outcome of an expression to a variable, analogous to BASIC's LET. Examples include:

01.30 SET PI=3.14156  
01.60 SET INTEREST=PRINCIPAL*(RATE/100)*TERM  

TYPE

The TYPE command (abbreviated T) displays one or multiple items separated by commas, comparable to BASIC's PRINT. Items can be variables, string literals enclosed in double quotes, or control characters such as ! (carriage return and line feed), # (carriage return), and : (tab). These elements may be combined; for instance, typing multiple ! characters outputs several CR/LFs consecutively.

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 !!!!!  

An optional format specifier % can be used with TYPE, where x indicates digits before the decimal and yz digits after it; if omitted, the default is %8.4 (eight digits total with four decimals). Examples:

SET A=67823  
TYPE %6.01,A  
=  67823.0  
TYPE %5,A  
= 67823  
TYPE %8.03,A  
=   67823.000  
TYPE %,A  
= 6.7823E4  

Output is right-padded with spaces to match the specified width; using only % formats the number in scientific notation.

A special control character $, when used with TYPE, prints a table listing all defined variables along with their values, showing only the first two letters of each variable name padded with zeros if necessary. Array elements appear on separate lines identifying their indices:

TYPE $  
A0(00)=67823  

Variables

Variable identifiers must begin with any letter except F (which is reserved for functions), and may include letters and digits thereafter. Only the initial two characters are significant internally; thus DESTINATION and DES both refer to the variable DE:

01.80 ASK DESTINATION  
02.30 IF (DES-14) 2.4,3.1,2.4  

Variables can also be indexed as arrays with subscripts ranging from -2048 to 2047.

Math

FOCAL supports five arithmetic operators:

  • ^ for exponentiation (converted internally to a 12-bit integer)
  • * for multiplication
  • / for division
  • + for addition
  • - for subtraction

In the original 1968 edition, operator precedence was distinct: exponentiation had highest priority, followed by multiplication and division equally, then addition and subtraction—but notably addition and subtraction did not share equal precedence themselves. For example, the expression 2-3+1 evaluated as 2-(3+1) = -2 rather than the more common left-to-right evaluation yielding zero—this discrepancy could lead to errors when porting FOCAL code to other languages.

Later versions FOCAL-69 and FOCAL-71 adjusted this behavior so that addition and subtraction have equal precedence, causing expressions like the above to evaluate as expected.

Uniquely, FOCAL allowed parentheses (), square brackets [], and angle brackets <> interchangeably in matched pairs to define evaluation order within expressions; for instance:

  01.30 SET A=<10*[5+1]*(1+5)>  

This expression evaluates from left to right at equal precedence levels resulting in a value of 360.

Built-in mathematical functions encompass:

  • ABS — absolute value
  • ATAN — arctangent
  • COS — cosine (in radians)
  • EXP — exponential function e^x
  • INT — integer part of a number
  • LOG — natural logarithm (base e)
  • RND — random number generator
  • SGN — sign function (implementation varies by version)
  • SIN — sine (in radians)
  • SQRT — square root

Character functions

FOCAL-71 introduced two routines for handling single-character input and output, resembling the ASK command but providing ASCII codes:

  • waits for a key press and returns the corresponding ASCII code
  • sends an ASCII code as a character to the console or file output

Additional functions

FOCAL featured specialized functions including:

  • accessing PDP-8 analog-to-digital converter channels for input
  • plotting at a defined Y-axis coordinate
  • plotting at a defined X-axis coordinate

Program execution

Programs are initiated using (often shortened to ), which serves a role similar to BASIC’s . Execution can also begin at a specified line number.

Editing operations

New lines are inserted by specifying a line number. Editing commands consist of ERASE (E), MODIFY (M), and WRITE (W):

  • ERASE – clears all variables or removes lines, groups, or entire programs (e.g., ERASE line number, ERASE ALL)
  • MODIFY line number – changes the content of a particular line
  • WRITE line/group number or WRITE ALL – outputs program code listings

File management

The file command (O) controls file input/output operations:

  • – opens a file for reading from the beginning
  • – opens a file for writing from the start
  • and – resume reading or writing respectively
  • – flushes buffers and closes the file

Library management

FOCAL provided the LIBRARY command (L) to manage collections of programs, facilitating program chaining and subroutine invocation:

  • LIBRARY DELETE [device:]program – removes a specified program
  • LIBRARY LIST [device:][file] – displays the directory listing
  • LIBRARY RUN [device:]program [line] – executes a program, optionally starting at a particular line
  • LIBRARY SAVE [device:]program – stores a program to device
  • LIBRARY EXIT – returns control to the PDP-8 monitor

Enhancements in FOCAL-71 included:

  • LIBRARY CALL [device:]program – loads an external program into memory
  • LIBRARY GOSUB [device:]program [group] – invokes an external subroutine group

Error reporting

Due to limited memory available for error messages or lookup tables, FOCAL indicated errors by outputting the address of the error-checking routine as a fixed-point numeric value. For example, division by zero was displayed as , where 28.73 denotes the memory page and offset of the error code, and 01.10 specifies the line number. Since PDP-8 pages contained 128 bytes, this corresponds to memory location 3657.

Version differences

DEC released three FOCAL iterations for the PDP-8: the original FOCAL, FOCAL,1969, and FOCAL,1971. While FOCAL,1969 remained largely consistent with the original version, FOCAL,1971 introduced substantial enhancements such as file handling capabilities, improved mathematical routines, and additional features. Unlike earlier standalone implementations, FOCAL,1971 operated integrated with the nascent OS/8 (then PS/8), utilizing it for file and editing operations.

FOCAL,1971 specifics

The 1971 release incorporated a 10-digit precision math package. The function was modified to return zero when given zero input (previously it returned one). The random number generator () was updated with an improved algorithm producing more evenly distributed results. New functions included , which converts strings into their ASCII numeric equivalents (comparable to BASIC’s ), and , which transforms numbers into ASCII characters (). To accommodate memory limits, upon startup FOCAL,1971 required users to select which features to enable.

Comparison with JOSS

FOCAL can be viewed as a more concise iteration of JOSS, featuring a simplified syntax designed for easier interpretation. Most commands in FOCAL have direct counterparts in JOSS, though they vary slightly in detail. Unlike JOSS, which is case-insensitive and uses mixed-case keywords requiring statements to end with periods, FOCAL mandates uppercase only and does not enforce line-ending punctuation.

A significant distinction lies in JOSS’s extensive comparison operations and boolean logic capabilities within and constructs, enabling conditional execution of virtually any statement. Conversely, FOCAL’s approach to branching and looping mimics straightforward goto-like behavior without explicit value comparisons. For instance:

 1.10 Type A if X>10.
 1.20 Type i for i=1(1)10.

These lines in JOSS conditionally print or iterate over values; their FOCAL equivalents are:

1.10 IF (X-10),,1.30
1.20 TYPE A!
1.30 FOR I=1,1,10;TYPE I,!

JOSS simplifies common loops by allowing flexible ranges but at the cost of increased runtime overhead due to repeated expression evaluation each cycle. FOCAL enhances efficiency by storing loop parameters within memory structures.

To achieve brevity, FOCAL shortened certain commands: JOSS's became , and was abbreviated to , freeing up letters for additional keywords like .

Some JOSS features were eliminated from FOCAL to streamline parsing. For example, multi-variable assignments such as had to be divided into individual statements in FOCAL: . Additionally, JOSS’s command was consolidated into FOCAL’s with formatting handled via .

Comparison with BASIC

Comparisons between FOCAL and BASIC were frequent since both languages were prevalent on minicomputers during the same period and shared similar syntactical frameworks. In many cases, code written in one could be translated directly into the other. For example, prompting user input in FOCAL is done with:

 ASK "What is your age?",AGE

while BASIC accomplishes this through:


Despite slight syntactic variations and some missing features unique to each language, their overall structure remains comparable.

A notable difference is BASIC's statement, which permits any statement following , resembling JOSS-style control flows. BASIC places the condition at the beginning (), whereas JOSS appends it at the end (). FOCAL’s functioned similarly to BASIC's computed goto, , but limited jump targets strictly to three options (negative, zero, positive), unlike BASIC’s more flexible list of destinations.

Another important divergence is FOCAL’s absence of native support for strings as assignable variables. Like early versions of BASIC and FORTRAN prior to string enhancements, literal strings were only used within input/output commands. This limitation complicated manipulation of individual characters or strings within programs.

Because string variables were unavailable, FOCAL converted typed characters into their numeric character codes during input. For example, entering transformed 'H' into "8" (its six-bit PDP-8 code), causing subsequent letters to be misread as exponent expressions and producing invalid numeric results. To manage text input, programmers typically relied on single-character responses (e.g., "Do you need instructions, Y or N") and compared numeric codes against expected values.

By prefixing zero, strings could be coerced into numeric form, allowing conditional tests such as to branch if A equaled "BROWN." However, inputs containing the character 'E' risked overflow errors—thus permitting checks for "BROWN" or "RED" but not for "GREEN" or "YELLOW."

FOCAL’s PDP-8 version employed a floating-point format spanning four 12-bit words (totaling 48 bits), allocating 36 bits for the mantissa and 12 for the exponent. This provided superior precision and a broader numeric range compared to most contemporaries, making FOCAL well-suited for advanced numerical computations. Its precision combined with default decimal formatting reduced binary-to-decimal rounding errors common in early interpreters. In contrast, Microsoft BASIC initially used a 32-bit format later extended to 40 bits; many BASIC implementations exhibited rounding inaccuracies that caused minor residuals in simple calculations.

Overall, FOCAL proved more efficient in resource usage than comparable BASIC interpreters. On typical systems equipped with 6 to 24 kilobytes of magnetic-core memory, FOCAL enabled larger and more sophisticated programming projects than BASIC could support.

Versions and Derivatives

The Coca-Cola Company developed a tailored variant of FOCAL known as COKE.

FOCAL was adapted for use on several DEC systems, including the PDP-7, PDP-9, PDP-10, PDP-11, PDP-12, PDP-5, and LINC-8. Its documentation provided instructions for extending the command parser, allowing numerous installations to implement custom commands suited to specific hardware configurations.

The Digital Equipment Computer Users' Society (DECUS) amassed a wide array of patches and improvements. Among the significant branches was FOCAL-W, which introduced enhancements such as advanced mass storage file input/output and virtual memory support for variables.

During the mid-1970s, the more sophisticated DELTA language emerged as an offshoot of FOCAL. It featured expanded capabilities including extended program line numbering and commands designed specifically for Tektronix 4010/14 graphics terminals.

In Russia, FOCAL continued to be utilized into the early 1990s on Electronika BK series home computers.

Microsoft distributed a version of FOCAL via paper tape; however, the original master tape has been lost, and this interpreter is no longer accessible.

Sample Program

The classic Lunar Lander program demonstrates the strengths of FOCAL. It is organized into several subroutines—a typical structure in both FOCAL and JOSS—enabled by its line numbering system. The code comprises nine routines: the first group handles printing instructions and initializing variables; the second group contains the central game loop; while groups three through nine manage computations and control logic.

Important variables include (current mass) and (empty mass), with remaining fuel calculated as . The user provides input for burn rate , which must fall between 8 and 200 pounds per second. Input validation loops ensure only acceptable values are entered.

A timer variable governs ten-second intervals for updating status information. Fuel usage and altitude checks dictate transitions between different subroutines. Group five displays game results and offers options to restart or exit.

This well-organized modular approach showcases FOCAL’s effectiveness in interactive programming with clear control structures and robust user input management.

See also

  • JOSS, the Rand Corporation language that inspired FOCAL
  • MUMPS, a data manipulation language influenced by concepts from JOSS and FOCAL

Bibliography

External links