wcc: drop @test fns from non-T builds, both stages (harec check.c:3941)

Splice @test N_FNDECLs out of the unit after the body-check passes,
mirroring harec's checked-but-not-emitted: a broken @test body still
errors loudly in non-T; @test-free units are emission-unchanged.
910/997 table rows pin keep/test x non-T/-T, head+consecutive unlink,
undef-body reject, and plain-calls-dropped loud link-fail. w6c+wwdump
combined.ww regen. (#6-team)
This commit is contained in:
2026-06-10 22:20:15 +09:00
parent 7470b1a5c3
commit 08a76cf4c8
10 changed files with 442 additions and 4 deletions

View File

@@ -3228,4 +3228,38 @@ check_file(Checker *c, Node *file)
}
}
c->cur_mod = NULL;
/*
* #6 harec-fidelity (ref/harec/src/check.c:3941): a @test fn is
* fully checked above — pass 2 walked its body like every fn — but
* is NOT emitted in a non-test build. harec skips append_decl for
* FN_TEST && !is_test, so the fn never reaches unit->declarations
* (the list codegen walks); the body is still type-checked, only the
* emission is dropped. ww shares one file->list across check + cgen
* (no separate checked-decl list, project_hare_ast_no_result), so we
* splice the already-checked @test fns out here, after pass 2 — they
* stay checked, never reach cg_file. The -T path is untouched: its
* synth main calls the @test fns, so they must remain. Prereq for
* in-package @test colocation (#9). Twin: selfhost/cmd/wcc/check.ww.
*/
if (!c->is_test) {
Node *prev = NULL;
for (Node *d = file->list; d; ) {
int istest = 0;
if (d->kind == N_FNDECL)
for (Node *at = d->attr; at; at = at->next)
if (at->str
&& strcmp(at->str, "test") == 0) {
istest = 1;
break;
}
Node *nx = d->next;
if (istest) {
if (prev == NULL) file->list = nx;
else prev->next = nx;
} else
prev = d;
d = nx;
}
}
}