code wiki / _hdl_build / nx_emit_guard.nx

nx_emit_guard.nx source

↩ module page · 61 lines · 2507 B

1// nx_emit_guard.nx -- the ONE set of guards every emitter CLI in this lane uses (rule 15: written twice 2// is once too many, and these encode a LAW rather than a convenience). 3// 4// ★WHY: an emitter that writes a SET of files can fail in three ways that all LOOK like success -- 5// 1. an unchecked sys_mmap returns null, so every subsequent write goes nowhere; 6// 2. the emitter produces a technically-valid but empty page (a few dozen bytes); 7// 3. individual writes are checked, but nobody asks afterwards whether the SET actually exists. 8// (3) is the one that bit this lane: refine's per-file writes were fail-loud, yet a run that produced 9// zero files still printed a success envelope, because nothing verified the set. A tool that emits a set 10// must PROVE the set before it claims success. Dependency-light on purpose (nx_syscalls only) so any 11// emitter can compose it without dragging a page kit in. license_tier: ORIGINAL 12import "nx_syscalls.nx" 13 14// a real generated page is >=13KB in this lane; anything under this floor means the emitter produced 15// nothing usable and the run must abort rather than write a husk. 16const EG_MIN_PAGE: i64 = 2000 17 18func eg_say(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(2, s, n); return 0 } 19 20// allocate or die loudly. `what` names the buffer so the failure says which one. 21func eg_buf(size: i64, what: *u8) -> *u8 { 22 let p: *u8 = sys_mmap(size) 23 if (p as i64) == 0 { 24 eg_say("EMIT-GUARD FAIL: allocation returned null for " as *u8) 25 eg_say(what) 26 eg_say("\n" as *u8) 27 sys_exit(6) 28 } 29 return p 30} 31 32// a page shorter than the floor is a husk, not a page. 33func eg_assert_size(len: i64, what: *u8) -> i64 { 34 if len < EG_MIN_PAGE { 35 eg_say("EMIT-GUARD FAIL: emitted artifact is impossibly small: " as *u8) 36 eg_say(what) 37 eg_say("\n" as *u8) 38 sys_exit(7) 39 } 40 return len 41} 42 43// does this path open for reading? 44func eg_have(path: *u8) -> i64 { 45 let fd: i64 = sys_openat_rd(path) 46 if fd < 0 { return 0 } 47 sys_close(fd) 48 return 1 49} 50 51// THE SET ASSERTION: the caller loops its planned outputs through this before printing success. 52// A run that wrote nothing now exits 8 instead of reporting a job well done. 53func eg_assert_present(path: *u8) -> i64 { 54 if eg_have(path) == 0 { 55 eg_say("EMIT-GUARD FAIL: post-write check, missing " as *u8) 56 eg_say(path) 57 eg_say("\n" as *u8) 58 sys_exit(8) 59 } 60 return 1 61}