lib: collapse the parallel vstream scaffold onto the single Hare io surface (#94 fold-eFinal)
The Option-C parallel _v vstream API was scaffolding to bring the io stack up alongside the old surface; carrying both permanently is a rule-9 divergence from ref/hare, which has exactly one io surface. Collapse onto that surface (stream = *vtable, ref/hare/io/stream.ha) and rename the _v symbols to their Hare names (io vstream->stream, fmt vfprint->fprint, bufio/memio/log surfaces, log.new). Deletes the 4 lib/*/vstream.ww scaffold files; regenerates w6c/wwdump combined.ww. cstage and wwstage stay byte-identical and combined_ww_fresh holds; all 220 tests pass.
This commit is contained in:
@@ -30,168 +30,161 @@ fn streq(a: str, b: str) bool = {
|
||||
return true;
|
||||
};
|
||||
|
||||
// ---- A write-always-closed stream for the io.closed surfacing test ----
|
||||
// ---- an error-returning stream for the io.error surfacing test --------
|
||||
//
|
||||
// Replaces the OLD io.closed source. errvt is module-static; its
|
||||
// reader/writer return a nomem-widened io.error.
|
||||
let errvt: io.vtable;
|
||||
|
||||
fn closedread(s: *io.stream, buf: []u8) (i32 | io.eof | io.closed) = {
|
||||
let e: io.closed; return e;
|
||||
fn errread(s: io.stream, buf: []u8) (size | io.eof | io.error) = {
|
||||
let nm: nomem; let e: io.error = nm; return e;
|
||||
};
|
||||
fn closedwrite(s: *io.stream, buf: []u8) (i32 | io.closed) = {
|
||||
let e: io.closed; return e;
|
||||
fn errwrite(s: io.stream, buf: []u8) (size | io.error) = {
|
||||
let nm: nomem; let e: io.error = nm; return e;
|
||||
};
|
||||
fn closedclose(s: *io.stream) (void | io.closed) = { return; };
|
||||
|
||||
fn closedstream(s: *io.stream) void = {
|
||||
s.ctx = nil;
|
||||
s.read = closedread;
|
||||
s.write = closedwrite;
|
||||
s.close = closedclose;
|
||||
fn errsource() io.stream = {
|
||||
errvt.reader = (&errread): *io.reader;
|
||||
errvt.writer = (&errwrite): *io.writer;
|
||||
return &errvt;
|
||||
};
|
||||
|
||||
// ---- fprint: bare str --------------------------------------------------
|
||||
|
||||
@test fn fprintbarestr() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let r: (i32 | io.closed) = fmt.fprint(&s, "hello");
|
||||
let r: (size | io.error) = fmt.fprint(s, "hello");
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 5) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 5) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "hello")) { fail(); };
|
||||
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// ---- fprint: int + str mix, space-separated ----------------------------
|
||||
|
||||
@test fn fprintintstr() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let r: (i32 | io.closed) = fmt.fprint(&s, 42i64, "x");
|
||||
let r: (size | io.error) = fmt.fprint(s, 42i64, "x");
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 4) { fail(); }; }; // "42 x"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 4) { fail(); }; }; // "42 x"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "42 x")) { fail(); };
|
||||
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// ---- fprint: bool + rune renders as "true A" --------------------------
|
||||
|
||||
@test fn fprintboolrune() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let r: (i32 | io.closed) = fmt.fprint(&s, true, 'A': rune);
|
||||
let r: (size | io.error) = fmt.fprint(s, true, 'A': rune);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 6) { fail(); }; }; // "true A"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 6) { fail(); }; }; // "true A"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "true A")) { fail(); };
|
||||
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// ---- fprint: zero args returns 0, no bytes written --------------------
|
||||
|
||||
@test fn fprintempty() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let r: (i32 | io.closed) = fmt.fprint(&s);
|
||||
let r: (size | io.error) = fmt.fprint(s);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 0) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 0) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (memio.string(&mem).len != 0) { fail(); };
|
||||
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// ---- fprintln: multi-arg, trailing '\n' --------------------------------
|
||||
|
||||
@test fn fprintlnmulti() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let r: (i32 | io.closed) = fmt.fprintln(&s, "a", 1i64, false);
|
||||
let r: (size | io.error) = fmt.fprintln(s, "a", 1i64, false);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 10) { fail(); }; }; // "a 1 false\n"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 10) { fail(); }; }; // "a 1 false\n"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "a 1 false\n")) { fail(); };
|
||||
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// ---- fprintln: zero args writes just the newline ----------------------
|
||||
|
||||
@test fn fprintlnempty() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let r: (i32 | io.closed) = fmt.fprintln(&s);
|
||||
let r: (size | io.error) = fmt.fprintln(s);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 1) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 1) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "\n")) { fail(); };
|
||||
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// ---- fprint over a fixed stream: short writes return partial count ----
|
||||
// memio.fixedwrite caps each call at the remaining buffer space and
|
||||
// never closes the stream, so fprint sees a short i32 result, not
|
||||
// io.closed. Verifies the inner-loop arithmetic adds the actual byte
|
||||
// io.error. Verifies the inner-loop arithmetic adds the actual byte
|
||||
// count rather than the requested length.
|
||||
|
||||
@test fn fprintfixedshort() void = {
|
||||
let buf: [3]u8;
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.fixed(&mem, &s, buf[0:3]);
|
||||
let mem: memio.stream = memio.fixed(buf[0:3]);
|
||||
let s: io.stream = &mem.vt;
|
||||
|
||||
let r: (i32 | io.closed) = fmt.fprint(&s, "hello");
|
||||
let r: (size | io.error) = fmt.fprint(s, "hello");
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 3) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 3) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "hel")) { fail(); };
|
||||
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// ---- fprint over a closed stream surfaces io.closed -------------------
|
||||
// ---- fprint over a closed stream surfaces io.error -------------------
|
||||
// Exercises the early-return arm in fprint's inner match — distinct from
|
||||
// the short-write path above, which keeps returning i32 from a partial
|
||||
// accept. Single arm is enough: every formattable case routes errors
|
||||
// through the same putbytes / io.write wiring.
|
||||
|
||||
@test fn fprintclosed() void = {
|
||||
let s: io.stream;
|
||||
closedstream(&s);
|
||||
let s: io.stream = errsource();
|
||||
|
||||
let r: (i32 | io.closed) = fmt.fprint(&s, "x");
|
||||
let r: (size | io.error) = fmt.fprint(s, "x");
|
||||
match (r) {
|
||||
case let n: i32 => fail();
|
||||
case io.closed => {};
|
||||
case let n: size => fail();
|
||||
case let eioe: io.error => {};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -201,203 +194,189 @@ fn closedstream(s: *io.stream) void = {
|
||||
// see the file header.
|
||||
|
||||
@test fn fprintf_implicit() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "hello {} {}", "world", 42i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "hello {} {}", "world", 42i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 14) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 14) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "hello world 42")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_indexed() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{1} {0} {1}", "hello", "world");
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{1} {0} {1}", "hello", "world");
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 17) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 17) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "world hello world")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_literal_braces() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{{ {} }}", 1i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{{ {} }}", 1i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 5) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 5) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "{ 1 }")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_width_right() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:5}", 42i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:5}", 42i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 5) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 5) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), " 42")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_width_left() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:-5}", 42i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:-5}", 42i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 5) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 5) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "42 ")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_width_center() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:=5}", "hi");
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:=5}", "hi");
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 5) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 5) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), " hi ")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_pad_underscore() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:_05}", "hi");
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:_05}", "hi");
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 5) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 5) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "000hi")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_base_hex() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:x} {:X}", 48879i64, 61453i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:x} {:X}", 48879i64, 61453i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 9) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 9) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "beef F00D")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_base_oct_bin() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:o} {:b}", 493i64, 27i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:o} {:b}", 493i64, 27i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 9) { fail(); }; }; // "755 11011"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 9) { fail(); }; }; // "755 11011"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "755 11011")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_prec_int() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:.5}", 42i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:.5}", 42i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 5) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 5) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "00042")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_prec_str_trunc() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:.3}", "hello");
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:.3}", "hello");
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 3) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 3) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "hel")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_sign_neg() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{} {:+} {: }", -7i64, 7i64, 7i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{} {:+} {: }", -7i64, 7i64, 7i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 8) { fail(); }; }; // "-7 +7 7"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 8) { fail(); }; }; // "-7 +7 7"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "-7 +7 7")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintfln_basic() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintfln(&s, "x={}", 9i64);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintfln(s, "x={}", 9i64);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 4) { fail(); }; }; // "x=9\n"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 4) { fail(); }; }; // "x=9\n"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "x=9\n")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_closed() void = {
|
||||
let s: io.stream;
|
||||
closedstream(&s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "hello {}", 1i64);
|
||||
let s: io.stream = errsource();
|
||||
let r: (size | io.error) = fmt.fprintf(s, "hello {}", 1i64);
|
||||
match (r) {
|
||||
case let n: i32 => fail();
|
||||
case io.closed => {};
|
||||
case let n: size => fail();
|
||||
case let eioe: io.error => {};
|
||||
};
|
||||
};
|
||||
|
||||
@test fn bsprintf_basic() void = {
|
||||
let buf: [16]u8;
|
||||
let r: (str | io.closed) = fmt.bsprintf(buf[0:16], "{} {}", "hi", 42i64);
|
||||
let r: (str | io.error) = fmt.bsprintf(buf[0:16], "{} {}", "hi", 42i64);
|
||||
match (r) {
|
||||
case let s: str => { if (!streq(s, "hi 42")) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -407,29 +386,28 @@ fn closedstream(s: *io.stream) void = {
|
||||
// tagged arms so a future task-#18 fix that re-introduces the 24B
|
||||
// widen-by-value cannot regress silently.
|
||||
@test fn fprintf_bool_rune() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{} {}", true, 'A': rune);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{} {}", true, 'A': rune);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 6) { fail(); }; }; // "true A"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 6) { fail(); }; }; // "true A"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "true A")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// Verifies bsprintf's documented truncation contract — short writes
|
||||
// return the prefix that fit (memio.fixedwrite returns 0 once full,
|
||||
// not io.closed). Pairs with fprintfixedshort above which covers the
|
||||
// not io.error). Pairs with fprintfixedshort above which covers the
|
||||
// underlying fprint path.
|
||||
@test fn bsprintf_trunc() void = {
|
||||
let buf: [3]u8;
|
||||
let r: (str | io.closed) = fmt.bsprintf(buf[0:3], "{} {}", "hi", 42i64);
|
||||
let r: (str | io.error) = fmt.bsprintf(buf[0:3], "{} {}", "hi", 42i64);
|
||||
match (r) {
|
||||
case let s: str => { if (!streq(s, "hi ")) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -440,10 +418,10 @@ fn closedstream(s: *io.stream) void = {
|
||||
// formatraw + tail-pad both write 0 — must terminate.
|
||||
@test fn bsprintf_width_trunc() void = {
|
||||
let buf: [3]u8;
|
||||
let r: (str | io.closed) = fmt.bsprintf(buf[0:3], "{:5}", 42i64);
|
||||
let r: (str | io.error) = fmt.bsprintf(buf[0:3], "{:5}", 42i64);
|
||||
match (r) {
|
||||
case let s: str => { if (!streq(s, " ")) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -494,173 +472,162 @@ fn closedstream(s: *io.stream) void = {
|
||||
// `prec` and `base` ignored — graduate when strconv grows ffmt/fflags.
|
||||
|
||||
@test fn fprintf_f64_basic() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{}", 1.5);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{}", 1.5);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 3) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 3) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "1.5")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_f64_int_valued() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{}", 1.0);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{}", 1.0);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 1) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 1) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "1")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_f64_neg() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{}", -2.5);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{}", -2.5);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 4) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 4) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "-2.5")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_f64_zero() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{}", 0.0);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{}", 0.0);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 1) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 1) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "0")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_f64_small_frac() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{}", 0.05);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{}", 0.05);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 4) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 4) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "0.05")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// Pins a large magnitude through the fmt dispatch — post-Ryū-graduation
|
||||
// (fold-5) this is scientific notation, not the old lossy "huge" fallback.
|
||||
// Catches any regression where mods accidentally pre-truncate the view.
|
||||
@test fn fprintf_f64_huge() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{}", 9.5e18);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{}", 9.5e18);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 6) { fail(); }; }; // "9.5e18"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 6) { fail(); }; }; // "9.5e18"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "9.5e18")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// Sign-mod fold: '+' on positive, '-' still wins on negative (the
|
||||
// natural '-' from strconv is peeled and signof reapplies).
|
||||
@test fn fprintf_f64_sign_plus() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:+} {:+}", 1.5, -1.5);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:+} {:+}", 1.5, -1.5);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 9) { fail(); }; }; // "+1.5 -1.5"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 9) { fail(); }; }; // "+1.5 -1.5"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "+1.5 -1.5")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_f64_sign_space() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{: }", 1.5);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{: }", 1.5);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 4) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 4) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), " 1.5")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// Width + alignment round-trip through rawlenf64 (sign-aware len count).
|
||||
@test fn fprintf_f64_width_right() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:8}", 1.5);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:8}", 1.5);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 8) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 8) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), " 1.5")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn fprintf_f64_width_left() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprintf(&s, "{:-8}", 1.5);
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprintf(s, "{:-8}", 1.5);
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 8) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 8) { fail(); }; };
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "1.5 ")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
// Legacy fprint variadic — covers the non-printf surface arm (where
|
||||
// formatraw isn't reached because there's no mods parser).
|
||||
@test fn fprint_f64_variadic() void = {
|
||||
let mem: memio.state;
|
||||
let s: io.stream;
|
||||
memio.dynamic(&mem, &s);
|
||||
let r: (i32 | io.closed) = fmt.fprint(&s, 1.5, "x");
|
||||
let mem: memio.stream = memio.dynamic();
|
||||
let s: io.stream = &mem.vt;
|
||||
let r: (size | io.error) = fmt.fprint(s, 1.5, "x");
|
||||
match (r) {
|
||||
case let n: i32 => { if (n != 5) { fail(); }; }; // "1.5 x"
|
||||
case io.closed => fail();
|
||||
case let n: size => { if (n: i32 != 5) { fail(); }; }; // "1.5 x"
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
if (!streq(memio.string(&mem), "1.5 x")) { fail(); };
|
||||
let c: (void | io.closed) = io.close(&s);
|
||||
match (c) { case void => {}; case io.closed => fail(); };
|
||||
let c: (void | io.error) = io.close(s);
|
||||
match (c) { case void => {}; case let eioe: io.error => fail(); };
|
||||
};
|
||||
|
||||
@test fn bsprintf_f64() void = {
|
||||
let buf: [16]u8;
|
||||
let r: (str | io.closed) = fmt.bsprintf(buf[0:16], "x={}", 1.5);
|
||||
let r: (str | io.error) = fmt.bsprintf(buf[0:16], "x={}", 1.5);
|
||||
match (r) {
|
||||
case let s: str => { if (!streq(s, "x=1.5")) { fail(); }; };
|
||||
case io.closed => fail();
|
||||
case let eioe: io.error => fail();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user