code wiki / _hdl_build / nx_func_compare.nx

nx_func_compare.nx source

↩ module page · 122 lines · 3955 B

1// nx_func_compare.nx -- pure-NishiLang function-equivalence checker. 2// 3// Usage: 4// nx_func_compare <file1> <file2> [<file3> ...] <function_name> 5// 6// For each file, extract the named function's body, normalize away 7// comments and whitespace, compute FNV-1a 64-bit hash. Emit per-file 8// hash + verdict. 9// 10// Verdict EQUIVALENT if all hashes match exactly. 11// Verdict DIVERGE otherwise -- with first hash + first-diff file flagged. 12// 13// This is the substrate-native answer to "are these N functions 14// actually the same?" before consolidation. No grep, no awk, no diff. 15// 16// genealogy_id: fowler_noll_vo_1991_fnv1a + clone_detection_lit 17// lineage_id: content_hash_equivalence_test 18// axioms: NX_AX_REL_TRANSITIVITY (chain hash equalities) 19 20// nx_safety_envelope: 21// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 22// sil_target: SIL1 23// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 24// verdict: NOT_YET_EVALUATED 25 26import "syscalls.nx" 27import "runtime.nx" 28import "nx_extract.nx" 29 30const NX_CMP_NORM_BUF: i64 = 65536 31 32// Emit JSONL summary for one file's function. 33func compare_emit_file(file: *u8, fname: *u8, h: i64) -> i64 { 34 print("{\"file\":\"" as *u8) 35 print(file) 36 print("\",\"function\":\"" as *u8) 37 print(fname) 38 print("\",\"hash\":" as *u8) 39 print_i64(h) 40 println("}" as *u8) 41 return 0 42} 43 44func main(argc: i64, argv: *i64) -> i64 { 45 // argv form: program file1 fname1 file2 fname2 ... fileN fnameN 46 // argc = 1 + 2*N (must be odd, >= 5). 47 if argc < 5 { 48 println("usage: nx_func_compare <file1> <fname1> <file2> <fname2> [...]" as *u8) 49 return 1 50 } 51 if argc - (argc / 2) * 2 != 1 { 52 println("usage: argc must be odd (alternating file fname pairs)" as *u8) 53 return 1 54 } 55 let n_files: i64 = (argc - 1) / 2 56 57 let norm_buf: *u8 = sys_mmap(NX_CMP_NORM_BUF) 58 let out_len: *i64 = (sys_mmap(8)) as *i64 59 60 var first_hash: i64 = 0 61 var have_first: i64 = 0 62 var all_equal: i64 = 1 63 var first_diff_file: *u8 = 0 as *u8 64 65 var fi: i64 = 0 66 while fi < n_files { 67 let path: *u8 = (argv[1 + 2 * fi]) as *u8 68 let fname: *u8 = (argv[1 + 2 * fi + 1]) as *u8 69 out_len[0] = 0 70 let buf: *u8 = sys_read_file(path, out_len) 71 if (buf as i64) == 0 { 72 print("{\"file\":\"" as *u8) 73 print(path) 74 println("\",\"error\":\"read_failed\"}" as *u8) 75 all_equal = 0 76 } 77 if (buf as i64) != 0 { 78 let h: i64 = nx_extract_func_hash(buf, out_len[0], fname, norm_buf) 79 if h == 0 { 80 print("{\"file\":\"" as *u8) 81 print(path) 82 print("\",\"function\":\"" as *u8) 83 print(fname) 84 println("\",\"error\":\"function_not_found\"}" as *u8) 85 all_equal = 0 86 } 87 if h != 0 { 88 compare_emit_file(path, fname, h) 89 if have_first == 0 { 90 first_hash = h 91 have_first = 1 92 } 93 if have_first == 1 { 94 if h != first_hash { 95 all_equal = 0 96 if (first_diff_file as i64) == 0 { 97 first_diff_file = path 98 } 99 } 100 } 101 } 102 } 103 fi = fi + 1 104 } 105 106 // Verdict. 107 print("{\"summary\":true,\"n_files\":" as *u8) 108 print_i64(n_files) 109 print(",\"verdict\":\"" as *u8) 110 if all_equal == 1 { print("EQUIVALENT" as *u8) } 111 if all_equal == 0 { print("DIVERGE" as *u8) } 112 print("\"" as *u8) 113 if all_equal == 0 { 114 if (first_diff_file as i64) != 0 { 115 print(",\"first_diff\":\"" as *u8) 116 print(first_diff_file) 117 print("\"" as *u8) 118 } 119 } 120 println("}" as *u8) 121 return 0 122}