This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 11/4/2026.
I/O
import std/ioKoru Standard Library: I/O
io.kz · 17 tors · ~[comptime]· ~[runtime]
Phantom lifecycles
Derived from the phantom labels in the declarations below — state! issues an
obligation the compiler will chase, !state discharges it, a bare state holds it without moving it. Nothing here is hand-drawn.
string 2 states allocated!// Print without trailing newline — the no-newline sibling of print.ln.
// SAME implementation (__printInterpolate, with_newline=false): comptime
// {{ }} interpolation, rerouted to print.impl for shape checking.
//
// The old RUNTIME passthrough tor (`print { text }` + |zig/|js procs) died
// here (2026-06-11, Lars ruling: std/io's print surface is comptime-only;
// stage/runtime printing is the future std/compiler print-family). Its
// positional-arg mis-emit bug died with the codepath.
~[keyword|comptime|transform] pub tor print {
expr: ?Expression,
invocation: *const Invocation,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter,
allocator: std.mem.Allocator
} -> SiteResultreadln
koru_std/io.kz:47// `println` REMOVED — subsumed by `print.ln` (the interpolating print). Calling
// `std/io:println` is now an unknown-event error by design (greenfield: the old
// form must fail loudly once removed).
//
// Print formatted text
// NOTE: printf with varargs would require runtime support — deliberately absent.
//
// One blocking line from stdin. EOF is a branch, not an empty string —
// an empty line is `line` with length 0. The buffer is module-static:
// the returned slice is valid until the next readln (the caller must
// finish with the line first). That is the interactive/pipe contract
// (`650_009`); read.ln remains the leaky slurp-a-chunk sibling.
~pub tor readln {}
| line string
| eof
| failed stringread.ln
koru_std/io.kz:76// Simple line reader - returns the line, or empty string on EOF/error
// No error handling, just returns what it gets
~pub tor read.ln {} -> string// Print error to stderr
~pub tor eprintln { message: string<*@scoped> }// Success message with green color (if terminal supports it)
~pub tor success { message: string<*@scoped> }// Warning message
~pub tor warn { message: string<*@scoped> }~[
- aspirational
Same gap as std/fs:read-lines: a per-line streaming surface backed by a
whole-stream slurp (readToEndAlloc), bounded by RAM. True streaming is the
deferred honest fix; marked so the gap is explicit and greppable.
]pub tor read-lines {}
! line string
| done usize
| failed string// Read entire stdin as text. The buffer is allocator-owned and carries the
// `allocated!` obligation: hand it to `std/io:free` (auto-discharge inserts
// the call when the trace is unambiguous — most callers never write it).
// Ruled 2026-07-31 (the 335_042/043 question): one label, `allocated`, for
// every allocator-owned buffer an io tor hands back; `std/io:free` is the
// one disposer.
~pub tor read-stdin {}
| ok string<allocated!>
| eof
| failed string// Read entire file as text. `ok` carries the `allocated!` obligation — see
// read-stdin's header; `std/io:free` discharges it.
~pub tor read-file { path: string }
| ok string<allocated!>
| not-found
| failed string// Discharge the `allocated!` obligation on a buffer an io tor handed back
// (read-file, read-stdin). The one disposer for the one label.
~pub tor free { content: string<!allocated> }args
koru_std/io.kz:237// Get command line arguments
~pub tor args {} -> []string// PRINT.LN - Interpolated printing with Expression (ZERO OVERHEAD)
//
// Syntax: std/io:print.ln("Hello {{ name }}! Count: {{ count }}")
//
// ARCHITECTURE:
// - print.ln is a comptime transform that generates inline Zig code
// - Parses {{ ... }} placeholders from the Expression string
// - Optional format specifier: {{ name:s }} or {{ count:d }}
// - Generates: std.debug.print("Hello {}! Count: {}\n", .{name, count});
//
// This is NOT a regular tor - it's a pure compile-time transformation.
~[keyword|comptime|transform] pub tor print.ln {
expr: ?Expression,
invocation: *const Invocation,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter,
allocator: std.mem.Allocator
} -> SiteResult~[norun] pub tor print.impl { expr: string<*@scoped> }// eprint / eprint.ln — the stderr siblings of print / print.ln. Same engine
// (__printInterpolate), routed to fd 2. They reuse print.impl for shape
// checking (the reroute is analysis-only; the inline body does the write).
~[keyword|comptime|transform] pub tor eprint.ln {
expr: Expression,
invocation: *const Invocation,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter,
allocator: std.mem.Allocator
} -> SiteResult~[keyword|comptime|transform] pub tor eprint {
expr: Expression,
invocation: *const Invocation,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter,
allocator: std.mem.Allocator
} -> SiteResult~part jsprec koru_std/io.jsprec.kz
Koru Standard Library: I/O — JS placeholder operand emission. Joined via `~part jsprec` in io.kz; merged into the io module at load. Emit one `{{ … }}` placeholder's VALUE operand for the JS concat `__printInterpolateJs` is building. The raw text between the braces arrives untrimmed; the spec after the first `:` is dropped — JS `+` promotes Numbers to strings on concat, so no per-spec mapping is needed — EXCEPT a `:.N` precision tail, which emits `Number(x).toFixed(N)`, the same honoring fmt's jsPlaceholder gives `ln|js` (same parse as it). A lone/leading operand is parenthesized so a multi-term expr (`{{ c + 1 }}`) is ONE operand — `"n=" + c + 1` would otherwise fold left-to-right to `"n=<c>" + 1` = "n=<c>1" instead of the sum.
~part csprec koru_std/io.csprec.kz
Koru Standard Library: I/O — CS placeholder operand + interpolation engine. Joined via `~part csprec` in io.kz; merged into the io module at load. The K# vertical's print path. Same surface as __printInterpolateJs — string-literal vs bare expression, `{{ var:fmt }}` placeholders, `{% if v %}…{% endif %}` blocks — and nearly the same emitted text: `"" + x + "lit"` is valid C# (string concat promotes the operand exactly like JS), and `(cond ? "body" : "")` is the same ternary. What differs lives in the two helpers here: exprs lower through the `.cs` arm (and/or, .len, `++`, reserved words) and a `:.N` precision tail honors via `.ToString("F"+N, InvariantCulture)` rather than JS's toFixed — C#'s culture-sensitive formatting would otherwise answer "3,14" for "3.14" in half the world's locales. CS-target interpolation engine — the __printInterpolateJs twin. SAME expr surface, same reroute-to-print.impl surgery; only the emitted operand text differs, and both helpers producing it live above.
~part lowers koru_std/io.lowers.kz
Koru Standard Library: the `lowers` part of io.kz. Joined via `~part lowers` in io.kz; merged into the io module at load. The `{{ … }}` interpolation doors — one per host vocabulary arm. Both engines splice a Koru expression into host text through these twins; they live together because a fix to the lowering contract lands in both places or in neither. A `{{ … }}` INTERPOLATION IS A KORU EXPRESSION, and this builder splices it into JavaScript. It is the third door onto the same pass — after `std/store`'s guards and `std/kernel`'s op bodies — and it was the last one still writing the text through raw. What that cost: `print.ln("… {{ new:s }}")` over `! updated { old, new }` emitted a bare `new` into the concatenation, and node refused the file. It also meant an interpolation naming `a and b` or `@as(i64, x)` reached node unlowered, which nothing had noticed because no test interpolates one. Refusal is swallowed rather than reported: an unmodelled `@`-operation here falls back to the raw text, which is what this site did for every expression until now, so the failure mode is unchanged rather than newly silent. The diagnostic belongs with the print transform's own error surface and that is a separate job.
~part blkcs koru_std/io.blkcs.kz
Koru Standard Library: the `blkcs` part of io.kz. Joined via `~part blkcs` in io.kz; merged into the io module at load. print.blk|cs — the C#-target variant of the block-print transform, ported from print.blk|js in io.blk.kz. Same scan: `{% if v %}…{% endif %}` → `(v ? "escaped" : "")` (C#'s ternary is the same shape), `{{ var:fmt }}` → the ioCsPlaceholderOperand door (parens + .cs lowering + the :.N honoring), literal runs escaped into `"…"` segments, all joined by ` + ` — C# string concat promotes the operand exactly like JS. Newline: JS's console.log appends one, so |js strips a trailing `\n` from the template content. __koru_stdout_write is a bare Write — the same strip applies, then the newline is re-added inside the concat, so the emitted program writes exactly what |zig's raw_posix writes.
~part blk koru_std/io.blk.kz
Koru Standard Library: I/O — the `print.blk` family. Joined via `~part blk` in io.kz; merged into the io module at load. Lifted out of io.kz so both files stay under their line baselines; module-scope names (KORU_OUT_FN, __appendFmtLiteralByte, codegen_utils_io, the expr_parser idiom) resolve through the merge. PRINT.BLK - Multi-line block printing with Source block (ZERO OVERHEAD) Syntax: std/io:print.blk { Header: {{ title }} Value: {{ count }} } ARCHITECTURE: - Takes a Source block (multi-line text) - Parses {{ ... }} and {% if %} placeholders - Generates inline Zig print statement This is NOT a regular tor - it's a pure compile-time transformation.
~[comptime|transform] pub tor print.blk {
source: Source,
invocation: *const Invocation,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter,
allocator: std.mem.Allocator
} -> SiteResult~[norun] pub tor print.blk.impl { text: string }