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}