Skip to main content

Phase 7.8. File I/O

FieldValue
MEPMEP-54
StatusLANDED
Started2026-05-29 (GMT+7)
Landed2026-05-29 (GMT+7)
Tracking PR#22583
Commit492a45a1c9

Gate

8 fixtures cover the I/O surface: file_append_basic, file_write_read_basic, file_write_overwrite, file_write_read_newlines, file_read_long, lines_basic, lines_empty_file, lines_no_trailing_newline. 230 transpiler3/go fixtures green.

Lowering decisions

WriteFileStmt dispatches in stmt.go to os.WriteFile(path, []byte(content), 0644). The mode 0644 matches the C runtime default and is the canonical Go idiom for user-rw / group-r / other-r.

AppendFileStmt dispatches to mochiAppendFile, a helper that opens with O_APPEND|O_CREATE|O_WRONLY, writes the content, closes the file, and ignores errors. Go's stdlib has no one-liner for append-create-and-write; the helper packages the three syscalls and matches the C runtime's silent-on-error behaviour (which Mochi's semantics promise).

ReadFileExpr lowers to mochiReadFile, which calls os.ReadFile(path) and returns the string content (or "" on error). The empty-string-on-error contract matches the C runtime's mochi_read_file.

LinesExpr lowers to mochiLines, which calls os.ReadFile(path), splits on '\n', and drops a trailing empty token so a file ending with a newline produces N lines, not N+1. The trailing-newline drop matches the C runtime's behaviour for mochi_file_lines, which the JVM and BEAM transpilers also mirror.

addImport("os") is registered for the helpers; the helpers themselves are emitted via addHelper into the emittedHelpers block.

Files changed

FilePurpose
transpiler3/go/lower/stmt.goWriteFileStmt, AppendFileStmt dispatch
transpiler3/go/lower/expr.goReadFileExpr, LinesExpr dispatch
transpiler3/go/lower/lower.gomochiAppendFile, mochiReadFile, mochiLines helper texts
tests/transpiler3/go/fixtures/file_*/, lines_*/8 fixtures

Test set

  • 8 TestPhase1Hello/file_*, lines_* subtests.

Closeout notes

The "ignore errors" contract for file I/O matches every other Mochi transpiler's behaviour; surfacing errors here would be a semantic divergence that the upstream type-checker is not prepared for. The trailing-newline drop in mochiLines is the kind of detail that's easy to miss in a fresh-write helper: the test lines_no_trailing_newline exercises both shapes (with and without the trailing newline) so the contract is pinned.