# StructureFacts
> **职责**:把 CFG + GraphFacts + Dataflow 翻译成源码恢复候选(branch / loop / short-circuit / goto / scope)。
>
> **不负责**:最终 HIR 语法决策、AST 糖化。
>
> **例子**:`cfg.branch_edges(B3) + dataflow.phi_candidates_in(B5)` → `BranchCandidate { header: B3, merge: B5, arms: [B4a, B4b] }`
## 入口
```
src/structure/mod.rs
analyze_structure(proto, cfg, graph_facts, dataflow, children) -> StructureFacts
```
## 模块布局
```
src/structure/
mod.rs 入口 + 所有类型导出
common.rs 所有结构候选类型(StructureFacts / BranchCandidate / LoopCandidate 等)
analyze.rs analyze_structure 骨架,协调各子模块
helpers.rs 共享 query/cache:region entry/exit/predecessor/reducible 判定
phi_facts.rs phi → 结构候选翻译(merge arm def 提取 / generic phi fallback)
branches.rs branch 候选识别
branch_values.rs branch value merge 候选识别
loops.rs loop 候选识别(含 WhileLike 判定)
goto.rs GotoRequirement 识别
regions.rs region block 收集
scope.rs ScopeCandidate 识别
short_circuit/
branch_exit.rs 短路条件出口识别
value_merge.rs 短路值合流提取
shared.rs 短路共享设施
debug.rs dump_structure
```
## 数据流
```
LoweredProto + Cfg + GraphFacts + DataflowFacts
└─ analyze_structure
├─ branches.rs → Vec<BranchCandidate>
├─ loops.rs → Vec<LoopCandidate>
├─ short_circuit/ → Vec<ShortCircuitCandidate>
├─ goto.rs → Vec<GotoRequirement>
├─ scope.rs → Vec<ScopeCandidate>
└─ phi_facts.rs → Vec<GenericPhiMaterialization>
└─ StructureFacts { branches, loops, short_circuits, gotos, scopes, generic_phis, ... }
```
## 关键类型(`src/structure/common.rs`)
| `StructureFacts` | 所有候选的统一容器 |
| `BranchCandidate` | if / if-else 候选:header block + merge block + arms |
| `BranchValueMergeCandidate` | branch 两臂合流成值的候选 |
| `LoopCandidate` | while / repeat 候选:header + back edge + exit |
| `LoopSourceBindings` | loop 携带状态绑定信息 |
| `LoopValueMerge` / `LoopExitValueMergeCandidate` | loop 出口值合流 |
| `ShortCircuitCandidate` | 短路逻辑候选 |
| `GotoRequirement` | 必须保留的 goto/label 对 |
| `ScopeCandidate` | TBC close 作用域候选 |
| `RegionFact` / `RegionKind` | region 边界描述 |
| `GenericPhiMaterialization` | fallback phi 物化候选 |
## 应优先复用的共享设施
| `helpers.rs` | region entry/exit edge、reducible 判定、branch region block 收集、forward region 扫描 |
| `phi_facts.rs` | phi/def/incoming 翻译成结构候选,避免在 loops / branch_values / short_circuit 各处散落 |
| `short_circuit/` | 短路条件出口识别 + 值合流提取;包含 `if a or b then ... else ... end` 这类共享 then/else body 的条件 DAG,不跑到 HIR 再重新解释 DAG |
### 短路条件出口补充
`short_circuit/branch_exit.rs` 会同时提取三类条件出口 DAG:
- 线性 guard / if-then 链,例如 `if a and b then body end`。
- if-else 共享 body 链,例如 `if a or b then shared else gated end`,其中后续 header 可能把一臂接到共享 body,另一臂接到 loop continue / merge。
- 嵌套 if-else 节点组成的 guard DAG。遇到多前驱目标时会先把目标视为出口,避免把共享 continuation 或 body header 继续 follow 进后面的 merge。
在 loop 内,单纯的全图 `can_reach` 会穿过回边,不能作为“两个出口属于自然 fallthrough”的唯一依据。这里优先结合后支配关系判断出口方向;对同一共享出口在不同节点上极性不同的链,允许 relaxed linear inference 只要求最终收敛到两个出口。
## 维护规范
1. **结构证据应尽量前移**:HIR 需要的 phi 分类 / merge arm 信息优先补进 `StructureFacts`,不让 HIR 再从 dataflow 裸存储推断。
2. **候选与最终决策分开**:这一层只回答"像不像 branch/loop/short-circuit",不决定"HIR 应该选哪种语法"。
- `loops.rs` 的 `WhileLike` 判定应接受无副作用条件前缀(位运算、表访问等),不应只接受"一条裸 branch"。
3. **共享事实放 `common.rs`**,算法放子模块。
4. **复用 CFG/Dataflow query**:不私养"小型 CFG API"或"小型 Dataflow API"。
## 向后提供的事实
HIR 消费的所有结构候选,见"关键类型"一节。
## 排错指引
| branch 合流 block 识别错误 | `helpers.rs` region exit 逻辑 |
| loop 类型判断错误(while vs repeat) | `loops.rs` WhileLike 识别 |
| 短路候选丢失 | `short_circuit/branch_exit.rs`,尤其检查 guard/if-then 链和 if-else 共享 body 两类条件出口 |
| phi 归属错误(branch vs loop vs generic) | `phi_facts.rs` incoming 分类 |
| 想看结构候选 | `unluac --debug --target-stage structure-facts <file>` |