ffi issue-0047: #run print output now routes to stdout

`#run` / post-link callback `print` output was reaching stderr via
`std.debug.print` flushes from three sites. The runtime JIT path
already writes to fd 1 (stdout) directly. Anyone redirecting one
stream saw the two halves disappear in different places.

Switches all three flush sites + the `--- build done ---` delimiter
in main.zig to `std.c.write(1, ...)` so build-time and runtime
prints share the stream the user wrote them against (they typed
the same `print(...)` at both call sites — there's no reason for
them to land on different streams). Test runner uses `2>&1` so
snapshots are unaffected; suite stays at 218/218.

Closes issue-0047.
This commit is contained in:
agra
2026-05-28 08:15:18 +03:00
parent 11eef8a6b1
commit 0119c9c05f
3 changed files with 23 additions and 5 deletions

View File

@@ -184,13 +184,22 @@ pub const Compilation = struct {
ir.Interpreter.last_bail_builtin = null;
ir.Interpreter.last_bail_detail = null;
const result = interp.call(id, args) catch |err| {
if (interp.output.items.len > 0) std.debug.print("{s}", .{interp.output.items});
flushInterpOutput(interp.output.items);
return err;
};
if (interp.output.items.len > 0) std.debug.print("{s}", .{interp.output.items});
flushInterpOutput(interp.output.items);
return result;
}
/// #run / post-link callback `print` output lands here. Routes to
/// fd 1 (stdout) so it joins the JIT-executed runtime's output
/// stream — the user wrote `print(...)` in both call sites, so
/// the stream split is invisible to them. issue-0047.
fn flushInterpOutput(bytes: []const u8) void {
if (bytes.len == 0) return;
_ = std.c.write(1, bytes.ptr, bytes.len);
}
/// Get link flags accumulated from #run build blocks.
pub fn getBuildLinkFlags(self: *Compilation) []const []const u8 {
if (self.ir_emitter) |*e| return e.build_config.link_flags.items;