nx_primitive_synth.nx
buildroot/runtime/nx_primitive_synth.nx
about
nx_synth.nx -- substrate-native per-primitive synthesizer.
Per user directive 2026-05-14: "i want you building nishilang to
the point it can [ingest algorithms and create primitives]" -- the
substrate must be the actor, not bash.
Reads nxc2/specs/algo_corpus.txt (TSV: name, module, shape, summary,
KEY=VAL ...) and emits substituted .nx impl + test files under
nxc2/runtime/ using shape templates in nxc2/specs/algo_shapes/<shape>/.
Design rules:
- Every mmap happens at startup; the per-row loop allocates ZERO.
- One open output file at a time, stream sys_write per chunk.
No 16 MiB write buffer to accumulate state across primitives.
- Hard cap NX_SYNTH_MAX_PRIMITIVES per run.
- Wired through nx_disk_budget for graceful halt on disk pressure.
- Function signatures kept <= 8 params (until nxc2 supports stack-passed
args 9+). Cross-function state packed via NxSynthCtx.
genealogy_id: substrate_self_hosting_synth_2026_05_14
lineage_id: per_primitive_emit_no_batch
dependencies 5 imports · 0 importers
imports: nx_syscalls.nxnx_runtime.nxnx_tier.nxnx_fcntl.nxnx_disk_budget.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 207 | struct NxSynthCtx |
consts
| 41 | const NX_SYNTH_MAX_PRIMITIVES: nx_int = 200 |
| 42 | const NX_SYNTH_DISK_BUDGET: nx_size = 16777216 |
| 44 | const NX_SYNTH_PATH_BUF: nx_size = 256 |
| 45 | const NX_SYNTH_NAME_LEN: nx_size = 64 |
| 46 | const NX_SYNTH_TPL_CAP: nx_size = 32768 |
| 47 | const NX_SYNTH_KV_CAP: nx_int = 32 |
| 48 | const NX_SYNTH_KV_KEY: nx_size = 64 |
| 49 | const NX_SYNTH_KV_VAL: nx_size = 512 |
| 51 | const NX_SYNTH_TAB: nx_int = 9 |
| 52 | const NX_SYNTH_NL: nx_int = 10 |
| 53 | const NX_SYNTH_EQ: nx_int = 61 |
| 54 | const NX_SYNTH_LBRACE: nx_int = 123 |
| 55 | const NX_SYNTH_RBRACE: nx_int = 125 |
| 216 | const NX_SYNTH_CTX_BYTES: nx_size = 48 |
functions
| 59 | func sy_strlen(s: *u8) -> nx_size |
| 65 | func sy_str_eq(a: *u8, b: *u8) -> nx_int |
| 75 | func sy_str_cpy(dst: *u8, src: *u8) -> nx_size |
| 85 | func sy_str_cat(dst: *u8, off: nx_idx, src: *u8) -> nx_idx |
| 97 | func sy_find_byte(corpus: *u8, start: nx_idx, end: nx_idx, c: nx_int) -> nx_idx |
| 110 | func sy_find_byte2(corpus: *u8, start: nx_idx, end: nx_idx, c1: nx_int, c2: nx_int) -> nx_idx called by 1: sy_parse_row |
| 124 | func sy_copy_range(corpus: *u8, lo: nx_idx, hi: nx_idx, dst: *u8, cap: nx_size) -> nx_size |
| 142 | func sy_parse_row( |
| 190 | func sy_lookup(keys_buf: *u8, vals_buf: *u8, n_kv: nx_size, key: *u8, out: *u8) -> nx_int |
| 220 | func sy_emit_substituted(tpl: *u8, tpl_n: nx_size, ctx: *NxSynthCtx, fd: nx_fd) -> nx_int |
| 292 | func sy_load_shape_file( |
| 318 | func main() -> nx_exit |