refactor(joinir): Extract legacy binding path to routing_legacy_binding.rs

Phase 179-A Step 2: Separate LoopFrontendBinding JSON construction logic
into dedicated module for better organization.

Changes:
- New file: routing_legacy_binding.rs (223 lines)
- routing.rs: cf_loop_joinir_impl() simplified to 15 lines (delegates to legacy path)
- Routing now clearly separates pattern-based vs. legacy binding paths

Benefits:
- Clear separation of concerns (pattern router vs. legacy whitelist)
- routing.rs reduced from 364 to 146 lines (60% reduction)
- Legacy path isolated for future deprecation
This commit is contained in:
nyash-codex
2025-12-08 18:36:13 +09:00
parent 7a01ffe522
commit 95f3aa429e
25 changed files with 626 additions and 755 deletions

View File

@ -40,6 +40,19 @@ JoinIR ラインで守るべきルールを先に書いておくよ:
- JoinIR が対応していないループパターン / if パターンは、必ず `[joinir/freeze]` 等で明示的にエラーにする。
- LoopBuilder 等へのサイレントフォールバックは禁止。
7. **Param の役割ParamRoleを分ける**
- JoinIR 側で扱うパラメータは概念的に 3 種類に分かれる:
- 条件専用Condition param: 継続条件や break 条件だけに使う値
- キャリアCarrier param: ループ状態pos/result など)として更新される値
- 式結果Expr param: ループが式として返す値
- ExitLine / Header PHI / InstructionRewriter は **Carrier param だけ** を対象にし、Condition/Expr param は上書きしない。
- 現状は ConditionBinding/ExitMeta/JoinFragmentMeta で役割を区別しており、将来 ParamRole enum として明示する予定。
8. **LoopHeader PHI dst は予約領域(上書き禁止)**
- LoopHeaderPhiBuilder が生成したヘッダ PHI の dst ValueId は「現在のループ値」の SSOT として扱い、
BoundaryInjector や InstructionRewriter が `Copy` などで二度書きすることを禁止する。
- merge ラインでは「ヘッダ PHI dst に対する新しい定義が出てきたら debug モードで panic する」ことで契約違反を早期検出する。
---
## 2. 主な箱と責務

View File

@ -33,9 +33,9 @@
| P2: Break | `joinir_min_loop.hako` | 単純 | 条件付きbreak | なし | なし | Outer | 単一 |
| P3: IfPHI | `loop_if_phi.hako` | 単純 | なし | なし | ifPHI | Outer | 条件付き |
| P4: Continue | `loop_continue_pattern4` | 単純 | なし | 条件付きcont | なし | Outer | 単一 |
| P5: Trimlike* | `TrimTest.trim`(設計中) | 単純 | 条件付きbreak | なし | なし | BodyLocal | 単一 |
| P5: Trimlike* | `TrimTest.trim`(設計中) | 単純 | 条件付きbreak | なし | なし | BodyLocal | 複数 |
\*P5 は Phase 171 時点では「検出+安全性判定」まで。実際の JoinIR lower は Phase 172 以降の仕事
\*P5 は Phase 171 時点では「検出+安全性判定」までだったが、Phase 172176 で Trim / `_skip_whitespace` / `_parse_string` 最小版について JoinIR→MIR lower と複数キャリア更新まで実装済み
ここまでで:
@ -209,4 +209,3 @@ loop (i < n) {
JsonParserBox / Trim 系ループのインベントリと、どの Pattern に入るかの観測ログ。
- `phase171-pattern5-loop-inventory.md`
Trim/JsonParser 向け Pattern5LoopBodyLocal 条件)設計の進捗。

View File

@ -0,0 +1,71 @@
# Phase 178: LoopUpdateAnalyzer String Detection
## Summary
Phase 178 extends `LoopUpdateAnalyzer` to detect string/complex carrier updates,
enabling Fail-Fast behavior for unsupported patterns.
## Changes
### 1. UpdateRhs Enum Extension (`loop_update_analyzer.rs`)
Added two new variants:
- `StringLiteral(String)` - for `result = result + "x"` patterns
- `Other` - for method calls and complex expressions
### 2. analyze_rhs Extension
Extended to detect:
- String literals: `ASTNode::Literal { value: LiteralValue::String(_) }`
- Method calls: `ASTNode::MethodCall { .. }`
- Other complex expressions: `ASTNode::Call`, `ASTNode::BinaryOp`, etc.
### 3. Pattern 2/4 can_lower Updates
Both `pattern2_with_break.rs` and `pattern4_with_continue.rs` now check for
string/complex updates in `can_lower()` and return `false` if detected.
This triggers a clear error message instead of silent incorrect behavior.
### 4. Legacy Fallback Comment Fixes
Updated misleading comments about "legacy fallback" - LoopBuilder was removed
in Phase 187-2 and all loops must use JoinIR.
## Behavior
When a loop contains string concatenation like:
```nyash
loop(i < limit) {
result = result + "x" // String update
i = i + 1
}
```
Phase 178 now produces a clear error:
```
[pattern2/can_lower] Phase 178: String/complex update detected, rejecting Pattern 2 (unsupported)
[ERROR] MIR compilation error: [joinir/freeze] Loop lowering failed:
JoinIR does not support this pattern, and LoopBuilder has been removed.
```
## Test Results
- P1 (simple while): OK
- P2 (break + int carriers): OK
- P4 (continue + multi-carrier): OK
- String loops: Fail-Fast with clear error
## Known Issues
- **79 global test failures**: Pre-existing issue, NOT caused by Phase 178
- Confirmed by `git stash` test - failures exist in HEAD~1
- Tracked separately from Phase 178
## Future Work
To support string loops, either:
1. Add JoinIR instructions for string concatenation (Option A)
2. Process loop body statements in MIR alongside JoinIR control flow (Option B)
Phase 178 provides the detection foundation for future string support.