# Step: IOChan over files Tag `v3-iochan-files`. Suite **130/130**; fixpoint **OK** (`bootstrap/fixpoint.sh`, image **2,103,316 bytes**). ## What changed `IOChan` now covers files as well as the standard streams, so a program can treat a file and stdin/stdout uniformly through one `ChanId`: - `OpenRead(name)`, `OpenWrite(name)` → `ChanId` (a failed open yields a closed channel: `IsOpen` = FALSE). - `Close(VAR cid)` — closes and clears the handle. - `IsOpen(cid)`. - `ReadString(cid, VAR s)` — reads one line (the newline is dropped) into the NUL-terminated string; `ReadInt(cid)` reads a signed decimal integer (skipping leading blanks). The existing standard channels and operations (`StdIn/Out/ErrChan`, `ReadChar`, `WriteChar`, `WriteString`, `WriteLn`, `WriteInt`) are unchanged. Operations on a closed/failed channel stay safe no-ops (`ReadChar` returns `0C`). ## Bridge additions - `runtime/syslib/SysShim.def`/`.mod`: `freadint`, `freadline`. - `runtime/syslib/shim.c`: `m2freadline` (line read into a descriptor, newline dropped, header set to the length). `m2freadint` already existed (used by `Files`). ## Test `compiler/tests/iochanfile_prog.mod` (`IOChanFileProg`, exit 3): writes `"line one\n-7\n"` through a channel to `gen_ssa/_iochan_tmp.txt`, closes, reopens for reading, and checks the line (`ReadString` → `"line one"`) and the integer (`ReadInt` → `-7`). The harness removes the temporary file before and after. ## Notes - `Close` takes `cid` by reference so it can set it to `NIL`; this mirrors the ISO-ish "release the channel" shape. - `ReadString` truncates to the destination capacity. - `Files` keeps its own direct shim binding for now; `IOChan` could become its base layer in a later step. ## Files `stdlib/iochan.def`/`.mod`, `runtime/syslib/SysShim.def`/`.mod`, `runtime/syslib/shim.c`, `compiler/tests/iochanfile_prog.mod`, `compiler/run_tests.sh`, `docs/features.md`.