lib/fmt: add Option C parallel vstream API (#94 fold-e3)
Adds lib/fmt/vstream.ww with four new wrappers — fdprint_v / fdprintln_v / fdprintf_v / fdprintfln_v — that take a raw fd, stack- allocate an fd_ctx whose first field is `vt: io.vtable`, and dispatch through io.st_write on a vstream pointing at &c.vt (intrusive offset-0 cast — same shape as lib/memio/vstream.ww's fixed_ctx / dynamic_ctx in fold-e2). Coexists with the pre-vtable fdprint / fdprintln / fdprintf / fdprintfln in fmt.ww. ken's escape-risk discipline: every wrapper owns the fd_ctx slot for its frame only; the &c.vt vstream pointer is consumed inside the same function (passed through internal vfprint / vfprintf helpers) and never returned. Single tagged field (vt) lets the local default-zero plus chained `c.vt.X = …` assigns sidestep the multi-tagged-field copy drop (sibling #207) — no struct-lit init needed and c is a stack value, not an aliased pointer, so #195's chained-store carve-out doesn't bite either. Drew defer cited at the file head: io.handle (= file | int) is out-of-scope for this fold per fold-d/fold-e3 precedent; Hare's ref/hare/fmt/wrappers.ha:9-25 routes through the handle sum, and fdNNN_v collapses into bare fNNN_v once io fold-2 lands the port (filed inline as "io fold-2 handle port" backlog). Internal vfprint / vfprintf duplicate the per-arg and {n}- placeholder loops from fmt.ww (fprint:177, fprintf:676) because the OLD versions take *io.stream (the legacy struct) and fmt.ww stays UNCHANGED this fold. Shared bits — i64dec, modsinit, scandigits, scanmods, formattable, field, mods, fmtabort — are reused directly from fmt.ww. vformatfield mirrors the inline-per- arm dispatch shape OLD formatfield (fmt.ww:648) uses to dodge #18 silent miscompile of 24B return-by-value in for-loop context. Cast workaround per #206 at each vtable-fn-ptr-slot init (2 sites per wrapper, 8 total): bare `&fn_name` does not type-check as `(*<alias> | void)`. Same `(&fn): *io.<role>` cast shape that lib/memio/vstream.ww uses. Drops out wholesale when #206 closes. #173 workaround at fdsinkwrite_v: constructs nomem and widens to io.error explicitly rather than `os.trywrite(...)?` — same shape memio.vstream.ww line 71-74 note adopted. OLD fmt surface is UNCHANGED. fold-eFinal (task #50) atomically flips the package shape: deletes OLD wrappers + callbacks, renames _v suffix off, and migrates the few callers (with io fold-2's handle sum landing in the same flip). Probe test/wcc/777_fmt_vstream_run.c: 4 rows (fdprintf_v_int / fdprintln_v_multi / fdprint_v_raw / branched_fdprintf_v) open per-row /tmp output files, dispatch one V wrapper per row, reopen the file, read the bytes back, and assert both the exact byte content and a unique row-tagged exit constant. 4/4 fixtures total, all green via cstage. Cstage-only per row (no STAGE_WW, no byte_id) — pre-existing wwstage match-arm bug (sibling of #190, filed inline as #209): the wwstage checker bails `case: not a variant of scrutinee (X)` / `match: variant not handled (formattable)` on the OLD fmt.fdprint's match arms whenever any probe `import fmt;`s the package. The bug bites the OLD surface identically — even `fmt.errorln("hi")` from a probe trips the same trace. 970 fmttest dodges via cstage-only ww run; 995 self-rebuild dodges because no selfhost cmd transitively pulls fmt (err.ww imports fmt but no main.ww in cmd/{ww,w6c,w6a,w6l,wwdump} pulls err.ww in). Byte-id graduates when #209 closes — out-of-scope for the additive fold-e3. Combined.ww regen NO-OP: none of the five tracked combined.ww files (cmd/{ww,w6c,w6a,w6l,wwdump}/main.combined.ww) embed `package fmt;` — fmt is not in the dep graph of any selfhost binary. combined_ww_fresh stays green untouched. 210/210 tests passing (was 209; +1 for 777_fmt_vstream_run).
This commit is contained in:
8
Makefile
8
Makefile
@@ -327,6 +327,7 @@ TESTS = $(BIN)/test_smoke $(BIN)/test_lex $(BIN)/test_parse $(BIN)/test_check \
|
||||
$(BIN)/test_tagged_widen_named_variant \
|
||||
$(BIN)/test_io_vtable_run \
|
||||
$(BIN)/test_memio_vstream_run \
|
||||
$(BIN)/test_fmt_vstream_run \
|
||||
$(BIN)/test_use_promote_alias \
|
||||
$(BIN)/test_field_signed $(BIN)/test_frame_argcount \
|
||||
$(BIN)/test_selfhost $(BIN)/test_w6a_ww $(BIN)/test_w6l_ww \
|
||||
@@ -696,6 +697,13 @@ $(BIN)/test_memio_vstream_run: test/wcc/776_memio_vstream_run.c \
|
||||
$(LIB)/libwwrt.a | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BIN)/test_fmt_vstream_run: test/wcc/777_fmt_vstream_run.c \
|
||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
||||
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
|
||||
lib/fmt/fmt.ww lib/fmt/vstream.ww \
|
||||
$(LIB)/libwwrt.a | $(BIN)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
$(BIN)/test_arrlit_str_full: test/wcc/711_arrlit_str_full.c \
|
||||
$(BIN)/ww $(BIN)/w6c $(BIN)/w6a $(BIN)/w6l \
|
||||
$(BIN)/ww_ww $(BIN)/w6c_ww $(BIN)/w6a_ww $(BIN)/w6l_ww \
|
||||
|
||||
Reference in New Issue
Block a user