// fmt — formatting writers. Mirrors Hare's lib/fmt subset that fmt- // prints values via [[io::handle]]-style fd writers. Call sites take // Hare's variadic shape: `fmt.println(42, "hi", true)` gathers the // args into a `[]formattable` slice; wrappers forward via `args...`. use os; use strconv; use strings; // formattable — tagged union of types fmt can render. Mirrors Hare's // `fmt::formattable = (...types::numeric | uintptr | str | rune | // bool | nullable *opaque | void)`, narrowed to the set ww actually // has codegen for. Slot size is 24B (8 tag + 16 str payload). export type formattable = (i64 | str | bool | rune); // fprint — write the formatted form of each `args` element to `fd`, // separated by spaces. Returns total bytes written or the first // negative os.write result. Hare's separator-by-space matches. export fn fprint(fd: i32, args: formattable...) i64 = { let total: i64 = 0; let i: i32 = 0; for (i < args.len) { if (i > 0) { let r: i64 = os.write(fd, " ".ptr, 1u64); if (r < 0) { return r; }; total += r; }; match (args[i]) { case let n: i64 => { let s: str = strconv.i64tos(n, strconv.base.DEC); let r: i64 = os.write(fd, s.ptr, s.len: u64); if (r < 0) { return r; }; total += r; }; case let s: str => { let r: i64 = os.write(fd, s.ptr, s.len: u64); if (r < 0) { return r; }; total += r; }; case let b: bool => { let s: str = "false"; if (b) { s = "true"; }; let r: i64 = os.write(fd, s.ptr, s.len: u64); if (r < 0) { return r; }; total += r; }; case let r: rune => { let buf: [4]u8; buf[0] = r: u8; let n: i64 = os.write(fd, &buf[0], 1u64); if (n < 0) { return n; }; total += n; }; }; i += 1; }; return total; }; // fprintln — fprint plus a trailing newline. export fn fprintln(fd: i32, args: formattable...) i64 = { let n: i64 = fprint(fd, args...); if (n < 0) { return n; }; let m: i64 = os.write(fd, "\n".ptr, 1u64); if (m < 0) { return m; }; return n + m; }; // print / println — fprint / fprintln on stdout. Direct counterparts // of Hare's fmt::print / fmt::println. export fn print(args: formattable...) i64 = { return fprint(1, args...); }; export fn println(args: formattable...) i64 = { return fprintln(1, args...); }; // errorln — fprintln on stderr. Hare's `fmt::error` (without -ln) is // skipped here: the bare `error` name collides with strconv's // `type error = !(invalid | overflow)` under the driver's flat // concatenation namespace. Callers wanting the no-newline form use // `fprint(2, args...)` directly. export fn errorln(args: formattable...) i64 = { return fprintln(2, args...); }; // fatal — errorln then exit(255). `never` return marks the bottom // type so flow-control checks treat callers as terminated. The // fprintln result is dropped as an expression statement (Hare's // `_ = fprintln(...)` wouldn't add safety here — process exit // follows immediately). export fn fatal(args: formattable...) never = { fprintln(2, args...); os.exit(255); };