"It is much easier for most people to write an English statement than it is to use symbols." — Grace Hopper, 1952
Part of The Ian Index (coming soon) — Preserving computing history. pip install ian-flowmatic
FLOW-MATIC was the first English-like programming language, developed by Grace Hopper and her team at Remington Rand from 1955-1959. It ran on the UNIVAC I and UNIVAC II computers and was the direct ancestor of COBOL.
This implementation faithfully recreates FLOW-MATIC's syntax and semantics based on the original U1518 FLOW-MATIC Programming System manual (1958).
pip install ian-flowmatic# Run a program
flowmatic examples/invoice_generator.flowmatic
# Run all demos
flowmatic --demo
# List available examples
flowmatic --list
# Or use Python directly
python -c "from flowmatic import run_file; run_file('program.flowmatic')"| Program | Description |
|---|---|
invoice_generator.flowmatic |
Generates invoices by matching orders with product catalog |
payroll.flowmatic |
Calculates employee pay with overtime and deductions |
inventory_reorder.flowmatic |
Checks stock levels and generates purchase orders |
set_operation_demo.flowmatic |
Demonstrates runtime flow modification (feature COBOL killed!) |
xi_sections_demo.flowmatic |
Shows X-I machine code sections (another lost feature) |
block_integrity.flowmatic |
Language-level data integrity checking |
(0) INPUT INVENTORY FILE-A PRICE-LIST FILE-B ;
OUTPUT INVOICE FILE-C ;
HSP D .
INPUT- Define input files with single-letter aliasesOUTPUT- Define output filesHSP- High-Speed Printer output
Each operation is numbered and contains statements:
(1) READ-ITEM A ;
IF END OF DATA GO TO OPERATION 10 .
(2) COMPARE PRODUCT-NO (A) WITH PRODUCT-NO (B) ;
IF EQUAL GO TO OPERATION 4 ;
IF LESS GO TO OPERATION 3 ;
OTHERWISE GO TO OPERATION 5 .
| Statement | Description |
|---|---|
READ-ITEM A |
Read next record from file A |
WRITE-ITEM C |
Write current record to file C |
PRINT-ITEM D |
Print to high-speed printer |
TRANSFER A TO C |
Copy entire record from A to C |
MOVE value TO field (C) |
Move value to a field |
COMPARE field (A) WITH field (B) |
Compare two fields |
IF EQUAL GO TO OPERATION n |
Conditional jump |
IF GREATER GO TO OPERATION n |
Conditional jump |
IF LESS GO TO OPERATION n |
Conditional jump |
OTHERWISE GO TO OPERATION n |
Default branch |
JUMP TO OPERATION n |
Unconditional jump |
IF END OF DATA GO TO OPERATION n |
End-of-file check |
MULTIPLY a BY b GIVING c |
Multiplication |
ADD a TO b |
Addition |
SUBTRACT a FROM b |
Subtraction |
DIVIDE a BY b GIVING c |
Division |
SET OPERATION n TO GO TO OPERATION m |
Runtime flow modification! |
TEST field AGAINST value |
Test a field value |
EXECUTE OPERATION n [THROUGH m] |
Subroutine call! (from U1518) |
REWIND A |
Rewind file for multi-pass (from U1518) |
CLOSE-OUT FILES C |
Close output files |
STOP |
End program |
FLOW-MATIC:
SET OPERATION 9 TO GO TO OPERATION 2
This one English sentence changes where operation 9 jumps to at runtime.
Modern equivalent requires:
- Interface definition
- Concrete strategy classes
- Context class
- Factory or dependency injection
COBOL had ALTER which did something similar, but it was deprecated and removed.
FLOW-MATIC allowed embedding machine code for performance-critical sections:
* In original FLOW-MATIC:
X-I A000 ; Load from input area
X-I M010 ; Multiply instruction
X-I W000 ; Store to working storage
The relative addressing (A000, W000, M000) kept code portable between UNIVAC models.
COBOL removed this to achieve "machine independence" — creating a 39-year gap before FFI/JNI/ctypes reinvented the concept in 1996.
FLOW-MATIC:
COMPARE PRODUCT-NO (A) WITH PRODUCT-NO (B)
TRANSFER A TO C
COBOL:
COMPARE PRODUCT-NUMBER OF INVENTORY-MASTER-FILE
WITH PRODUCT-NUMBER OF PRICE-LIST-FILE
MOVE CORRESPONDING INVENTORY-MASTER-RECORD
TO OUTPUT-INVOICE-RECORD
18 FLOW-MATIC operations became 50+ COBOL statements.
From U1518 page 92: "Performs designated operation or sequence of operations."
(5) EXECUTE OPERATION 10 THROUGH OPERATION 12 .
This runs operations 10-12 as a subroutine, then returns to operation 6! A primitive but effective subroutine mechanism in 1958.
From U1518 page 97: "Rewinds current reel of an input file."
(4) REWIND A .
(5) READ-ITEM A ; ...
This resets file A to the beginning, allowing multi-pass algorithms.
FLOW-MATIC file definitions included:
BLK CT IND 000000000001 ; Enable block counting
BLK CT LOC 000000000001 ; Where count stored
END REEL SEN ; End-of-reel sentinel
END FILE SEN ; End-of-file sentinel
The language verified your data automatically. We now need external checksums, database transaction logs, and ETL validation code.
- 1955: Grace Hopper begins development of FLOW-MATIC
- 1957: FLOW-MATIC operational on UNIVAC I
- 1958: U1518 manual published
- 1959: CODASYL committee formed (includes Hopper)
- 1960: COBOL released, based heavily on FLOW-MATIC
- 1960+: FLOW-MATIC features gradually dropped from COBOL
flowmatic/
├── README.md # This file
├── flowmatic_parser.py # FLOW-MATIC interpreter (recursive descent)
├── run_flowmatic.py # Command-line runner
├── demo.py # Quick demonstration
├── play_21.py # Interactive UNIVAC 21 card game
├── src/
│ ├── flowmatic.gram # Formal BNF grammar
│ └── ast_nodes.py # AST node classes
├── tests/
│ ├── run_tests.py # Test runner
│ ├── 01_simple_transfer.flowmatic
│ ├── 02_arithmetic.flowmatic
│ ├── 03_compare_match.flowmatic
│ └── 04_set_operation.flowmatic
└── examples/
├── invoice_generator.flowmatic
├── payroll.flowmatic
├── inventory_reorder.flowmatic
├── set_operation_demo.flowmatic
├── xi_sections_demo.flowmatic
├── block_integrity.flowmatic
└── univac_21.flowmatic # Card game in authentic FLOW-MATIC
# Run all tests
python tests/run_tests.py
# Run with verbose output
python tests/run_tests.py --verbose
# Run specific test
python tests/run_tests.py 01The formal grammar is defined in src/flowmatic.gram. Key production rules:
Program ::= Operation0 { Operation }
Operation ::= '(' NUMBER ')' StatementList '.'
Statement ::= ReadItem | WriteItem | Compare | IfCondition | Jump | Transfer | ...
FieldRef ::= IDENTIFIER '(' LETTER ')'
The interpreter uses a recursive descent parser, following the same pattern as the Plankalkül implementation in this repository. Each statement type has a corresponding regex pattern that matches the statement and extracts its components.
FLOW-MATIC uses a memory-changing model where:
- Files are read into current records indexed by single-letter aliases (A, B, C...)
- Statements modify these records in place
- Records are written back to output files
The SET OPERATION feature stores modified jump targets in operation_targets dict.
When a JUMP/GO TO executes, it checks if the current operation has an override target.
This is how FLOW-MATIC achieved runtime polymorphism without objects or functions!
- U1518 FLOW-MATIC Programming System (1958), Remington Rand UNIVAC
- "The Education of a Computer" - Grace Hopper (1952)
- COBOL-60 Report (1960)
Part of the Ian index and Hopper project - Preserving Grace Hopper's Legacy.
"The most dangerous words in the language: 'We have always done it this way.'" — Grace Hopper