Files
gw-basic-2026/docs/language-reference.md
Eremey Valetov e7f35c21ff Implement binary SAVE/LOAD, INKEY$ extended keys, golden tests, update to v0.10.0
Binary SAVE/LOAD: SAVE now writes tokenized binary by default (0xFF header
format), matching original GW-BASIC behavior. SAVE "file",A for ASCII.
LOAD auto-detects binary vs ASCII from the first byte. Command-line file
loading also auto-detects, so binary .BAS files just work.

INKEY$ extended keys: arrow keys, Home/End/PgUp/PgDn, Insert/Delete, and
F1-F10 now return the correct CHR$(0) + scan_code two-byte sequences per
the IBM PC convention. Refactored event trap key parsing to use tui_read_key()
instead of duplicating escape sequence parsing.

Golden-file regression tests: generated .expected output files for 55 of 58
test programs (3 timing-dependent tests excluded). The test runner now
reports compat match status alongside pass/fail.

Classic programs: added Hamurabi, Lunar Lander, Gunner, and Diamond from
David Ahl's BASIC Computer Games (1978) in tests/classic/ for manual
compatibility testing.

Docs updated with compiler roadmap item and hardware I/O simulator plan.
2026-03-01 12:25:47 -05:00

7.9 KiB
Raw Blame History

Language Reference

Data Types

Type Suffix Description
INTEGER % 16-bit signed
SINGLE ! 32-bit float
DOUBLE # 64-bit float
STRING $ Up to 255 bytes

Operators

+, -, *, /, ^, \ (integer div), MOD, AND, OR, XOR, EQV, IMP, NOT, <, =, >, <=, >=, <>

Numeric Functions

SGN, INT, ABS, SQR, SIN, COS, TAN, ATN, LOG, EXP, RND, FIX, CINT, CSNG, CDBL

RND can be called with or without parentheses: RND is equivalent to RND(1).

String Functions

LEN, ASC, CHR$, VAL, STR$, LEFT$, RIGHT$, MID$, SPACE$, STRING$, HEX$, OCT$, INSTR, INPUT$

File Functions

EOF, LOC, LOF

Pseudo-variables

ERL, ERR, CSRLIN, INKEY$, DATE$, TIME$, TIMER, POS(0)

Literals

Decimal, &H hex, &O octal, D exponent (double), E exponent (single), type suffixes (%, !, #)

Statements

Category Statements
Output PRINT, LPRINT, LLIST, PRINT USING, WRITE, CLS
Variables LET, DIM, ERASE, SWAP, DEFINT, DEFSNG, DEFDBL, DEFSTR
Control flow GOTO, GOSUB/RETURN, FOR/NEXT, IF/THEN/ELSE, WHILE/WEND, ON...GOTO, ON...GOSUB
Input INPUT, LINE INPUT, DATA/READ/RESTORE, INKEY$
Program control RUN, RUN "file", CONT, STOP, END, NEW, LIST, CLEAR, AUTO, RENUM, DELETE, EDIT
Sequential I/O OPEN, CLOSE, PRINT#, WRITE#, INPUT#, LINE INPUT#
Random-access I/O FIELD, LSET, RSET, PUT, GET, CVI/CVS/CVD, MKI$/MKS$/MKD$
Program I/O SAVE (binary/ASCII), LOAD (auto-detects), MERGE, CHAIN, COMMON
Event trapping ON TIMER(n) GOSUB, TIMER ON/OFF/STOP, ON KEY(n) GOSUB, KEY(n) ON/OFF/STOP
Error handling ON ERROR GOTO, RESUME, RESUME NEXT, RESUME n, ERROR, ERR, ERL
User functions DEF FN, RANDOMIZE
File management KILL, NAME, FILES, MKDIR, RMDIR, CHDIR, SHELL
Date/time DATE$, TIME$, TIMER
Screen LOCATE, COLOR, WIDTH, SCREEN, KEY ON/OFF/LIST, KEY n,"string"
Graphics PSET, PRESET, LINE, CIRCLE, DRAW, PAINT
Sound SOUND, BEEP, PLAY (MML parser, PulseAudio backend)
Misc POKE, KEY, TRON/TROFF, OPTION BASE, MID$ assignment
System SYSTEM

Program I/O (SAVE / LOAD)

SAVE writes the current program to a file. The default format is tokenized binary (compact, fast to load), matching the original GW-BASIC behavior:

SAVE "myprog.bas"       ' tokenized binary (default)
SAVE "myprog.bas",A     ' ASCII text (human-readable, editable)

LOAD reads a program file, auto-detecting the format from the first byte:

LOAD "myprog.bas"       ' auto-detects binary or ASCII
LOAD "myprog.bas",R     ' load and run immediately

Binary files use the standard GW-BASIC 0xFF header format. Command-line loading (./gwbasic file.bas) also auto-detects format.

MERGE loads an ASCII file without clearing the current program, overlaying lines by number. CHAIN loads and runs a new program, optionally preserving variables listed by COMMON.

INKEY$ Extended Keys

INKEY$ returns a zero-length string when no key is available, a one-byte string for regular ASCII keys, or a two-byte string for extended keys:

K$ = INKEY$
IF LEN(K$) = 2 THEN scan = ASC(MID$(K$, 2, 1))

Extended keys return CHR$(0) as the first byte and the IBM PC scan code as the second. Common scan codes:

Key Scan Key Scan
F1-F10 59-68 Home 71
Up 72 PgUp 73
Left 75 Right 77
End 79 Down 80
PgDn 81 Ins 82
Del 83

Printer Output (LPRINT / LLIST)

LPRINT works identically to PRINT but sends output to the printer:

  • Default: output is appended to LPT1.TXT in the current directory
  • --lpt /dev/lp0 (Linux) or --lpt LPT1 (FreeDOS): send to real hardware
  • --lpt report.txt: redirect to a custom file

LLIST lists the program to the printer, with optional line number ranges (LLIST, LLIST 10-50, LLIST -100).

Both support PRINT USING, semicolons, commas, TAB(), and SPC().

Graphics

Graphics mode is activated with SCREEN 1 (320x200, 4 colors) or SCREEN 2 (640x200, monochrome). Drawing commands render to an internal framebuffer and output via Sixel graphics, which works in terminals like xterm, mlterm, foot, and WezTerm.

Drawing Commands

  • PSET (x,y), color / PRESET (x,y) — set/reset individual pixels
  • LINE (x1,y1)-(x2,y2), color [,B|BF] — lines, boxes, filled boxes
  • CIRCLE (cx,cy), r [,color [,start, end [,aspect]]] — circles and arcs
  • PAINT (x,y), fill, border — flood fill
  • DRAW string — turtle graphics mini-language (U/D/L/R/E/F/G/H, M, C, S, B, N)
  • POINT (x,y) — read pixel color
  • COLOR fg, bg — set foreground/background colors

Example

SCREEN 1
LINE (0,0)-(319,199), 1
CIRCLE (160,100), 80, 2
PAINT (160,100), 3, 2

Sound

  • SOUND frequency, duration — play a tone (frequency in Hz, duration in clock ticks)
  • BEEP — play the default beep
  • PLAY string — Music Macro Language (MML) string for melodies

Sound output uses PulseAudio when available; commands are silently ignored otherwise.

Full-Screen Editor (TUI)

When running interactively, GW-BASIC 2026 presents the authentic full-screen editor:

  • 25×80 screen buffer by default, or full terminal size with --full
  • Press Enter on any screen line to re-enter it as BASIC input
  • Insert/Overwrite toggle (Insert key)
  • Home/End/Delete/Backspace/Escape for line editing
  • Ctrl+C interrupts running programs
  • Uses the ANSI alternate screen buffer for clean terminal restore on exit

Function Keys

Default F1-F10 bindings match the original GW-BASIC:

Key Default Key Default
F1 LIST F6 ,"LPT1:" + Enter
F2 RUN + Enter F7 TRON + Enter
F3 LOAD" F8 TROFF + Enter
F4 SAVE" F9 KEY
F5 CONT + Enter F10 SCREEN 0,0,0 + Enter
  • KEY ON — show the function key bar on line 25
  • KEY OFF — hide the bar
  • KEY LIST — display all definitions
  • KEY n, "string" — redefine a function key

Piped Mode

When stdin is not a terminal (piped input), the TUI is not activated. The interpreter reads lines from stdin and writes output directly to stdout, suitable for scripting and test harnesses.

Program Editing

  • EDIT [linenum] — display a program line for editing in the TUI; press Enter to re-store it
  • AUTO [start][,increment] — automatic line numbering mode
  • RENUM [new][,[old][,increment]] — renumber program lines (patches all GOTO/GOSUB references)
  • DELETE range — delete program lines (DELETE 10-50, DELETE -100, DELETE 200-)

Event Trapping

GW-BASIC supports event-driven programming through trap handlers that fire between statements during program execution.

Timer Events

ON TIMER(n) GOSUB line    ' register handler (fires every n seconds)
TIMER ON                  ' enable timer trapping
TIMER STOP                ' suspend trapping (events are queued)
TIMER OFF                 ' disable trapping (events are discarded)

Function Key Events

ON KEY(n) GOSUB line      ' register handler for F-key n (1-10)
KEY(n) ON                 ' enable trapping for key n
KEY(n) STOP               ' suspend trapping (events are queued)
KEY(n) OFF                ' disable trapping

Event handlers execute as implicit GOSUBs. The RETURN statement returns to the interrupted code and clears the handler's in-progress flag. Events do not fire inside their own handler (re-entrant protection).

TIMER STOP / KEY(n) STOP queue events while stopped; switching to TIMER ON / KEY(n) ON fires the pending event immediately.