code wiki / _hdl_build / nx_collision_plan.nx

nx_collision_plan.nx source

↩ module page · 114 lines · 6638 B

1// nx_collision_plan.nx -- the RESOLUTION PROPOSER: mechanizes the careful merge method for each shadow 2// collision so the team can resolve sprawl without hand-judging every pair (and without ever losing a 3// capability). For a shadowed basename it reads BOTH copies (runtime/<n> = A, runtime/_hdl_build/<n> = B), 4// extracts each copy's FUNCTION-NAME SET, and from the set relationship proposes the resolution: 5// shared==0 -> CODE 0 RENAME_DISTINCT : disjoint = two DIFFERENT capabilities sharing 6// a name -> rename both to clear names (GROWTH, like nx_extract vs nx_func_extract). 7// shared>0, onlyA==0, onlyB==0 -> CODE 1 KEEP_NEWER_GEN : same func-set, different bytes = the SAME 8// capability in two GENERATIONS -> keep the _hdl_build (probe-first) canon, retire the old runtime gen. 9// shared>0, onlyA==0, onlyB>0 -> CODE 2 RETIRE_A_SUBSET : B is the SUPERSET and B already RUNS (probe-first) = correct -> retire the runtime subset A. 10// shared>0, onlyA>0, onlyB==0 -> CODE 3 CAPABILITY-LOSS!: A (runtime) is the SUPERSET but the LESS-capable 11// B shadows it -> we are SILENTLY LOSING A's extra funcs -> must merge A's extras into B (or promote A). The highest-value catch. 12// shared>0, onlyA>0, onlyB>0 -> CODE 4 MERGE_UNION : each copy has unique funcs -> merge the union into one. 13// Toolchain-critical organs (nx_link = the ELF linker, never-brick #26) are flagged REVIEW regardless -- the 14// proposer NEVER auto-executes; it emits a plan the warden/operator gates. READ-ONLY (never-brick by construction). 15// RESIDUAL CAVEAT (honest): the program-vs-library signal is "has a top-level main". A LIBRARY that also carries 16// a self-test main (e.g. nx_research_ledger, prints GREEN x2) looks like a program, so a library-vs-report pair 17// can still slip through as MERGE_UNION. Full disambiguation needs IMPORT-ANALYSIS (does anything import it and 18// call its exported funcs?) -- the next rung; for now the benchmark/human layer catches that edge. license_tier: ORIGINAL 19import "nx_janitor_dupname.nx" 20import "nx_syscalls.nx" 21const K_MAGIC_1024: i64 = 1024 22const K_MAGIC_1048576: i64 = 1048576 23const K_MAGIC_4000: i64 = 4000 24 25// identifier char: [0-9A-Za-z_] 26func crp_is_ident(ch: u8) -> i64 { 27 let c: i64 = ch as i64 28 if c>=48 { if c<=57 { return 1 } } 29 if c>=65 { if c<=90 { return 1 } } 30 if c>=97 { if c<=122 { return 1 } } 31 if c==95 { return 1 } 32 return 0 33} 34 35// extract every top-level "func NAME" basename into names (NUL-term) + noff[k]=start. returns count. 36func crp_extract_funcs(buf: *u8, len: i64, names: *u8, noff: *i64, maxn: i64) -> i64 { 37 var k: i64=0; noff[0]=0; var i: i64=0 38 while i+5 <= len { 39 var hit: i64=0 40 if buf[i]==(102 as u8) { if buf[i+1]==(117 as u8) { if buf[i+2]==(110 as u8) { if buf[i+3]==(99 as u8) { if buf[i+4]==(32 as u8) { 41 if i==0 { hit=1 } else { if buf[i-1]==(10 as u8) { hit=1 } } 42 } } } } } 43 if hit==1 { 44 var p: i64=i+5 45 var sp: i64=1 46 while sp==1 { if p<len { if buf[p]==(32 as u8) { p=p+1 } else { sp=0 } } else { sp=0 } } 47 let start: i64=noff[k]; var c: i64=0; var rd: i64=1 48 while rd==1 { if p<len { if crp_is_ident(buf[p])==1 { names[start+c]=buf[p]; c=c+1; p=p+1 } else { rd=0 } } else { rd=0 } } 49 names[start+c]=0 as u8 50 if c>0 { if k<maxn { noff[k+1]=start+c+1; k=k+1 } } 51 i=p 52 } 53 i=i+1 54 } 55 return k 56} 57 58func crp_name_in(name: *u8, names: *u8, noff: *i64, count: i64) -> i64 { 59 var j: i64=0 60 while j<count { if jdn_streq(name, (names as i64 + noff[j]) as *u8)==1 { return 1 } j=j+1 } 61 return 0 62} 63// out[0]=shared out[1]=onlyA out[2]=onlyB 64func crp_setcmp(na: *u8, oa: *i64, ca: i64, nb: *u8, ob: *i64, cb: i64, out: *i64) -> i64 { 65 var shared: i64=0; var onlyA: i64=0; var i: i64=0 66 while i<ca { if crp_name_in((na as i64+oa[i]) as *u8, nb,ob,cb)==1 { shared=shared+1 } else { onlyA=onlyA+1 } i=i+1 } 67 var onlyB: i64=0; var j: i64=0 68 while j<cb { if crp_name_in((nb as i64+ob[j]) as *u8, na,oa,ca)==0 { onlyB=onlyB+1 } j=j+1 } 69 out[0]=shared; out[1]=onlyA; out[2]=onlyB; return 0 70} 71 72func crp_is_toolchain(name: *u8) -> i64 { 73 if jdn_streq(name, "nx_link.nx\x00" as *u8)==1 { return 1 } 74 if jdn_streq(name, "nx_asm.nx\x00" as *u8)==1 { return 1 } 75 if jdn_streq(name, "nx_cc.nx\x00" as *u8)==1 { return 1 } 76 return 0 77} 78 79// the resolution decision from the set relationship (see header). 80func crp_classify(shared: i64, onlyA: i64, onlyB: i64) -> i64 { 81 if shared==0 { return 0 } 82 if onlyA==0 { if onlyB==0 { return 1 } else { return 2 } } 83 if onlyB==0 { return 3 } 84 return 4 85} 86 87// CODE 5 DISTINCT_KIND: one copy is a runnable PROGRAM (has a top-level `main`), the other an imported LIBRARY 88// (no main). They are different KINDS sharing a name -- an incidental helper overlap (e.g. g_puts) can fool the 89// name-set classifier into MERGE/SUBSET, but a program and a library must NOT be merged; rename the mis-named one. 90// This kind-mismatch OVERRIDES the set relationship. (Caught the real nx_research_ledger case: RESEARCH_MEMORY 91// library shadowed by an integrated-research REPORT program.) 92func crp_classify2(shared: i64, onlyA: i64, onlyB: i64, hasMainA: i64, hasMainB: i64) -> i64 { 93 if hasMainA != hasMainB { return 5 } 94 return crp_classify(shared, onlyA, onlyB) 95} 96 97// plan ONE shadowed basename. out[0]=shared out[1]=onlyA out[2]=onlyB out[3]=cntA out[4]=cntB. 98// caller supplies reusable buffers (ba/bb >=1MB, na/nb >=64KB, oa/ob >=4096 slots). returns CODE 0..4, or -1 read err. 99func crp_plan_one(name: *u8, ba: *u8, bb: *u8, na: *u8, oa: *i64, nb: *u8, ob: *i64, out: *i64) -> i64 { 100 let pr: *u8=sys_mmap(K_MAGIC_1024); let ph: *u8=sys_mmap(K_MAGIC_1024) 101 jdn_path("runtime/\x00" as *u8, name, pr) 102 jdn_path("runtime/_hdl_build/\x00" as *u8, name, ph) 103 let la: i64=jdn_read(pr, ba, K_MAGIC_1048576); let lb: i64=jdn_read(ph, bb, K_MAGIC_1048576) 104 if la<0 { return 0-1 } 105 if lb<0 { return 0-1 } 106 let ca: i64=crp_extract_funcs(ba, la, na, oa, K_MAGIC_4000) 107 let cb: i64=crp_extract_funcs(bb, lb, nb, ob, K_MAGIC_4000) 108 let s3: *i64=sys_mmap(32) as *i64 109 crp_setcmp(na,oa,ca, nb,ob,cb, s3) 110 let hma: i64=crp_name_in("main\x00" as *u8, na, oa, ca) 111 let hmb: i64=crp_name_in("main\x00" as *u8, nb, ob, cb) 112 out[0]=s3[0]; out[1]=s3[1]; out[2]=s3[2]; out[3]=ca; out[4]=cb; out[5]=hma; out[6]=hmb 113 return crp_classify2(s3[0], s3[1], s3[2], hma, hmb) 114}