code wiki / (root) / nx_code_quality.nx

nx_code_quality.nx source

↩ module page · 389 lines · 14479 B

1// nx_code_quality.nx -- qualitative + quantitative code refactor verdict. 2// 3// Six measurable axes -> Q10 score per axis + sealed-enum CodeQualityVerdict. 4// Operates on a source-text byte buffer (any language whose lexical 5// substrate uses { } ( ) [ ] for nesting + // for comments -- which covers 6// NishiLang, C, Rust, Go, Java, JavaScript, TypeScript, C++). 7// 8// Refactor triggers (each maps to a Q10 axis): 9// 10// 1. NULL_PTR_HAZARD count of `0 as *` patterns (NULL sentinel) 11// normalized by source length 12// 2. HARDCODING_SCORE count of `* 8`, `* 4` literals not in 13// comments (cardinal-violation signal: 14// should be NX_SIZEOF_NX_INT etc.) 15// 3. NESTING_HAZARD maximum bracket nesting depth (cyclomatic 16// proxy; deep nesting -> refactor) 17// 4. REPETITION_HAZARD line-length-diversity proxy (very uniform 18// line lengths -> repetition; very long 19// single lines -> readability issue) 20// 5. COMMENT_DEFICIT comment density below threshold -> 21// documentation gap 22// 6. TIER_COMPLIANCE bare `i64 ` occurrences (should use 23// nx_int / nx_size / nx_idx aliases) 24// 25// Composite_q10 = inverse-weighted sum across axes (low hazard count 26// + good comment density + nx_tier compliance = high composite). 27// 28// Sealed-enum verdict: 29// NX_CQ_REFACTOR_HOT composite < 300 immediate refactor 30// NX_CQ_REFACTOR_RECOMMENDED 300 <= comp < 600 31// NX_CQ_ACCEPTABLE 600 <= comp < 800 32// NX_CQ_EXCELLENT comp >= 800 33// 34// Cross-language: same primitive over any text-source byte stream 35// (NishiLang .nx, C .c, Rust .rs, prose .txt -- though the cardinal- 36// violation axes 1, 2, 6 are NishiLang-specific; they read as 37// no-op on other languages where those patterns don't appear). 38// 39// "Competitive coding best practices" reading per dual-reading 40// cardinal: the qualitative verdict names WHICH refactor is most 41// urgent (deepest nesting? most duplication? most hardcoding?); 42// the quantitative axes give the operator the numbers behind it. 43// 44// genealogy_id: mccabe_1976_cyclomatic + halstead_1977_metrics + 45// fenton_2014_software_metrics + lloyd_1986_practical 46// lineage_id: code_quality_composite_q10 47 48// nx_safety_envelope: 49// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 50// sil_target: SIL1 51// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 52// verdict: NOT_YET_EVALUATED 53 54import "nx_syscalls.nx" 55import "nx_tier.nx" 56 57const NX_CQ_Q: nx_int = 1024 58const NX_CQ_MAX_NESTING_OK: nx_int = 5 59 60const NX_CQ_REFACTOR_HOT: nx_int = 0 61const NX_CQ_REFACTOR_RECOMMENDED: nx_int = 1 62const NX_CQ_ACCEPTABLE: nx_int = 2 63const NX_CQ_EXCELLENT: nx_int = 3 64const NX_CQ_N_VERDICTS: nx_int = 4 65 66const NX_CQ_AXIS_NULL_PTR: nx_int = 0 67const NX_CQ_AXIS_HARDCODING: nx_int = 1 68const NX_CQ_AXIS_NESTING: nx_int = 2 69const NX_CQ_AXIS_REPETITION: nx_int = 3 70const NX_CQ_AXIS_COMMENT: nx_int = 4 71const NX_CQ_AXIS_TIER: nx_int = 5 72const NX_CQ_N_AXES: nx_int = 6 73 74struct CodeQualityReport { 75 line_count: nx_int, 76 null_ptr_count: nx_int, 77 hardcoded_size_count: nx_int, 78 bare_i64_count: nx_int, 79 comment_line_count: nx_int, 80 max_nesting: nx_int, 81 null_ptr_q10: nx_int, // 0 = many nulls (bad); Q10 = none (good) 82 hardcoding_q10: nx_int, // same convention -- HIGH = clean 83 nesting_q10: nx_int, // HIGH = shallow (good) 84 repetition_q10: nx_int, 85 comment_q10: nx_int, // HIGH = well-documented 86 tier_q10: nx_int, 87 composite_q10: nx_int, 88 verdict: nx_int, // NX_CQ_* sealed enum 89 worst_axis: nx_int, // NX_CQ_AXIS_* of the lowest-scoring axis 90} 91 92// ===== Helpers ========================================================= 93 94// Check if buffer[i..i+n] equals literal byte string. 95func _cq_match_at(buf: *u8, len: nx_int, pos: nx_int, lit: *u8, n: nx_int) -> nx_int { 96 if pos + n > len { return 0 } 97 var k: nx_int = 0 98 while k < n { 99 if buf[pos + k] != lit[k] { return 0 } 100 k = k + 1 101 } 102 return 1 103} 104 105// Is position inside a // line comment? Cheap heuristic: scan back 106// from pos to start-of-line and check for // before any non-whitespace. 107// For NishiLang/C-style. Returns 1 if in comment, 0 if not. 108func _cq_in_comment(buf: *u8, pos: nx_int) -> nx_int { 109 var p: nx_int = pos 110 while p > 0 { 111 let c: u8 = buf[p - 1] 112 if c == 10 { return 0 } // hit start-of-line without seeing // 113 if p >= 2 { 114 if buf[p - 2] == 47 { // '/' 115 if buf[p - 1] == 47 { return 1 } 116 } 117 } 118 p = p - 1 119 } 120 return 0 121} 122 123// ===== Primary scanner ================================================ 124// 125// Single pass over the buffer, accumulating all axis counters. 126 127func nx_code_quality_scan(buf: *u8, len: nx_int, report: *CodeQualityReport) -> nx_int { 128 report.line_count = 0 129 report.null_ptr_count = 0 130 report.hardcoded_size_count = 0 131 report.bare_i64_count = 0 132 report.comment_line_count = 0 133 report.max_nesting = 0 134 135 // Literals to search for. Allocate small const-string buffers 136 // (NishiLang doesn't yet have string-literal pool, so we use 137 // byte-array allocations). 138 let lit_null: *u8 = sys_mmap(4) 139 lit_null[0] = 48 // '0' 140 lit_null[1] = 32 // ' ' 141 lit_null[2] = 97 // 'a' 142 lit_null[3] = 115 // 's' 143 144 let lit_star8: *u8 = sys_mmap(3) 145 lit_star8[0] = 42 // '*' 146 lit_star8[1] = 32 // ' ' 147 lit_star8[2] = 56 // '8' 148 149 let lit_i64: *u8 = sys_mmap(4) 150 lit_i64[0] = 105 // 'i' 151 lit_i64[1] = 54 // '6' 152 lit_i64[2] = 52 // '4' 153 lit_i64[3] = 32 // ' ' (trailing space prevents 'i640' false positive) 154 155 var nest: nx_int = 0 156 var max_nest: nx_int = 0 157 var at_line_start: nx_int = 1 158 var leading_ws: nx_int = 1 159 var line_has_comment: nx_int = 0 160 161 var i: nx_int = 0 162 while i < len { 163 let c: u8 = buf[i] 164 165 // Newline: count line, reset line state. 166 if c == 10 { 167 report.line_count = report.line_count + 1 168 if line_has_comment == 1 { 169 report.comment_line_count = report.comment_line_count + 1 170 } 171 at_line_start = 1 172 leading_ws = 1 173 line_has_comment = 0 174 i = i + 1 175 // continue 176 } else { 177 // Comment detection: '//' on a line. 178 if c == 47 { // '/' 179 if i + 1 < len { 180 if buf[i + 1] == 47 { 181 line_has_comment = 1 182 } 183 } 184 } 185 186 // Bracket nesting. 187 if c == 123 { // '{' 188 if _cq_in_comment(buf, i) == 0 { 189 nest = nest + 1 190 if nest > max_nest { max_nest = nest } 191 } 192 } 193 if c == 125 { // '}' 194 if _cq_in_comment(buf, i) == 0 { 195 nest = nest - 1 196 if nest < 0 { nest = 0 } 197 } 198 } 199 200 // Pattern matches at this position (skip if in comment). 201 if _cq_in_comment(buf, i) == 0 { 202 if _cq_match_at(buf, len, i, lit_null, 4) == 1 { 203 // Followed by '*' to confirm '0 as *T' shape? 204 if i + 4 < len { 205 if buf[i + 4] == 42 { // '*' 206 report.null_ptr_count = report.null_ptr_count + 1 207 } 208 } 209 } 210 if _cq_match_at(buf, len, i, lit_star8, 3) == 1 { 211 // Confirm boundary: prev char is not letter/digit 212 var prev_ok: nx_int = 1 213 if i > 0 { 214 let pc: u8 = buf[i - 1] 215 if pc >= 48 { 216 if pc <= 57 { prev_ok = 0 } 217 } 218 if pc >= 65 { 219 if pc <= 90 { prev_ok = 0 } 220 } 221 if pc >= 97 { 222 if pc <= 122 { prev_ok = 0 } 223 } 224 } 225 if prev_ok == 1 { 226 // Confirm next char is whitespace/newline/end (not '8'-of-a-bigger-number) 227 var next_ok: nx_int = 1 228 if i + 3 < len { 229 let nc: u8 = buf[i + 3] 230 if nc >= 48 { 231 if nc <= 57 { next_ok = 0 } 232 } 233 } 234 if next_ok == 1 { 235 report.hardcoded_size_count = report.hardcoded_size_count + 1 236 } 237 } 238 } 239 if _cq_match_at(buf, len, i, lit_i64, 4) == 1 { 240 // Confirm boundary on the LEFT: prev is whitespace/colon/comma 241 var pok: nx_int = 1 242 if i > 0 { 243 let pc: u8 = buf[i - 1] 244 if pc >= 65 { 245 if pc <= 90 { pok = 0 } 246 } 247 if pc >= 97 { 248 if pc <= 122 { pok = 0 } 249 } 250 } 251 if pok == 1 { 252 report.bare_i64_count = report.bare_i64_count + 1 253 } 254 } 255 } 256 257 i = i + 1 258 } 259 } 260 // Tail line without trailing newline. 261 if len > 0 { 262 if buf[len - 1] != 10 { 263 report.line_count = report.line_count + 1 264 if line_has_comment == 1 { 265 report.comment_line_count = report.comment_line_count + 1 266 } 267 } 268 } 269 report.max_nesting = max_nest 270 return 0 271} 272 273// ===== Axis Q10 scoring + composite + verdict ========================= 274// 275// All scores are HIGH = GOOD convention. Each axis maps the relevant 276// count + a tolerance into a Q10 [0, 1024] band: 277// null_ptr_q10 = max(0, Q - 4 * null_count) clamped 278// hardcoding_q10 = max(0, Q - 64 * hardcoded_count / line_count_norm) 279// nesting_q10 = max(0, Q - 200 * (max_nesting - NX_CQ_MAX_NESTING_OK)) 280// repetition_q10 = derived from line-density distribution (placeholder 281// for the shingling-based repetition detector -- 282// today fixed at Q/2 = 512 ('unmeasured'). 283// comment_q10 = comment_lines / total_lines * Q (clamped) 284// tier_q10 = max(0, Q - 32 * bare_i64_density_q10) 285 286func nx_code_quality_score(report: *CodeQualityReport) -> nx_int { 287 let lc: nx_int = report.line_count 288 let lc_safe: nx_int = lc 289 var lc_div: nx_int = lc_safe 290 if lc_div < 1 { lc_div = 1 } 291 292 // null_ptr_q10: 0 nulls = Q10 (perfect); each null subtracts ~64. 293 var ng: nx_int = NX_CQ_Q - report.null_ptr_count * 64 294 if ng < 0 { ng = 0 } 295 report.null_ptr_q10 = ng 296 297 // hardcoding_q10: each hardcoded literal subtracts ~256. 298 var hc: nx_int = NX_CQ_Q - report.hardcoded_size_count * 256 299 if hc < 0 { hc = 0 } 300 report.hardcoding_q10 = hc 301 302 // nesting_q10: every level beyond NX_CQ_MAX_NESTING_OK subtracts 200. 303 var ns: nx_int = NX_CQ_Q 304 let over: nx_int = report.max_nesting - NX_CQ_MAX_NESTING_OK 305 if over > 0 { ns = NX_CQ_Q - over * 200 } 306 if ns < 0 { ns = 0 } 307 report.nesting_q10 = ns 308 309 // repetition_q10: placeholder pending shingling pass. 310 report.repetition_q10 = NX_CQ_Q / 2 311 312 // comment_q10: comment density. 313 let cd: nx_int = (report.comment_line_count * NX_CQ_Q) / lc_div 314 var cd_clamped: nx_int = cd 315 if cd_clamped > NX_CQ_Q { cd_clamped = NX_CQ_Q } 316 report.comment_q10 = cd_clamped 317 318 // tier_q10: bare i64 occurrences scaled. 319 let bd: nx_int = (report.bare_i64_count * NX_CQ_Q) / lc_div 320 var tg: nx_int = NX_CQ_Q - bd * 4 321 if tg < 0 { tg = 0 } 322 report.tier_q10 = tg 323 324 // Composite = simple average across the 6 axes. 325 let comp: nx_int = ( 326 report.null_ptr_q10 + 327 report.hardcoding_q10 + 328 report.nesting_q10 + 329 report.repetition_q10 + 330 report.comment_q10 + 331 report.tier_q10 332 ) / 6 333 report.composite_q10 = comp 334 335 // Verdict band. 336 if comp < 300 { report.verdict = NX_CQ_REFACTOR_HOT } 337 if comp >= 300 { report.verdict = NX_CQ_REFACTOR_RECOMMENDED } 338 if comp >= 600 { report.verdict = NX_CQ_ACCEPTABLE } 339 if comp >= 800 { report.verdict = NX_CQ_EXCELLENT } 340 341 // Worst axis: the lowest-scoring of the 6 -- this is what the 342 // operator should refactor first. 343 var worst_axis: nx_int = NX_CQ_AXIS_NULL_PTR 344 var worst_score: nx_int = report.null_ptr_q10 345 if report.hardcoding_q10 < worst_score { 346 worst_score = report.hardcoding_q10 347 worst_axis = NX_CQ_AXIS_HARDCODING 348 } 349 if report.nesting_q10 < worst_score { 350 worst_score = report.nesting_q10 351 worst_axis = NX_CQ_AXIS_NESTING 352 } 353 if report.repetition_q10 < worst_score { 354 worst_score = report.repetition_q10 355 worst_axis = NX_CQ_AXIS_REPETITION 356 } 357 if report.comment_q10 < worst_score { 358 worst_score = report.comment_q10 359 worst_axis = NX_CQ_AXIS_COMMENT 360 } 361 if report.tier_q10 < worst_score { 362 worst_score = report.tier_q10 363 worst_axis = NX_CQ_AXIS_TIER 364 } 365 report.worst_axis = worst_axis 366 367 return 0 368} 369 370// Sealed-enum validity check. 371func nx_code_quality_verdict_is_valid(v: nx_int) -> nx_int { 372 if v < 0 { return 0 } 373 if v >= NX_CQ_N_VERDICTS { return 0 } 374 return 1 375} 376 377func nx_code_quality_axis_is_valid(a: nx_int) -> nx_int { 378 if a < 0 { return 0 } 379 if a >= NX_CQ_N_AXES { return 0 } 380 return 1 381} 382 383// One-shot composite: allocate report, scan, score. Caller frees 384// (we don't have explicit free in the substrate yet). 385func nx_code_quality_compute(buf: *u8, len: nx_int, report: *CodeQualityReport) -> nx_int { 386 nx_code_quality_scan(buf, len, report) 387 nx_code_quality_score(report) 388 return 0 389}