refactor(io): extract channel I/O from Interpreter into an io package
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Thu, 3 Sep 2026 20:49:00 +0000 (23:49 +0300)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Thu, 3 Sep 2026 20:49:00 +0000 (23:49 +0300)
commit3ccaa91a38175d95edcf4eb3b8fcb5f812eb3f17
tree8a68ada1f8c0d7d00d0b71e9beaf9b1553312133
parent24c8c9e56917d0de28dec405735e032c6b54776e
refactor(io): extract channel I/O from Interpreter into an io package

Interpreter grew a god-object sprawl of nine parallel maps keyed by
channel number (text readers, paths, writers, columns, lookahead,
remainder, binary handles, CON set, COM set) — every file feature had
to touch several of them, and CLOSE had to clean each separately.

New package eu.svjatoslav.crtbasic.io:

- Channel: one holder for all per-channel state (kind, reader, writer,
  column, lookahead, remainder, byte handle) — new per-channel facts
  become fields, not new maps
- FileHandle: the in-memory BINARY/RANDOM file image (moved out of
  Interpreter, accessor-encapsulated)
- DosPaths: DOS path resolution (backslashes, drive letters,
  case-insensitive components, drive-root anchoring) + CHDIR/MKDIR
- IoSubsystem: the channel table and all operations — OPEN/CLOSE,
  FREEFILE, EOF/LOF/LOC/SEEK, readLine/readItem (INPUT # tokenizer),
  readBytes (INPUT$ file form), PRINT # with 14-column zones and
  column-255 wrap, NAME, KILL wildcards, SHELL "DIR" listings
- ConsoleOutput/IoErrors bridges keep the interpreter's screen and
  ON ERROR semantics without io depending back on it

CP437 helpers consolidate on the existing Cp437 class (stringOf/
bytesOf/charset); Interpreter's private copies are gone. Docs: the
BINARY/RANDOM row no longer claims FIELD (never implemented).

Verification: 93/93 tests green; the full QB45 EXAMPLES suite re-run
through the GameDriver — every deterministic screen pixel-identical
to the pre-refactor captures, CRLF/ENTAB outputs byte-exact, WHEREIS
recursive SHELL-DIR scan pixel-identical.
Documentation/language/index.org
src/main/java/eu/svjatoslav/crtbasic/Cp437.java
src/main/java/eu/svjatoslav/crtbasic/interp/Interpreter.java
src/main/java/eu/svjatoslav/crtbasic/io/Channel.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/crtbasic/io/ConsoleOutput.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/crtbasic/io/DosPaths.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/crtbasic/io/FileHandle.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/crtbasic/io/IoErrors.java [new file with mode: 0644]
src/main/java/eu/svjatoslav/crtbasic/io/IoSubsystem.java [new file with mode: 0644]