BASIC
Part of Programming Fundamentals
BASIC is a simple, interpreted programming language designed for immediate usability, making it the ideal first high-level language for a rebuilding civilization.
Why This Matters
When you want a computer to be useful to people who are not specialists, you need a language that can be learned in an afternoon and used productively by the end of the day. BASIC — Beginner’s All-purpose Symbolic Instruction Code — was designed exactly for this purpose. Created at Dartmouth College in 1964, it became the lingua franca of personal computing in the 1970s and 1980s precisely because its syntax mirrors how a non-programmer might describe a problem.
For a civilization rebuilding computation, BASIC is the right first high-level language to implement. It is simple enough that a competent programmer can write a working BASIC interpreter in a few thousand lines of code. It is powerful enough to solve real problems — inventory management, agricultural calculations, record-keeping, basic engineering math. And it is immediately accessible: a farmer or medic with one week of training can write useful programs.
The historical record shows that BASIC implementations ran on 4 KB machines. You do not need sophisticated hardware to make BASIC productive.
The Structure of BASIC Programs
Classic BASIC programs consist of numbered lines. Every statement begins with a line number, which both identifies the line and determines execution order. Programs run from the lowest numbered line to the highest, unless a control flow statement redirects execution.
10 PRINT "HARVEST CALCULATOR"
20 INPUT "FIELD SIZE (HECTARES)"; H
30 INPUT "YIELD PER HECTARE (KG)"; Y
40 LET TOTAL = H * Y
50 PRINT "TOTAL HARVEST: "; TOTAL; " KG"
60 END
Line numbers traditionally increment by 10, leaving room to insert lines later (you can add line 25 between 20 and 30 without renumbering). This feels awkward compared to modern editors but was practical when programs were entered on keyboards and stored in RAM.
The BASIC interpreter stores the program as a list of lines sorted by line number. When you type RUN, it begins executing from the first line. When you type a line number followed by a statement, it inserts or replaces that line. When you type a number with no statement, it deletes that line. This edit-in-place model made early BASIC systems immediately understandable.
Core Statements
PRINT: Outputs text or values to the screen. PRINT "HELLO" outputs the literal string. PRINT X outputs the value of variable X. PRINT "VALUE: "; X outputs both. A semicolon suppresses the newline, letting you print multiple items on one line.
INPUT: Prompts the user and reads a value into a variable. INPUT X prints a question mark and waits for a number. INPUT "ENTER NAME: "; N$ displays a prompt and reads a string (note the dollar sign suffix for string variables).
LET: Assigns a value to a variable. LET X = 42 sets X to 42. LET X = X + 1 increments X. In many BASIC implementations, LET is optional — the interpreter infers assignment from the equals sign.
IF…THEN: Conditional execution. IF X > 10 THEN PRINT "BIG". In extended BASIC, IF…THEN…ELSE handles both branches.
GOTO: Unconditional jump to a line number. GOTO 100 continues execution at line 100. Goto is simple but leads to spaghetti code when overused. Use it sparingly, primarily for error handling and loop implementations.
GOSUB…RETURN: Subroutine call. GOSUB 500 jumps to line 500, runs until RETURN, then resumes after the GOSUB. This is BASIC’s mechanism for reusable code.
FOR…NEXT: Counted loop. FOR I = 1 TO 10: PRINT I: NEXT I prints 1 through 10. The optional STEP clause changes the increment: FOR I = 0 TO 1 STEP 0.1 counts in tenths.
DIM: Declares an array. DIM A(100) creates a 101-element array (indices 0 to 100). DIM NAMES$(20) creates a string array.
Variables and Types
Classic BASIC has two variable types: numeric and string. Numeric variables are floating-point by default — they handle both integers and decimals. String variables hold text and are identified by a dollar sign suffix: N$, ADDRESS$.
Variable names in many classic implementations are limited to one or two characters, a constraint from the era of tiny interpreters. Modern BASIC implementations allow full names. The practical difference is readability: TOTAL is clearer than T, and you should use descriptive names wherever your implementation permits.
Numeric variables are automatically initialized to zero. String variables are initialized to the empty string. This differs from assembly language where uninitialized memory contains unpredictable values — a genuine safety feature of higher-level languages.
Control Flow Patterns
BASIC programs become readable and maintainable when they follow clear control flow patterns:
The main loop: Most interactive programs run in an infinite loop until the user chooses to quit.
10 REM MAIN LOOP
20 GOSUB 1000 : REM show menu
30 GOSUB 2000 : REM get choice
40 IF CHOICE = 0 THEN END
50 GOSUB 3000 : REM process choice
60 GOTO 20
Input validation: Always validate user input before using it.
200 INPUT "ENTER 1-10: "; X
210 IF X < 1 OR X > 10 THEN PRINT "INVALID": GOTO 200
Subroutine organization: Keep each logical function in its own subroutine block, organized at well-known line numbers. Put the main program at lines 10-999, subroutines starting at 1000, 2000, 3000, etc. Comment each subroutine block with its purpose.
REM: The remark statement. Everything after REM on a line is a comment, ignored by the interpreter. Use REM liberally — BASIC code can become opaque without documentation.
Implementing a BASIC Interpreter
A BASIC interpreter has three main components:
The line store: A sorted list (or linked list) of program lines. Each line is a number plus a text string. The interpreter searches this list during GOTO, GOSUB, and FOR loops.
The lexer and parser: Convert a line of text into an executable form. The simplest approach stores lines as text and re-parses them on each execution — slow but simple. A tokenizer converts keywords to single-byte codes, speeding up execution significantly.
The evaluator: Executes each statement. Maintains a variable table (name-value pairs), a stack for GOSUB return addresses and FOR loop state, and the current line pointer.
A working BASIC interpreter for a Z80 or 6502 processor can be implemented in 4-8 KB of code. Microsoft’s early BASIC implementations fit in 4 KB. For a rebuilder with a working assembler and a month of programming time, a functional BASIC interpreter is a realistic goal.
Practical Applications
Agricultural calculations: Compute seed quantities, fertilizer rates, expected yields, storage requirements. A farmer who can write a 20-line BASIC program saves hours of mental arithmetic every season.
Medical dosing: Calculate drug doses by weight, track patient records, flag dangerous combinations.
Engineering: Structural load calculations, material quantities for construction, power consumption estimates for electrical systems.
Record keeping: Inventory management with simple file I/O (many BASIC implementations included cassette tape or disk access from the start).
Education: Teaching arithmetic, logic, and systematic thinking through programming. A student who learns to debug a BASIC program learns to think clearly about cause and effect.
Practical Notes for Rebuilders
Implement BASIC before any other high-level language. Its simplicity makes it achievable; its utility makes it worth the effort. Once BASIC exists, non-programmers can contribute to the computing infrastructure.
Document the exact syntax your implementation supports. Early BASIC had no standard, and dialects differed significantly. Write a reference card that fits on one printed page, listing every supported keyword with a brief example.
BASIC’s GOTO statement attracts criticism for encouraging undisciplined code, but for short programs solving specific problems, it is perfectly adequate. Save structured programming advocacy for the team that builds the next, more capable language on top of BASIC’s foundation.