84 lines
3.6 KiB
Markdown
84 lines
3.6 KiB
Markdown
|
|
Status: Completed
|
|||
|
|
Scope: Phase 253 (`--profile quick` 回帰: mutable-acc-spec / accumulator 判定の改善)
|
|||
|
|
Related:
|
|||
|
|
- docs/development/current/main/10-Now.md
|
|||
|
|
- docs/development/current/main/phases/phase-252/README.md
|
|||
|
|
|
|||
|
|
# Phase 253: `json_lint_vm` 回帰(mutable-acc-spec)
|
|||
|
|
|
|||
|
|
## 現象(最初の FAIL)
|
|||
|
|
|
|||
|
|
`./tools/smokes/v2/run.sh --profile quick` が `json_lint_vm` で失敗する。
|
|||
|
|
|
|||
|
|
エラー:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
[ERROR] ❌ MIR compilation error: [joinir/mutable-acc-spec] Assignment form not accumulator pattern (required: target = target + x)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 背景(なぜここで落ちるか)
|
|||
|
|
|
|||
|
|
`Pattern2` の pipeline は、ループ本体の代入から「mutable accumulator(`x = x + y`)」を検出して
|
|||
|
|
最適化/簡略化に利用する。ところが現在の analyzer が Fail-Fast すぎて、
|
|||
|
|
“accumulator ではない単なる代入” を見つけた時点で Err にしてしまい、JoinIR 経路全体を落としている。
|
|||
|
|
|
|||
|
|
対象 SSOT:
|
|||
|
|
- `src/mir/loop_pattern_detection/mutable_accumulator_analyzer.rs`
|
|||
|
|
|
|||
|
|
## 方針(構造的に直す)
|
|||
|
|
|
|||
|
|
### 原則
|
|||
|
|
|
|||
|
|
- “accumulator pattern を検出できた時だけ” spec を返す。
|
|||
|
|
- それ以外は Err ではなく `Ok(None)` に戻して **別経路(通常 lowering)へ譲る**。
|
|||
|
|
- 例外として、本当に矛盾があるケースだけ Err(例: 同一変数への複数代入など、既に `Ok(None)` にしている)。
|
|||
|
|
|
|||
|
|
### 対処療法の禁止
|
|||
|
|
|
|||
|
|
- 特定関数名(`StringUtils.*`)や特定 script 名(`json_lint_vm`)で分岐しない。
|
|||
|
|
- “`-` の時だけ” のような場当たりでなく、spec と契約として整理する。
|
|||
|
|
|
|||
|
|
## 実装タスク(P0)
|
|||
|
|
|
|||
|
|
### 1) Analyzer の振る舞いを “検出器” に寄せる
|
|||
|
|
|
|||
|
|
ファイル:
|
|||
|
|
- `src/mir/loop_pattern_detection/mutable_accumulator_analyzer.rs`
|
|||
|
|
|
|||
|
|
変更案:
|
|||
|
|
- 以下のケースを `Err` ではなく `Ok(None)` に変更する(= accumulator ではないと判断する)
|
|||
|
|
- `value_node` が `BinaryOp` ではない(例: `i = s.length() - 1`)
|
|||
|
|
- `BinaryOperator` が `Add` 以外(例: `i = i - 1`)
|
|||
|
|
- 左辺が `target` と一致しない(例: `x = y + x`)
|
|||
|
|
- RHS が Literal/Variable 以外(例: `x = x + (i + 1)`)
|
|||
|
|
|
|||
|
|
目的:
|
|||
|
|
- “accumulator っぽくない代入” が混ざる loop でも、JoinIR 全体を落とさずに進める。
|
|||
|
|
|
|||
|
|
### 2) `-`(decrement)を accumulator として扱うかの設計を決める(P1 で可)
|
|||
|
|
|
|||
|
|
選択肢:
|
|||
|
|
- A) `i = i - 1` は “accumulator としては未対応” なので `Ok(None)`(安全・最小)
|
|||
|
|
- B) `i = i - 1` を “step=-1” として spec に載せる(将来の表現力は上がるが、下流の取り扱い整備が必要)
|
|||
|
|
|
|||
|
|
まずは quick を緑に戻す目的で A を推奨。
|
|||
|
|
|
|||
|
|
## テスト(仕様固定)
|
|||
|
|
|
|||
|
|
- unit tests を追加して「非 accumulator 代入があっても Err にならず `Ok(None)`」を固定する。
|
|||
|
|
- 例: ループ body に `local i = s.length() - 1` 相当の Assignment があるケース
|
|||
|
|
- 例: `i = i - 1` があるケース
|
|||
|
|
|
|||
|
|
## 受け入れ基準
|
|||
|
|
|
|||
|
|
- `./tools/smokes/v2/run.sh --profile quick` が PASS
|
|||
|
|
- “たまたま `json_lint_vm` だけ通す” ための by-name 分岐を追加していない
|
|||
|
|
- analyzer の戻り値契約が docs と tests で固定されている
|
|||
|
|
|
|||
|
|
## 結果(Phase 253 終点)
|
|||
|
|
|
|||
|
|
- `mutable_accumulator_analyzer` は “検出器” として振る舞うようになり、非 accumulator 代入で Err を出さず `Ok(None)` に譲る。
|
|||
|
|
- quick の最初の FAIL は次に切り出し(Phase 254):
|
|||
|
|
- `[joinir/freeze] Loop lowering failed: JoinIR does not support this pattern`
|
|||
|
|
- Function: `StringUtils.index_of/2`
|