code wiki / _hdl_build / nx_code_depgraph.nx

nx_code_depgraph.nx source

↩ module page · 106 lines · 5463 B

1// nx_code_depgraph.nx -- Analyzes source code to build a dependency graph of modules, identifying relationships and architectural hubs. 2import "nx_gate_gn.nx" 3import "nx_gate_base.nx" 4// nx_code_depgraph.nx -- NISHI code-analysis, the dependency/architecture-graph rung (vs Understand/Structure101). 5// Walks a repo's source files (nx_dir), extracts each file's #include "..."/<...> and import directives as 6// dependency EDGES, and reports the graph: modules (files), edges (deps), density, and the top HUB (the most 7// depended-on module = the architectural center). Sovereign, integer, zero egress. usage: 8// nx_code_depgraph <repo-dir> license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_dir.nx" 11const K_MAGIC_8192: i64 = 8192 12const K_MAGIC_2097152: i64 = 2097152 13const K_MAGIC_4096: i64 = 4096 14 15func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 16" as *u8); return ok } 17func match_at(buf: *u8, n: i64, i: i64, pat: *u8) -> i64 { var j: i64=0; while pat[j]!=(0 as u8){ if i+j>=n {return 0} if buf[i+j]!=pat[j]{return 0} j=j+1 } return 1 } 18 19const MAXT: i64 = 65536 20const ARENA: i64 = 8388608 21 22func main(argc: i64, argv: *i64) -> i64 { 23 if argc < 2 { gw("usage: nx_code_depgraph <repo-dir>\n"); return 2 } 24 let dir: *u8 = argv[1] as *u8 25 let rows: *NxDirRow = sys_mmap(K_MAGIC_8192 * NX_DIR_ROW_BYTES) as *NxDirRow 26 let na: *u8 = sys_mmap(K_MAGIC_2097152) 27 let res: *NxDirResult = sys_mmap(NX_DIR_RESULT_BYTES) as *NxDirResult 28 let v: i64 = nx_dir_list(dir, rows, K_MAGIC_8192, na, K_MAGIC_2097152, 0, res) 29 if v != NX_DIR_OK { if v != NX_DIR_TRUNCATED { gw("DEPGRAPH: dir list failed ("); gn(v); gw(")\n"); return 1 } } 30 let nfiles: i64 = res.n_filled 31 32 let arena: *u8 = sys_mmap(ARENA); var au: i64 = 0 33 let toff: *i64 = sys_mmap(MAXT*8) as *i64 34 let tlen: *i64 = sys_mmap(MAXT*8) as *i64 35 var nt: i64 = 0 36 37 let lenp: *i64 = sys_mmap(16) as *i64 38 let path: *u8 = sys_mmap(K_MAGIC_4096) 39 var dl: i64 = 0; while dir[dl]!=(0 as u8){dl=dl+1} 40 var idx: i64 = 0 41 while idx < nfiles { 42 let row: *NxDirRow = nx_dir_row_at(rows, idx) 43 if nx_dir_row_is_regular_file(row) == 1 { 44 var p: i64=0; while p<dl{path[p]=dir[p];p=p+1} path[p]=47 as u8; p=p+1 45 var q: i64=0; while q<row.name_len{path[p]=row.name_ptr[q];p=p+1;q=q+1} path[p]=0 as u8 46 let fb: *u8 = sys_read_file(path, lenp) 47 if (fb as i64) != 0 { 48 let flen: i64 = lenp[0] 49 var i: i64 = 0 50 while i < flen { 51 var s: i64 = 0 - 1; var e: i64 = 0 52 if match_at(fb, flen, i, "#include" as *u8) == 1 { 53 var j: i64 = i+8; while j<flen { if fb[j]==32 as u8 { j=j+1 } else { if fb[j]==9 as u8 { j=j+1 } else { break } } } 54 if fb[j]==34 as u8 { s=j+1; e=s; while e<flen { if fb[e]==34 as u8 { break } e=e+1 } } 55 else { if fb[j]==60 as u8 { s=j+1; e=s; while e<flen { if fb[e]==62 as u8 { break } e=e+1 } } } 56 i = j 57 } else { if match_at(fb, flen, i, "import " as *u8) == 1 { 58 var j: i64 = i+7; while j<flen { if fb[j]==32 as u8 { j=j+1 } else { break } } 59 if fb[j]==34 as u8 { s=j+1; e=s; while e<flen { if fb[e]==34 as u8 { break } e=e+1 } } 60 else { s=j; e=s; while e<flen { if fb[e]==32 as u8 { break } if fb[e]==10 as u8 { break } if fb[e]==59 as u8 { break } e=e+1 } } 61 i = j 62 } } 63 if s >= 0 { if e > s { 64 // strip to basename (after last '/') 65 var b: i64 = s; var bs: i64 = s 66 while b < e { if fb[b]==47 as u8 { bs = b+1 } b=b+1 } 67 let tl: i64 = e - bs 68 if nt < MAXT { if au + tl + 1 < ARENA { 69 toff[nt]=au; tlen[nt]=tl 70 var c: i64=0; while c<tl { arena[au+c]=fb[bs+c]; c=c+1 } au=au+tl; nt=nt+1 71 } } 72 } } 73 i = i + 1 74 } 75 sys_munmap(fb, flen) 76 } 77 } 78 idx = idx + 1 79 } 80 81 // top hub = max in-degree over distinct targets (O(nt^2) string compare, bounded) 82 var maxdeg: i64 = 0; var maxidx: i64 = 0 83 var a: i64 = 0 84 while a < nt { 85 var cnt: i64 = 0; var b: i64 = 0 86 while b < nt { 87 if tlen[a]==tlen[b] { 88 var m: i64=0; var same: i64=1 89 while m < tlen[a] { if arena[toff[a]+m] != arena[toff[b]+m] { same=0; break } m=m+1 } 90 if same==1 { cnt=cnt+1 } 91 } 92 b=b+1 93 } 94 if cnt > maxdeg { maxdeg=cnt; maxidx=a } 95 a = a + 1 96 } 97 98 gw("=== DEPGRAPH: "); gw(dir); gw(" ===\n") 99 gw(" modules (source files): "); gn(nfiles); gw("\n") 100 gw(" dependency edges (#include/import): "); gn(nt); gw("\n") 101 if nfiles > 0 { gw(" density (edges*100/module): "); gn(nt*100/nfiles); gw("\n") } 102 if nt > 0 { gw(" top hub (most depended-on): "); sys_write(1, ((arena as i64)+toff[maxidx]) as *u8, tlen[maxidx]); gw(" (in-degree "); gn(maxdeg); gw(")\n") } 103 gw("DEPGRAPH-OK modules="); gn(nfiles); gw(" edges="); gn(nt); gw(" maxindegree="); gn(maxdeg); gw("\n") 104 if nfiles > 0 { return 0 } 105 return 3 106}