分析轨让读者发问,在同一份索引上、由同一个核判决。
工作原理页上的每个家族各判一种树上已有的熵:一处克隆、一个死文件、一段重复的散文、一个扮演别人角色的单元。分析轨让读者发问——在同一份索引上、同一个核里判决、守同一套承诺:每个答案都是对实测事实的算术,证据与判决之间没有模型也没有浮点数,每个常数都钉在实现它的源码行上。
它的家族从第十五族往后续编号,每族一册;下面是短版,完整推导在 docs/reference/methodology.md,本页每个小标题都直接链进去。
判决家族量一个事实、拿它比一条写下来的阈值。分析家族拿的是一个程序——一个问题,或一份规则文件——在索引已有的事实上作答,阈值就是读者自己写的那句话。分工不动:Rust 度量与回标,Haskell 核判决,两者之间过线的只有整数。
用 CE Datalog 对索引已有的事实——文件、目录、引用、单元、复杂度、已判的克隆对与文档重复对、提及、路径类——提一个问题,每个答案带推导链;把规则文件里的断言当门判:一条违规就是一行见证加它的推导,ce rules 见第一条即退 1。
clause := atom ':-' body '.' | '?-' body '.' | 'assert' atom ':-' body '.'
lit := atom | 'not' atom | expr op expr | Var '=' expr | Var '=' agg(Vars : body)
prelude: entry(N) :- role(N, _). reach(M) :- reach(N), ref(N, M, K, _), K != asset, K != refdef.
dead(F) :- file(F), not reach(F). depends · same_dir · dir_ref
strata : a head sits above every negated or aggregated body predicate; a negative edge inside an SCC is a program error
eval : semi-naive per stratum over lazy bitmask indexes; the first derivation of a tuple is its provenance
度量侧把文本词法成 [kind, value] 记号流,只从自己的索引装配程序点名的事实表,两者一起送出;名字以 fnv1a64 哈希与请求内 id 上线、从不以文本,回来时也是同样的 id,再经请求自己的表回标。核解析(手写递归下降)、检查元数、类别(变量、谓词位置与常量类别上的并查集)、安全性(域界:变量只在正原子或绑定先绑定它之后才可读)与分层,逐层求值,回答每个目标的元组、每条断言的违规、推导行与程序错误——每个错误落在一个记号上,度量侧把它映回 line:column。推导树要么整棵、要么不出:结点预算下装不下的整棵不出并计数,从不截断。记号与事实行在判决前定价,超限即完整的降级应答;派生元组超限让整次求值作废;没有这个家族的核在文档里是具名的未判决。内置的 dead(F) 就是 ce deadcode 的文件级判决改写成规则,本仓以 ce.rules 里的九条断言给自己把门,作 CI 的第七条狗粮腿。
找一个函数内部的死代码:没有路径到达的语句、没有路径读到的存储、没人读的局部量,没人读的形参只作顾问。ce flow 列出它们,守卫数一次写入带进来的那几条,Stop 行只记、从不拦停。
tables : stmts [u, seq, parent, kind, flags, aux] · vars [u, v, declSeq, flags] · uses [u, seq, v, mode] cfg : structured kinds unfolded; a try body's every statement may reach each catch; one finally hub per try kind 0 : unreachable = no path from the entry, one finding per maximal run of seqs kind 1 : dead_store = a write no path reads before the next write or the exit (backward liveness) kind 2 : unused_local = no read · kind 3 : unused_param = no read (advice, never judged) skip : a unit with a dynamic statement is not judged in part, and counted
度量侧按每个语言一张 FlowSpec 表,把十个语言(Python、TypeScript 与 TSX、Rust、Go、C、C++、Java、Lua、R)的每个单元降成四张整数表;名字、路径、源码文本一样都不过线。核建控制流图,从入口走可达性、反向求活性到不动点,答回 [unit, kind, seq, var, seqEnd] 行,由度量侧回标。每一处近似都只加路径——finally 是一个汇合点、后继取待续目标的并集,表达式位置的出口不降表——所以发现只可能漏报、不可能凭空捏造。一条发现只在精度考题过门的语言里才算判决(盲评,门读的每一类都零误报)。十个语言都在门内:在回修后的降表上重生成的精度册(C++、R、Rust、TypeScript 是第二代考题)十份都过门,门读的每一类零误报;未用形参在哪个语言都只是顾问。守卫类 [flow] tier 出厂 observe,按(单元,种类,变量)的多重集差数新增发现,挪了位置的发现不算这次写入干的。
读每个克隆组怎样合并成一个函数:成员之间不同的地方成为参数,答案是参数个数、值得保留的成员、合并能省的行数,以及可不可行——不可行时给出原因。只当顾问:没有门读它,ce merge 出文档即退 0。
groups : T1/T2 dedup families (whole units when one unit fills ≥ 9/10 of each member, else fragments trimmed to the members' common shape) · T3 judged pairs trees : clone/1's postorder (lab, lld), extras (comments) left out, + leaf = fnv1a64 of a leaf's bytes (0 inside) + slot 0 stmt · 1 expr · 2 type · 3 name · 4 other align : T1/T2 isomorphic, holes = differing leaves; T3 the tree-edit mapping narrowed top-down, relabels and unequal gaps are holes params : one per distinct value vector; feasible iff every hole is an expression or a name, params ≤ 6 and savings > 0 reason : 3 a gap across statements, 1 position (a statement or other), 2 a type position, 4 more than six parameters, 5 no line saved kept : the member whose file has the greatest in-degree; savings = Σ lines − (skeleton lines + members × 1), a fragment's lines its kept run's
度量侧收集克隆组,为每个成员按 clone/1 的编码建树并多带两列整数——叶结点原文的哈希与它的位置类(每语言一张表,读流表的语句类)——再把答案回标成每个参数上每个成员的原文,间隙洞给整段森林。树里不带注释;片段族只送每个成员都有的那一段顶层结点,所以边界行上被截断的半条语句不会让成员变成两种形状,合并也按保留那一段的行数定价。核对齐成员、找出洞、给参数编号、给合并定价;名字、路径、源文本都不上线。核会拒收的组——没有函数可合并的 Markdown 与 HTML、没建成的树、形状不一的成员——按原因计数,不送。T3 骨架的行数是诚实的整数估计,不是实测。本仓在一个钉住提交上与四个钉住外部语料上的建议集被冻结,并从中抽一百条交盲判审可行性。
读目录之间怎么相互依赖:哪些在最底层,拆开它们的环最省要切哪几条边,哪些文件放到常打交道的文件旁边更合适,
每个目录的扇入、扇出与不稳定度,以及改一个文件会波及哪些文件。只当顾问:没有门读它,ce arch 出文档即退 0。
arcs : dir(F) → dir(G) per file reference, dir(F) → D per package reference; inside one directory uncounted
cuts : per SCC, a subset programme when it has ≤ 14 directories (exact 1), else Eades–Lin–Smyth + redundancy pass (exact 0)
layers : level(d) = 0 when nothing leaves d, else 1 + max level of what d points at, the cut arcs removed
cluster: deterministic Louvain, gains in integers, two levels; misplaced = its cluster holds strictly more files elsewhere
impact : breadth-first over the references read backwards, the focus at depth 0
metrics: fanIn, fanOut, instability = ⌊1000 · out ÷ (in + out)⌋, −1 when nothing touches the directory
度量侧送五张整数表——被度量的文件及其目录与行数、目录树、文件到文件的引用、文件到包的引用(落在包所在目录)、
--impact 点名的文件——再把答案回标:每条切边带着它背后的文件引用。核把引用折成目录图,逐个强连通分量求反馈弧集,
给剩下的图分层,在文件图上聚类,走影响面,度量每个目录。贪心路给出的切边集是极小的、未证最小,行上照实标出。
本仓在一个钉住提交上的读数被冻结,漂移就意味着度量或核动了。