code wiki / (root) / nx_normdiff.nx

nx_normdiff.nx

buildroot/runtime/nx_normdiff.nx

72638 B1551 linesdepth 2pulls 2 transitivereach 0 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_normdiff.nx -- IS THIS DIFFERENCE MADE OF CODE, OR OF COSMETICS? The escalation ruler. WHY IT EXISTS. nx_srcdiff answers "is a direction merge safe?" on the RAW line multiset, and that strictness is correct as a GUARD -- it is what caught the escaped nx_media_extract mutant that a symbol-set ruler waved through. But as a CENSUS it overstates the fork: it reports BIDIRECTIONAL for two files that differ only because a NAS cron lifted `4096` into `FOO_MAGIC_4096`, or because one side carries a trailing `// why` comment the other lacks. Measured on the standing residual: the raw ruler could decide 3.6% of 3,073 forked files; normalising first decides 8.6%. The other 91% is REAL CODE -- surplus shapes censused as control-flow 1408, bindings 1042, func-decls 278 -- which is the finding that matters most: NO FURTHER NORMALISER WILL CRACK IT, so stop building them. => ★A RULER TUNED TO BE A SAFE GUARD IS THE WRONG RULER FOR A CENSUS. Report BOTH verdicts and let the caller pick: the guard decides whether to ACT, the census decides what to LOOK AT. WHAT IT NORMALISES, and nothing else: 1. a trailing `//` comment -- ONLY when outside a string literal (backslash-escape aware, so `"http://x"` and `"a\"b // c"` are not mistaken for comments) 2. runs of whitespace -> one space; leading/trailing stripped 3. a const identifier -> ITS DECLARED VALUE TEXT, read out of the file that declares it. !!THE OBVIOUS SHORTCUT IS UNSOUND, measured: reading the digits out of `FOO_MAGIC_4096` breaks on nx_lz4_header's `const LZ4_MAGIC_0: i64 = 0x04` and nx_nxtask_store's `NXT_MAGIC_0 = 0x4E`. There the trailing digit is a FIELD INDEX ("magic byte 0"), and the value is an unrelated hex byte. A name-digit un-lift equates 0 with 4 and calls two different files identical. ⇒ ★A NAMING CONVENTION IS A COMMENT: IT IS EVIDENCE ABOUT INTENT, NEVER ABOUT VALUE. The value is substituted as its DECLARED TEXT, verbatim and unparsed. That is deliberate: a parser that "helpfully" normalised 0x04 to 4 would need to be right about every literal form in the language, and being wrong about one is how the line above got mis-measured TWICE (a decimal regex silently matched the `0` out of `0x04` and reported the const as declared zero). ⇒ ★DON'T PARSE WHAT YOU ONLY NEED TO COMPARE. WHERE THE TABLE COMES FROM, and why there is no tree walk here: NishiLang requires consts above use, and the NAS magicsweep lifts a literal into a const IN THE SAME FILE. Measured across both trees: 3,728 of 3,730 lifted-const uses (99.946%) are declared in the file that uses them -- the only two exceptions tree-wide are nx_archive_server's K_MAGIC_8080 and nx_web_crawl_step_gate's WC_MAGIC_2048. So each side's table is built FROM THAT SIDE'S OWN SOURCE, which is also the semantically correct scope: a const means what ITS file declares it to mean. Two files that declare the same name differently therefore normalise DIFFERENTLY and stay visible as surplus, which a single shared table would have silently equated. ⇒ ★A SYMBOL'S MEANING IS SCOPED; A LOOKUP TABLE THAT FORGETS THE SCOPE INVENTS AGREEMENT. [consttab] remains as an optional FALLBACK for the cross-file residual; file-local always wins.

dependencies 1 imports · 0 importers

nx_syscalls.nx nx_normdiff.nx

imports: nx_syscalls.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main sys_mmap nxa_die sys_write sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ nd_puts sys_write ↻ sys_exit ↻ nd_is_adopt nd_is_apply nd_adopt sys_mmap ↻ sys_read_file sys_openat_rd sys_lseek sys_mmap ↻ sys_read sys_munmap sys_close nd_puts ↻ sys_exit ↻ sys_openat_wr nd_join_root nd_run_pair sys_read_file ↻ nd_puts ↻ sys_exit ↻ nd_scan_consts nd_is_id_char

structs

none

consts

58const ND_MAGIC_8192: i64 = 8192
60const ND_SLOTS: i64 = 131072 // power of two; a 1000-line file loads at <1% -- headroom is cheap
61const ND_MASK: i64 = 131071
62const ND_OUTBUF: i64 = 4194304
63const ND_NUMBUF: i64 = 64
64const ND_TOK: i64 = 512 // longest identifier we will try to resolve
65const ND_ARENA: i64 = 8388608 // fixed per-side arena for census mode; a source over this is REFUSED, never truncated
66const ND_SURP_CAP: i64 = 16384 // surplus lines tracked per side for the supersede match
67const ND_MAXIMP: i64 = 128 // direct imports followed; a .nx file today declares <20
68const ND_BCL_CAP: i64 = 65536 // B comment-sites tracked; a 1000-line file uses <2%
69const ND_SLACK: i64 = 65536 // normalise can only shrink a line, but never trust that alone
70const ND_FNV_OFF: i64 = 1469598103934665603
71const ND_FNV_PRIME: i64 = 1099511628211
72const ND_SAMPLE_CAP: i64 = 25 // stdout sample; the FULL surplus list always goes to [outfile]
73const ND_LF: i64 = 10
74const ND_CR: i64 = 13
75const ND_TAB: i64 = 9
76const ND_SP: i64 = 32
77const ND_SLASH: i64 = 47
78const ND_QUOTE: i64 = 34
79const ND_BSLASH: i64 = 92
80const ND_USCORE: i64 = 95

functions

149func nd_puts(s: *u8) -> i64
155func nd_putn(v: i64) -> i64
166func nd_streq(a: *u8, b: *u8) -> i64
177func nd_hash(s: *u8) -> i64
188func nd_add(keys: *i64, counts: *i64, gen: *i64, line: *u8) -> i64
203func nd_get(keys: *i64, counts: *i64, gen: *i64, line: *u8) -> i64
called by 1: nd_run_pair calls 2: nd_hashnd_streq
216func nd_put_kv(keys: *i64, vals: *i64, gen: *i64, k: *u8, v: *u8) -> i64
227func nd_get_kv(keys: *i64, vals: *i64, gen: *i64, k: *u8) -> i64
238func nd_is_id_char(c: i64) -> i64
245func nd_is_id_start(c: i64) -> i64
called by 1: nd_norm
254func nd_comment_at(src: *u8) -> i64
called by 2: nd_normnd_load
281func nd_len(s: *u8) -> i64
289func nd_norm(src: *u8, dst: *u8, ctk: *i64, ctv: *i64, ctg: *i64) -> i64
348func nd_scan_consts(buf: *u8, n: i64, ctk: *i64, ctv: *i64, ctg: *i64) -> i64
453func nd_scan_imports(buf: *u8, n: i64) -> i64
called by 1: nd_run_pair
519func nd_is_dash(s: *u8) -> i64
called by 1: nd_run_pair
525func nd_join_root(root: *u8, name: *u8, out: *u8) -> i64
536func nd_join_dir(path: *u8, name: *u8, out: *u8) -> i64
called by 1: nd_run_pair
554func nd_fold_module(path: *u8) -> i64
630func nd_is_import(l: *u8) -> i64
called by 1: nd_supersedes
641func nd_supersedes(a: *u8, b: *u8) -> i64
686func nd_selftest() -> i64
called by 1: nd_run_pair calls 1: nd_supersedes
708func nd_emit(tag: *u8, n: i64, line: *u8) -> i64
called by 2: nd_lost_commentsnd_run_pair calls 1: nd_len
731func nd_sample(tag: *u8, n: i64, line: *u8) -> i64
called by 1: nd_run_pair calls 2: nd_putsnd_putn
741func nd_load(buf: *u8, n: i64, rk: *i64, rc: *i64, rg: *i64, side: i64) -> i64
821func nd_lost_comments() -> i64
called by 1: nd_run_pair calls 3: nd_get_kvnd_putsnd_emit
838func nd_load_consttab(path: *u8) -> i64
882func nd_run_pair(apath: *u8, bpath: *u8, iroot: *u8, quiet: i64, argc: i64, argv: *i64) -> i64
1218func nd_copy_atomic(src: *u8, dst: *u8) -> i64
1250func nd_is_adopt(s: *u8) -> i64
called by 1: main
1259func nd_is_apply(s: *u8) -> i64
called by 1: main
1266func nd_is_census(s: *u8) -> i64
called by 1: main
1288func nd_adopt(listp: *u8, aroot: *u8, broot: *u8, iroot: *u8, apply: i64) -> i64
1375func nd_census(listp: *u8, aroot: *u8, broot: *u8, iroot: *u8) -> i64
1427func main(argc: i64, argv: *i64) -> i64