code wiki / (root) / nx_template_instantiate.nx

nx_template_instantiate.nx source

↩ module page · 462 lines · 16880 B

1// nx_template_instantiate.nx -- substrate-native template engine. 2// 3// For each registry entry that declares a "shape" field, read the 4// corresponding template under specs/algo_shapes/<shape>/, substitute 5// {{PLACEHOLDER}} tokens with values from the meta.json's 6// "template_params" object, write the result to impl.nx + test.nx. 7// 8// This is the SELF-SUFFICIENCY dependency: new algorithms in a known 9// shape need ONLY metadata (no body) -- substrate emits the impl. 10// 11// Recognized placeholder tokens (any name in {{UPPER_CASE}} is replaced 12// from template_params). {{NX_MODULE}} is always replaced with the 13// meta's "nx_module" value. 14// 15// genealogy_id: substrate_template_engine_2026_05_13 16// lineage_id: codegen_via_substitution 17// license: public_domain 18 19// nx_safety_envelope: 20// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 21// sil_target: SIL1 22// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 23// verdict: NOT_YET_EVALUATED 24 25import "nx_syscalls.nx" 26import "nx_runtime.nx" 27import "nx_tier.nx" 28import "nx_dirent.nx" 29import "nx_fcntl.nx" 30const NX_MAGIC_16384: i64 = 16384 31 32const STDOUT: i64 = 1 33const NX_TPL_PATH_BUF: nx_size = 512 34const NX_TPL_VAL_CAP: nx_size = 512 35const NX_TPL_BUF_CAP: nx_size = 16384 36 37// ===== utilities ======================================================= 38 39func write_str_to_fd(fd: i64, s: *u8) -> nx_int { 40 let n: nx_size = strlen(s) 41 sys_write(fd, s, n) 42 return 0 43} 44 45func write_all2(fd: i64, buf: *u8, n: nx_size) -> nx_size { 46 var w: nx_size = 0 47 while w < n { 48 let p: *u8 = ((buf as i64) + w) as *u8 49 let m: i64 = sys_write(fd, p, n - w) 50 if m <= 0 { return w } 51 w = w + m 52 } 53 return w 54} 55 56// Find substring `needle` in haystack[start..n). Returns offset or -1. 57func find_substr2(buf: *u8, start: nx_idx, n: nx_size, needle: *u8, nlen: nx_size) -> nx_idx { 58 if nlen == 0 { return start } 59 var p: nx_idx = start 60 let last: nx_idx = n - nlen 61 while p <= last { 62 var j: nx_idx = 0 63 var hit: nx_int = 1 64 while j < nlen { 65 if buf[p + j] != needle[j] { hit = 0; j = nlen } 66 j = j + 1 67 } 68 if hit == 1 { return p } 69 p = p + 1 70 } 71 return -1 72} 73 74// Find pattern `"<key>": "<value>"` (whitespace-tolerant) inside meta JSON. 75// Same logic as nx_register_algo.read_field but lifted here so this 76// program is self-contained. Returns value length (0 if not found). 77func read_meta_field(buf: *u8, n: nx_size, key: *u8, out: *u8, out_cap: nx_size) -> nx_size { 78 let pat: *u8 = sys_mmap(128) 79 var po: nx_idx = 0 80 pat[po] = 34; po = po + 1 81 var ki: nx_idx = 0 82 while key[ki] != 0 { pat[po] = key[ki]; po = po + 1; ki = ki + 1 } 83 pat[po] = 34; po = po + 1 84 pat[po] = 58; po = po + 1 85 pat[po] = 0 86 87 let p: nx_idx = find_substr2(buf, 0, n, pat, po) 88 if p < 0 { out[0] = 0; return 0 } 89 var q: nx_idx = p + po 90 var done_ws: nx_int = 0 91 while done_ws == 0 { 92 if q >= n { out[0] = 0; return 0 } 93 let c: nx_int = buf[q] as nx_int 94 if c == 32 { q = q + 1 } 95 if c == 9 { q = q + 1 } 96 if c == 10 { q = q + 1 } 97 if c == 13 { q = q + 1 } 98 if c == 34 { done_ws = 1 } 99 if c != 32 { if c != 9 { if c != 10 { if c != 13 { if c != 34 { 100 out[0] = 0 101 return 0 102 }}}}} 103 } 104 q = q + 1 105 var out_len: nx_size = 0 106 while q < n { 107 let c2: nx_int = buf[q] as nx_int 108 if c2 == 34 { out[out_len] = 0; return out_len } 109 if out_len < out_cap - 1 { 110 out[out_len] = buf[q] 111 out_len = out_len + 1 112 } 113 q = q + 1 114 } 115 out[out_len] = 0 116 return out_len 117} 118 119// Substitute every {{TOKEN}} in src into dst, reading replacement values 120// from the `params_section` byte range of the meta buffer (the JSON sub- 121// object enclosed in `"template_params": { ... }`). 122// 123// Algorithm: scan src for `{{`; when found, scan to matching `}}` to 124// extract the token name; look up `"<token>"` in params_section using 125// read_meta_field; write the value to dst. Tokens not found are passed 126// through verbatim with the braces. 127func substitute_template(src: *u8, src_n: nx_size, 128 params: *u8, params_n: nx_size, 129 nx_module: *u8, 130 dst: *u8) -> nx_size { 131 let token: *u8 = sys_mmap(64) 132 let value: *u8 = sys_mmap(NX_TPL_VAL_CAP) 133 var i: nx_idx = 0 134 var o: nx_idx = 0 135 while i < src_n { 136 // Look for {{ 137 if i + 2 <= src_n { 138 if src[i] == 123 { 139 if src[i + 1] == 123 { 140 // Found {{ -- find closing }} 141 var j: nx_idx = i + 2 142 var found_close: nx_int = 0 143 while j + 1 < src_n { 144 if src[j] == 125 { 145 if src[j + 1] == 125 { found_close = 1; j = src_n + 1 } 146 } 147 if found_close == 0 { j = j + 1 } 148 } 149 if found_close == 1 { 150 // j+1 was set to src_n+1 to break; recover j as closing-pos 151 // We need the closing position; re-scan. 152 var jj: nx_idx = i + 2 153 var done_scan: nx_int = 0 154 while done_scan == 0 { 155 if jj + 1 >= src_n { done_scan = 1 } 156 if done_scan == 0 { 157 if src[jj] == 125 { 158 if src[jj + 1] == 125 { done_scan = 1 } 159 } 160 if done_scan == 0 { jj = jj + 1 } 161 } 162 } 163 // Extract token name 164 var tn: nx_idx = 0 165 var k: nx_idx = i + 2 166 while k < jj { 167 if tn < 63 { token[tn] = src[k]; tn = tn + 1 } 168 k = k + 1 169 } 170 token[tn] = 0 171 // Look up: special-case {{NX_MODULE}}, else use params section 172 var vlen: nx_size = 0 173 if strneq(token, "NX_MODULE" as *u8, tn) == 1 { 174 var vi: nx_idx = 0 175 while nx_module[vi] != 0 { 176 value[vi] = nx_module[vi] 177 vi = vi + 1 178 } 179 value[vi] = 0 180 vlen = vi 181 } 182 if vlen == 0 { 183 vlen = read_meta_field(params, params_n, token, value, NX_TPL_VAL_CAP) 184 } 185 if vlen > 0 { 186 // Emit value 187 var vi2: nx_idx = 0 188 while vi2 < vlen { 189 dst[o] = value[vi2] 190 o = o + 1 191 vi2 = vi2 + 1 192 } 193 i = jj + 2 194 } 195 if vlen == 0 { 196 // Pass through unchanged 197 dst[o] = src[i]; o = o + 1; i = i + 1 198 } 199 } 200 if found_close == 0 { 201 dst[o] = src[i]; o = o + 1; i = i + 1 202 } 203 } 204 } 205 } 206 if i < src_n { 207 if src[i] != 123 { 208 dst[o] = src[i] 209 o = o + 1 210 i = i + 1 211 } 212 if src[i] == 123 { 213 if i + 1 < src_n { 214 if src[i + 1] != 123 { 215 dst[o] = src[i] 216 o = o + 1 217 i = i + 1 218 } 219 } 220 if i + 1 >= src_n { 221 dst[o] = src[i] 222 o = o + 1 223 i = i + 1 224 } 225 } 226 } 227 } 228 dst[o] = 0 229 return o 230} 231 232// Extract the template_params sub-object as a raw byte slice from 233// meta.json. Returns the slice length; writes pointer into *out_start. 234// Simple: find `"template_params"`, scan to `{`, scan to matching `}`. 235func extract_params_slice(meta: *u8, meta_n: nx_size, out_start: *i64) -> nx_size { 236 let key: *u8 = "\"template_params\"" as *u8 237 let klen: nx_size = strlen(key) 238 let p: nx_idx = find_substr2(meta, 0, meta_n, key, klen) 239 if p < 0 { return 0 } 240 // Scan to `{` 241 var q: nx_idx = p + klen 242 while q < meta_n { 243 if meta[q] == 123 { q = q + 1; out_start[0] = q; q = meta_n } 244 if q < meta_n { if meta[q] != 123 { q = q + 1 } } 245 } 246 if out_start[0] == 0 { return 0 } 247 // Quote-aware brace match. Guard `advanced` keeps the in_string 248 // branches mutually exclusive -- a closing `"` flipping in_string 249 // to 0 must NOT immediately re-enter the in_string==0 branch in 250 // the same iteration (else strings re-open and the scan loops). 251 var r: nx_idx = out_start[0] 252 var in_string: nx_int = 0 253 var depth: nx_int = 1 254 while r < meta_n { 255 let c: nx_int = meta[r] as nx_int 256 var advanced: nx_int = 0 257 if in_string == 1 { 258 if c == 92 { // backslash: skip next char too 259 r = r + 2 260 advanced = 1 261 } 262 if advanced == 0 { 263 if c == 34 { in_string = 0 } 264 r = r + 1 265 advanced = 1 266 } 267 } 268 if advanced == 0 { 269 if c == 34 { in_string = 1 } 270 if c == 123 { depth = depth + 1 } 271 if c == 125 { 272 depth = depth - 1 273 if depth == 0 { return r - out_start[0] } 274 } 275 r = r + 1 276 } 277 } 278 return 0 279} 280 281// Instantiate one shape entry: read meta, read template, substitute, 282// write to specs/algo_registry/<entry>/impl.nx + test.nx. 283// Returns 1 on success, 0 on skip (no shape), -1 on error. 284func instantiate_shape_entry(entry_name: *u8) -> nx_int { 285 let path: *u8 = sys_mmap(NX_TPL_PATH_BUF) 286 var o: nx_idx = 0 287 o = 0 288 o = o + 0 // helper: o = str_cat-equivalent 289 // Build meta_path 290 let prefix: *u8 = "nxc2/specs/algo_registry/" as *u8 291 var pi: nx_idx = 0 292 while prefix[pi] != 0 { path[o + pi] = prefix[pi]; pi = pi + 1 } 293 o = o + pi 294 var ei: nx_idx = 0 295 while entry_name[ei] != 0 { path[o + ei] = entry_name[ei]; ei = ei + 1 } 296 o = o + ei 297 let suffix: *u8 = "/meta.json" as *u8 298 var si: nx_idx = 0 299 while suffix[si] != 0 { path[o + si] = suffix[si]; si = si + 1 } 300 o = o + si 301 path[o] = 0 302 303 let meta_len: *i64 = (sys_mmap(8)) as *i64 304 meta_len[0] = 0 305 let meta_buf: *u8 = sys_read_file(path, meta_len) 306 if (meta_buf as i64) == 0 { return -1 } 307 let meta_n: nx_size = meta_len[0] 308 309 // Check for "shape" field 310 let shape: *u8 = sys_mmap(64) 311 let shape_n: nx_size = read_meta_field(meta_buf, meta_n, "shape" as *u8, shape, 64) 312 if shape_n == 0 { return 0 } 313 314 // Get nx_module 315 let nx_module: *u8 = sys_mmap(128) 316 read_meta_field(meta_buf, meta_n, "nx_module" as *u8, nx_module, 128) 317 318 // Extract template_params slice 319 let params_start: *i64 = (sys_mmap(8)) as *i64 320 params_start[0] = 0 321 let params_n: nx_size = extract_params_slice(meta_buf, meta_n, params_start) 322 if params_n == 0 { return -1 } 323 let params: *u8 = ((meta_buf as i64) + params_start[0]) as *u8 324 325 // Read shape template 326 let tpl_path: *u8 = sys_mmap(NX_TPL_PATH_BUF) 327 o = 0 328 let tp1: *u8 = "nxc2/specs/algo_shapes/" as *u8 329 var t1i: nx_idx = 0 330 while tp1[t1i] != 0 { tpl_path[o + t1i] = tp1[t1i]; t1i = t1i + 1 } 331 o = o + t1i 332 var sh_i: nx_idx = 0 333 while shape[sh_i] != 0 { tpl_path[o + sh_i] = shape[sh_i]; sh_i = sh_i + 1 } 334 o = o + sh_i 335 let tp2: *u8 = "/template.nx" as *u8 336 var t2i: nx_idx = 0 337 while tp2[t2i] != 0 { tpl_path[o + t2i] = tp2[t2i]; t2i = t2i + 1 } 338 o = o + t2i 339 tpl_path[o] = 0 340 341 let tpl_len: *i64 = (sys_mmap(8)) as *i64 342 tpl_len[0] = 0 343 let tpl_buf: *u8 = sys_read_file(tpl_path, tpl_len) 344 if (tpl_buf as i64) == 0 { return -1 } 345 let tpl_n: nx_size = tpl_len[0] 346 347 let out_buf: *u8 = sys_mmap(NX_TPL_BUF_CAP) 348 let out_n: nx_size = substitute_template(tpl_buf, tpl_n, params, params_n, nx_module, out_buf) 349 350 // Write impl.nx 351 let impl_path: *u8 = sys_mmap(NX_TPL_PATH_BUF) 352 o = 0 353 var pi2: nx_idx = 0 354 while prefix[pi2] != 0 { impl_path[o + pi2] = prefix[pi2]; pi2 = pi2 + 1 } 355 o = o + pi2 356 var ei2: nx_idx = 0 357 while entry_name[ei2] != 0 { impl_path[o + ei2] = entry_name[ei2]; ei2 = ei2 + 1 } 358 o = o + ei2 359 let suf2: *u8 = "/impl.nx" as *u8 360 var si2: nx_idx = 0 361 while suf2[si2] != 0 { impl_path[o + si2] = suf2[si2]; si2 = si2 + 1 } 362 o = o + si2 363 impl_path[o] = 0 364 let fd_impl: i64 = nx_open_wr(impl_path) 365 if fd_impl < 0 { return -1 } 366 write_all2(fd_impl, out_buf, out_n) 367 sys_close(fd_impl) 368 369 // Read + substitute test template 370 let tpl2_path: *u8 = sys_mmap(NX_TPL_PATH_BUF) 371 o = 0 372 var p3i: nx_idx = 0 373 while tp1[p3i] != 0 { tpl2_path[o + p3i] = tp1[p3i]; p3i = p3i + 1 } 374 o = o + p3i 375 var sh2_i: nx_idx = 0 376 while shape[sh2_i] != 0 { tpl2_path[o + sh2_i] = shape[sh2_i]; sh2_i = sh2_i + 1 } 377 o = o + sh2_i 378 let tp3: *u8 = "/test_template.nx" as *u8 379 var t3i: nx_idx = 0 380 while tp3[t3i] != 0 { tpl2_path[o + t3i] = tp3[t3i]; t3i = t3i + 1 } 381 o = o + t3i 382 tpl2_path[o] = 0 383 let tpl2_len: *i64 = (sys_mmap(8)) as *i64 384 tpl2_len[0] = 0 385 let tpl2_buf: *u8 = sys_read_file(tpl2_path, tpl2_len) 386 if (tpl2_buf as i64) != 0 { 387 let tpl2_n: nx_size = tpl2_len[0] 388 let out2_buf: *u8 = sys_mmap(NX_TPL_BUF_CAP) 389 let out2_n: nx_size = substitute_template(tpl2_buf, tpl2_n, params, params_n, nx_module, out2_buf) 390 let test_path: *u8 = sys_mmap(NX_TPL_PATH_BUF) 391 o = 0 392 var p4i: nx_idx = 0 393 while prefix[p4i] != 0 { test_path[o + p4i] = prefix[p4i]; p4i = p4i + 1 } 394 o = o + p4i 395 var e3i: nx_idx = 0 396 while entry_name[e3i] != 0 { test_path[o + e3i] = entry_name[e3i]; e3i = e3i + 1 } 397 o = o + e3i 398 let suf3: *u8 = "/test.nx" as *u8 399 var s3i: nx_idx = 0 400 while suf3[s3i] != 0 { test_path[o + s3i] = suf3[s3i]; s3i = s3i + 1 } 401 o = o + s3i 402 test_path[o] = 0 403 let fd_test: i64 = nx_open_wr(test_path) 404 if fd_test >= 0 { 405 write_all2(fd_test, out2_buf, out2_n) 406 sys_close(fd_test) 407 } 408 } 409 return 1 410} 411 412func main() -> i64 { 413 let fd: i64 = nx_openat(NX_AT_FDCWD, "nxc2/specs/algo_registry" as *u8, 414 NX_O_RDONLY | NX_O_DIRECTORY, 0) 415 if fd < 0 { 416 let err: *u8 = "error: cannot open algo_registry dir\n" as *u8 417 sys_write(STDOUT, err, strlen(err)) 418 return 1 419 } 420 421 let buf: *u8 = sys_mmap(NX_MAGIC_16384) 422 let dr_raw: *u8 = sys_mmap(NX_DIRENT_BYTES) 423 let dr: *NxDirent = dr_raw as *NxDirent 424 var n_inst: nx_int = 0 425 var n_skip: nx_int = 0 426 427 var batch: i64 = nx_dirent_read(fd, buf, NX_MAGIC_16384) 428 while batch > 0 { 429 var off: i64 = 0 430 while off < batch { 431 let next_off: i64 = nx_dirent_iter(buf, off, batch, dr) 432 if next_off <= 0 { off = batch + 1 } 433 if off <= batch { 434 let nm_len: nx_size = nx_dirent_name_len(dr) 435 var is_dot: nx_int = 0 436 if nm_len == 1 { if dr.name[0] == 46 { is_dot = 1 } } 437 if nm_len == 2 { if dr.name[0] == 46 { if dr.name[1] == 46 { is_dot = 1 } } } 438 if is_dot == 0 { 439 let r: nx_int = instantiate_shape_entry(dr.name) 440 if r == 1 { 441 n_inst = n_inst + 1 442 sys_write(STDOUT, " instantiated: " as *u8, 16) 443 sys_write(STDOUT, dr.name, nm_len) 444 sys_write(STDOUT, "\n" as *u8, 1) 445 } 446 if r == 0 { n_skip = n_skip + 1 } 447 } 448 off = next_off 449 } 450 } 451 batch = nx_dirent_read(fd, buf, NX_MAGIC_16384) 452 } 453 sys_close(fd) 454 let msg: *u8 = "nx_template_instantiate: instantiated=" as *u8 455 sys_write(STDOUT, msg, strlen(msg)) 456 print_i64(n_inst) 457 let msg2: *u8 = " skipped(no-shape)=" as *u8 458 sys_write(STDOUT, msg2, strlen(msg2)) 459 print_i64(n_skip) 460 sys_write(STDOUT, "\n" as *u8, 1) 461 return 0 462}