Commit Graph

350 Commits

Author SHA1 Message Date
ca91be349d Refactor JoinIR lowerers and boundary 2025-12-28 03:52:52 +09:00
0269fc2ed4 Reduce build warnings 2025-12-28 01:34:46 +09:00
7ab042ca91 refactor: split large modules into submodules 2025-12-27 21:43:37 +09:00
f654dd316d Reduce unused warnings in tests and helpers 2025-12-27 17:49:42 +09:00
0d6229d5a2 Stabilize joinir tests and env guards 2025-12-27 17:41:30 +09:00
d9a1513991 docs(joinir): Phase 287 P8 - Add rewriter README/guard 2025-12-27 13:56:44 +09:00
5e7434c6d4 refactor(joinir): Phase 287 P7 - Remove unused rewriter box scaffolding 2025-12-27 13:37:57 +09:00
f225e27007 refactor(joinir): Phase 287 P6 - Remove scan stage (2-stage pipeline) 2025-12-27 13:25:15 +09:00
ce2b4b97e5 refactor(joinir): Tighten plan stage helper visibility 2025-12-27 13:18:54 +09:00
8774bf2fde refactor(joinir): Phase 287 P5 - Stages facade re-export 2025-12-27 13:14:45 +09:00
3c52ba954e refactor(joinir): Phase 287 P4 - Modularize plan stage (facade) 2025-12-27 12:48:33 +09:00
3224d83a7b refactor(joinir): Phase 287 P3 - Split instruction_rewriter into stages 2025-12-27 12:17:34 +09:00
fe895e8838 refactor(joinir): Phase 287 P2 - Modularize contract_checks (facade pattern)
- contract_checks.rs (846行) を facade 化
- 6モジュールへ分割(1 module = 1 contract):
  - terminator_targets.rs (208行) - Branch/Jump検証
  - exit_bindings.rs (35行) - exit_bindings ↔ exit_phis
  - carrier_inputs.rs (145行) - carrier_inputs完全性
  - boundary_creation.rs (160行) - B1/C2不変条件
  - entry_params.rs (317行) - Entry param一貫性
  - mod.rs (30行) - Facade
- Total: 846 → 895行(+49行モジュール境界オーバーヘッド)
- 意味論不変: エラータグ/ヒント文すべて保存
- Fail-Fast遵守: silent fallback追加なし
- 検証: Build 0 errors / Pattern6 RC=9 / quick 154/154 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 11:05:40 +09:00
de1cd1fea0 refactor(joinir): Phase 287 P1 - Modularize ast_feature_extractor (facade pattern)
Extracted pattern recognizers from ast_feature_extractor.rs (1,148 lines) into
specialized modules under pattern_recognizers/ directory.

**Structure**:
- ast_feature_extractor.rs: Facade (135 lines, re-exports)
- pattern_recognizers/: 8 modules (1,126 lines total)
  - continue_break.rs: continue/break/return detection
  - infinite_loop.rs: loop(true) detection
  - if_else_phi.rs: if-else PHI pattern detection
  - carrier_count.rs: carrier variable counting
  - parse_number.rs: parse_number pattern (+ read_digits)
  - parse_string.rs: parse_string pattern (+ continue pattern)
  - skip_whitespace.rs: skip_whitespace pattern

**Contract**:
- Semantic invariance: All existing APIs preserved via re-exports
- No routing changes, no detection spec changes
- Public API unchanged (facade pattern)

**Verification**:
- Build: 0 errors, 0 warnings
- Pattern6: RC:9 (maintained)
- Smoke tests: 154/154 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 10:42:17 +09:00
e51777b448 refactor(joinir): Phase 287 P0.6 - Final mod.rs cleanup
Add comprehensive modularization summary comment documenting the
complete Phase 287 P0 refactoring journey.

Changes:
- MOD: merge/mod.rs: Add modularization summary (19 lines)
- Final size: 1,053 lines (was 1,555 in Phase 286)
- Total reduction: -502 lines (-32%)

Modularization Summary:
- P0.1: debug_assertions.rs (verification functions)
- P0.2: value_remapper.rs (ValueId remapping helper)
- P0.3: entry_selector.rs (SSOT entry function selection)
- P0.4: header_phi_prebuild.rs (PHI pre-build orchestration)
- P0.5: boundary_logging.rs (consolidated logging)

Remaining in mod.rs (orchestrator only):
- Public API: merge_joinir_mir_blocks()
- Phase 1-6 pipeline coordination
- Phase 3.5: Parameter → PHI dst remapping (complex, kept inline)
- Phase 6: Boundary reconnection and expr_result resolution

SSOT Principles Enforced:
 Entry selection: boundary.loop_header_func_name > continuation_func_ids
 No string-based heuristics ("k_exit" prefix matching eliminated)
 Logging: debug/verbose only (no constant logs in quick profile)
 Reserved ValueIds: PHI dsts protected from conflicts

Verification:
- Build: 0 errors
- Pattern6: RC:9 
- Smoke: 154/154 PASS (verified via quick profile)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 10:27:44 +09:00
91daec104f refactor(joinir): Phase 287 P0.5 - Extract boundary_logging
Extract boundary logging functions to boundary_logging.rs (112 lines).
Consolidates scattered trace.stderr_if() calls into focused functions.

SSOT Principle:
- Only use trace.stderr_if(..., debug/verbose) - NO constant logs
- Prevents noise in quick smoke tests
- Consistent logging format across boundary operations

Changes:
- NEW: merge/boundary_logging.rs (112 lines)
- MOD: merge/mod.rs: 1,027 → ~973 lines (-54 lines)
- Functions:
  - log_boundary_info() - Comprehensive boundary logging (verbose mode)
  - log_merge_complete() - Merge completion summary (debug mode)

Logging Consolidated:
- Boundary join_inputs / host_inputs
- Exit bindings (carrier mappings)
- Condition bindings (if any)
- Carrier info (if present)
- Merge completion summary

Verification:
- Build: 0 errors
- Pattern6: RC:9 
- Smoke: 154/154 PASS (verified via quick profile)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 10:25:21 +09:00
5ee3b62042 refactor(joinir): Phase 287 P0.4 - Extract header_phi_prebuild
Extract header PHI pre-build orchestration to header_phi_prebuild.rs
(~220 lines). This is orchestration logic that coordinates entry
selection, block remapping, carrier extraction, and PHI building.

Changes:
- NEW: merge/header_phi_prebuild.rs (220 lines)
- MOD: merge/mod.rs: 1,233 → ~1,027 lines (-206 lines)
- Function: prebuild_header_phis() - orchestrates PHI pre-build
- Helper: get_default_entry_block() - fallback for no boundary

Orchestration Responsibilities:
- Entry function selection (via entry_selector SSOT)
- Block remapping (loop_header vs merge_entry)
- Carrier extraction from boundary (with exit_bindings filtering)
- LoopHeaderPhiBuilder invocation
- Reserved ValueId collection (PHI dsts + function params)

Verification:
- Build: 0 errors
- Pattern6: RC:9 
- Smoke: 154/154 PASS (verified via quick profile)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 10:21:28 +09:00
fb2ac627da refactor(joinir): Phase 287 P0.3 - Extract entry_selector (SSOT)
Extract entry function selection logic to entry_selector.rs (93 lines).
This enforces SSOT principles for loop header and merge entry selection.

SSOT Strategy:
1. Prefer boundary.loop_header_func_name (explicit specification)
2. Fallback: Exclude MAIN and continuation_func_ids (SSOT, not string matching)
3. Never use "k_exit" prefix heuristics

Changes:
- NEW: merge/entry_selector.rs (43 lines net after extraction)
- MOD: merge/mod.rs: 1,269 → ~1,233 lines (-36 lines)
- Functions:
  - select_loop_step_func_name() (loop header SSOT)
  - select_merge_entry_func() (Pattern 3 if-sum support)
  - get_function() (helper with error handling)

Verification:
- Build: 0 errors
- Pattern6: RC:9 
- Smoke: 154/154 PASS (verified via quick profile)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 10:17:49 +09:00
95fef8696d refactor(joinir): Phase 287 P0.2 - Extract value_remapper
Extract remap_values() to value_remapper.rs (46 lines). This is a pure
helper function that allocates new ValueIds while avoiding conflicts
with reserved PHI dst ValueIds.

Changes:
- NEW: merge/value_remapper.rs (Phase 3 helper)
- MOD: merge/mod.rs: 1,315 → ~1,269 lines (-46 lines)
- Delegation: value_remapper::remap_values() called from orchestrator

Verification:
- Build: 0 errors
- Pattern6: RC:9 
- Smoke: 154/154 PASS (verified via quick profile)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 10:14:27 +09:00
433e1d45c0 refactor(joinir): Phase 287 P0.1 - Move verification to debug_assertions
- Move verify_no_phi_dst_overwrite() to debug_assertions.rs
- Move verify_phi_inputs_defined() to debug_assertions.rs
- Move verify_joinir_contracts() to debug_assertions.rs
- Remove duplicate get_instruction_dst() from mod.rs
- mod.rs: 1,555 → ~1,380 lines (-176 lines)
- Semantic invariance: 154/154 smoke tests PASS, Pattern6 RC:9

Phase 287 P0: Big Files Refactoring (意味論不変)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 10:10:59 +09:00
a04b48416e fix(joinir): Phase 287 P2 - Pattern6 nested loop latch overwrite fix
Fix infinite loop in Pattern6 (nested loop minimal) caused by main→loop_step
overwriting k_inner_exit→loop_step latch values.

Root cause: JoinIR main entry block was incorrectly treated as BackEdge,
causing it to overwrite the correct latch incoming values set by the true
back edge (k_inner_exit → loop_step).

Solution:
- Restrict latch recording to TailCallKind::BackEdge only
- Treat only MAIN's entry block as entry-like (not loop_step's entry block)
- Add debug_assert! to detect double latch set in future

Refactoring:
- Extract latch recording to latch_incoming_recorder module (SSOT)
- Add boundary.loop_header_func_name for explicit header identification
- Strengthen tail_call_classifier with is_source_entry_like parameter

Tests: apps/tests/phase1883_nested_minimal.hako → RC:9 (was infinite loop)
Smoke: 154/154 PASS, no regressions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 09:39:29 +09:00
bbfc3c1d94 refactor(joinir): Phase 287 P2 - Strengthen BackEdge/latch conditions (WIP)
**Problem**: Phase 188.3 Pattern6 (nested loop) encounters infinite loop
- inner_step → inner_step (self-recursion) incorrectly classified as BackEdge
- → redirects to outer header (loop_step) instead of inner_step entry
- is_recursive_call causes inner recursion to overwrite outer latch values
- → PHI receives wrong values → i doesn't increment → infinite loop

**Fix 1: BackEdge classification strictness** (tail_call_classifier.rs)
- Add `is_target_loop_entry` parameter to classify_tail_call()
- BackEdge ONLY when target==loop_step (entry_func), not inner_step
- Prevents inner_step → inner_step from redirecting to outer header

**Fix 2: latch_incoming guard** (instruction_rewriter.rs)
- Change condition from `is_recursive_call || is_target_loop_entry`
  to `is_target_loop_entry` only
- Prevents inner_step self-recursion from overwriting outer loop's latch
- set_latch_incoming() now called with correct values (verified by debug)

**Status**: 🚧 WIP - Infinite loop still occurs
- set_latch_incoming('i', BasicBlockId(8), ValueId(21))  Called correctly
- But final PHI: `phi [%4, bb8]` instead of `phi [%21, bb8]` 
- Root cause likely in PHI generation (merge/mod.rs), not latch_incoming
- Next: Investigate why latch_incoming values aren't used in PHI

**Files**:
- src/mir/builder/control_flow/joinir/merge/tail_call_classifier.rs
- src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 08:32:14 +09:00
d0527bcc2a feat(joinir): Phase 188.3-P3.3 - Pattern6 continuation generation + Call callee fix
Phase 3-3 完了: 4関数モデル JoinIR 生成
- nested_loop_minimal.rs (337行, 新規): 4関数モデル実装
  - main(): エントリーポイント
  - loop_step(i, sum): outer loop header
  - inner_step(j, i_outer, sum): inner loop (tail recursion)
  - k_inner_exit(i, sum): outer continuation after inner loop
  - k_exit(sum): 最終 exit
- pattern6_nested_minimal.rs: lowering pipeline 実装
  - boundary 構築 (continuation_func_ids 設定)
  - JoinIRConversionPipeline 呼び出し
- instruction_rewriter.rs: latch incoming 拡張
  - continuation→header 呼び出し対応

Call callee 修正:
- call_generator.rs: callee フィールドを Callee::Global に設定
- joinir_block_converter.rs: emit_call_pair 使用に統一

smoke test 追加:
- phase1883_nested_minimal_vm.sh (integration)

既知の問題 (次タスク):
- ValueId(104) undefined: PHI/merge 問題
- JoinIR 関数パラメータの MIR マッピングが不完全

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 06:51:43 +09:00
c6ffc06660 feat(joinir): Phase 188.3-P3.1,3.2 - AST extraction & validation helpers
Phase 3-1 完了: extract_inner_loop_ast() 実装
- 外側 loop body から内側 loop を抽出
- 正確に 1 つの inner loop を検証
- 0 個 or 2+ 個の場合は明示エラー (Fail-Fast)

Phase 3-2 完了: validate_strict_mode() プレースホルダー
- 現在は大半の検証を is_pattern6_lowerable() で実施
- 将来の strict mode チェック用の足場

ドキュメント追加:
- P1-INSTRUCTIONS.md: Phase 3-3 実装指示書 (4関数モデル詳細)
- README.md: max_loop_depth 定義の明確化
- 10-Now.md: Phase 188.3 方針の整合性維持

次タスク: Phase 3-3 (Continuation 生成) - P1-INSTRUCTIONS.md 参照

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 06:22:59 +09:00
a2c5fd90fe feat(joinir): Phase 188.3 - Pattern6 (NestedLoopMinimal) 選択ロジック実装
## Phase 188.3 進捗: Phase 2 完了 (6/13 tasks)

### 実装完了 

**Phase 1: Fixture作成**
- apps/tests/phase1883_nested_minimal.hako 追加
  - Add/Compare のみ(乗算なし)
  - 期待 exit code: 9 (3×3 nested loops)
- 既存 lowering で fallback 動作確認

**Phase 2: 選択ロジック (SSOT)**
- LoopPatternContext に step_tree_max_loop_depth フィールド追加
- choose_pattern_kind() に Pattern6 選択ロジック実装:
  1. Cheap check (has_inner_loop)
  2. StepTree 構築 (max_loop_depth 取得)
  3. AST validation (is_pattern6_lowerable)
- pattern6_nested_minimal.rs モジュール作成 (stub)
- LOOP_PATTERNS に Pattern6 entry 追加
- **検証**: Pattern6 が正しく選択される 

### 設計原則 (確認済み)

1. **Fail-Fast**: Pattern6 選択後は Ok(None) で逃げない
2. **outer 変数 write-back 検出 → validation false** (Phase 188.4+)
3. **最小実装**: inner local だけ、Pattern1 モデル二重化
4. **cfg! 依存なし**: production で動作

### 検証結果

```
[choose_pattern_kind] has_inner_loop=true
[choose_pattern_kind] max_loop_depth=2
[choose_pattern_kind] is_pattern6_lowerable=true
 Pattern6 SELECTED!
```

Stub からの期待エラー:
```
[ERROR]  [Pattern6] Nested loop lowering not yet implemented
```

### 次: Phase 3 (Lowering 実装 - 推定4時間)

残りタスク:
- Phase 3-1: AST 抽出ヘルパー
- Phase 3-2: Validation ヘルパー
- Phase 3-3: Continuation 生成 (outer_step, inner_step, k_inner_exit)
- Phase 3-4: fixture が exit=9 を返すことを検証

### 変更ファイル

**新規**:
- apps/tests/phase1883_nested_minimal.hako
- src/mir/builder/control_flow/joinir/patterns/pattern6_nested_minimal.rs
- docs/development/current/main/phases/phase-188.{1,2,3}/README.md

**変更**:
- src/mir/builder/control_flow/joinir/routing.rs (Pattern6 選択)
- src/mir/builder/control_flow/joinir/patterns/router.rs (Context 拡張)
- src/mir/builder/control_flow/joinir/patterns/mod.rs (module 宣言)

🎯 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 05:45:12 +09:00
7a575e30cc refactor(joinir): Phase 286 P3.2 cleanup + normalizer modularization
## Legacy Pattern5 削除 (488行)
- pattern5_infinite_early_exit.rs 完全削除
- LOOP_PATTERNS テーブルからエントリ削除
- Plan extractor が SSOT

## Normalizer 分割 (3294行 → 12ファイル)
- helpers.rs: 共通ヘルパー関数
- pattern*.rs: 各パターン専用ファイル
- mod.rs: ディスパッチャ

## ドキュメント更新
- Phase 286 README: クリーンアップ完了・Fail-Fast方針記載
- Phase 287 README: 将来計画

quick smoke 154/154 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 10:30:08 +09:00
22945c190c feat(joinir): Phase 286 P3.2 - Pattern5 Plan line (loop(true) + early exit)
- Pattern5InfiniteEarlyExitPlan (Return/Break variants)
- extract_pattern5_plan() for loop(true) literal only
- normalize_pattern5_return(): 5 blocks CFG (header→body→found/step)
- normalize_pattern5_break(): 6 blocks CFG with carrier PHI
- NormalizationPlanBox exclusion for Pattern5-style loops
- Fixtures: phase286_pattern5_{return,break}_min.hako
- quick smoke 154/154 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 09:56:34 +09:00
b235a5b6db feat(joinir): Phase 286 P3.1 - Pattern2 Plan line 完走(after_bb PHI)
Pattern2(Loop with Break)を Plan/Frag SSOT へ移行。

主な変更:
- Pattern2BreakPlan 追加(DomainPlan variant)
- extract_pattern2_plan() 実装(PoC サブセット厳守)
- normalize_pattern2_break() 実装(6-block CFG, 3 PHI)
- after_bb PHI が本質: carrier_out = PHI(header: carrier_current, break_then: carrier_break)
- router に Pattern2 追加(Pattern1 より前、より具体的)

テスト:
- Fixture B (break without update): PASS (出力 11)
- quick smoke: 154/154 PASS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:56:30 +09:00
f76fb6cd3e refactor(joinir): Phase 286 P2.8 - Normalizer Hygiene(小箱化・重複削減)
- LoopBlocksStandard5: 5-block レイアウト(Pattern1/9 で使用)
- LoopBlocksWithIfPhi: 8-block レイアウト(Pattern3 で使用)
- create_phi_bindings(): phi_bindings 作成ヘルパー(全5パターンで使用)

リファクタ適用:
- Pattern1: LoopBlocksStandard5 + create_phi_bindings
- Pattern3: LoopBlocksWithIfPhi + create_phi_bindings
- Pattern4: create_phi_bindings(8-block は別構造のため据え置き)
- Pattern8: create_phi_bindings(6-block は別構造のため据え置き)
- Pattern9: LoopBlocksStandard5 + create_phi_bindings

意味論は完全不変。quick 154/154 PASS。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:08:09 +09:00
630ed02c48 feat(joinir): Phase 286 P2.7 - V10不変条件追加(body_bb effects契約)
- verifier.rs: V10検証追加 - body_bbのblock_effectsは空でなければならない
  - 違反時: "[V10] Loop at depth N has non-empty block_effects for body_bb"
  - テスト: test_v10_body_bb_effects_in_block_effects_fails
- joinir-plan-frag-ssot.md: V10をPlan段階の不変条件に追加
- README.md: P2.7セクション追加

Phase 286 P2.6.1で発見した「lowererはloop_plan.bodyをemitし、
block_effectsのbody_bbは無視する」問題を契約化し再発防止。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 04:55:14 +09:00
0fca2df5be feat(joinir): Phase 286 P2.6.1 - Pattern3 Plan 完走(normalizer 実装 + Fail-Fast 統一)
## 変更内容

### Router Fail-Fast 統一
- Pattern3 stub fallback 特例を撤去
- extract 成功 → normalize/lower 失敗は即 Err(他パターンと統一)

### normalize_pattern3_if_phi() 実装
- CFG 構造: 8 blocks (preheader, header, body, then, else, merge, step, after)
- PHI 構成: 3本(header×2 + merge×1)
  - Header: loop_var_current, carrier_current
  - Merge: carrier_next (if-else 合流)
- Frag: BranchStub×2 + EdgeStub×4(Pattern1 流儀の直接構築)

### 発見・修正
- lowerer は body_bb の block_effects を無視して loop_plan.body を emit
- body_bb effects は CorePlan::Effect(...) として loop_plan.body に配置

## テスト結果
- Phase 118 smoke: PASS (出力 12)
- quick: 154/154 PASS
- Plan line 完走確認: route=plan ... Pattern3_IfPhi MATCHED

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 04:39:36 +09:00
3abca63ebe refactor(joinir): Phase 286 P2.6 コード品質 - pattern3.rs 重複削除 + 共通化
## 変更内容
- pattern3.rs: has_return_statement() 削除 → common_helpers 使用
- pattern3.rs: has_control_flow_statement() → has_forbidden_control_flow_for_pattern3() にリネーム
  - Pattern3 固有のセマンティクス(ネスト if 禁止)を明確化
- common_helpers.rs: find_if_else_statement() 追加
  - PoC subset コメント付き(最初の if-else だけ取る)

## 効果
- 重複コード削除: -34 lines net
- 関数名で意図を明確化(Pattern3 固有の制約)
- common_helpers の再利用性向上

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 04:13:13 +09:00
4d17e3d812 feat(joinir): Phase 286 P2.6 - Pattern3 Plan 基盤 + Pattern1 退行修正
## Pattern1 退行修正(構造的 Fail-Fast)
- Router に pattern_kind ガード追加(ctx.pattern_kind != Pattern1SimpleWhile → skip)
- has_if_else_statement() ヘルパー追加(再帰版、ScopeBox/Loop 内もチェック)
- Pattern1 extractor に if-else 拒否追加

## Pattern3 Plan 基盤
- DomainPlan: Pattern3IfPhiPlan 構造体追加
- Extractor: extract_pattern3_plan() 追加
- Normalizer: normalize_pattern3_if_phi() スタブ追加(レガシー JoinIR へフォールバック)
- Router: PLAN_EXTRACTORS に Pattern3 追加

## テスト結果
- quick 154 PASS
- Phase 118 smoke PASS(出力 12、退行解消)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 04:01:11 +09:00
21daf1b7dd refactor(joinir): Phase 286 コード品質改善 - ヘルパー共通化 + static box フィルタ
## 1. lower_*_ast ヘルパー共通化
- `lower_value_ast()` に MethodCall 対応追加
- Pattern8 normalizer も共有ヘルパーを使用
- Pattern1/8/9 で一貫した lowering ロジック

## 2. PLAN_EXTRACTORS ドキュメント追加
- `WithPostLoop` variant: 将来拡張用として残存理由を明記
- 現在は常に `&[]` を渡すが、post-loop segment analysis 用に保持

## 3. Legacy Pattern8 残存 + static box フィルタ
- Plan extractor は pure 関数(builder にアクセス不可)
- router 側で static box フィルタリングを実装
- static box コンテキストは legacy Pattern8 へ fallback
- legacy 残存理由をドキュメント化

## 検証
- Quick: 154 PASS, 0 FAILED
- Pattern8 integration: exit 7

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 03:35:02 +09:00
832d018046 feat(joinir): Phase 286 P2.4.1 - Pattern8 normalizer 実装 + Fail-Fast 化
## 概要
Pattern8 (BoolPredicateScan) を Plan line で完走させる。
stub normalizer を完全実装に置き換え、legacy fallback を禁止。

## Step 0: Fixture 簡約
- `?:` ternary → `if/else` に変更(PoC 安定化)

## Step 1: Router Fail-Fast 化
- 文字列判定 `e.contains("[normalizer/pattern8]")` を削除
- extract が Some → normalize/lower 失敗は即 Err(fallback 禁止)
- extract が None → 次の extractor へ(legacy 含む)

## Step 2: Pattern8 normalizer 実装
- CFG: preheader → header(PHI) → body → found/step → after
- found: return false(早期脱出)
- after: return true(ループ完走)
- compose::cleanup() で 2 つの Return exit をマージ

## 検証結果
- Integration: exit 7 
- Plan 完走: route=plan strategy=extract pattern=Pattern8 MATCHED
- Regression: quick 154 PASS, 0 FAILED

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 03:17:48 +09:00
064cae169e feat(joinir): Phase 286 P2.4 - Pattern8 BoolPredicateScan Plan化 PoC
## 概要
Pattern8 (BoolPredicateScan) を Plan extraction routing に追加。
static box 除外(Phase 269 決定)を尊重し、非 static box fixture で PoC。

## 実装内容
- Pattern8BoolPredicateScanPlan struct + DomainPlan variant
- extract_pattern8_plan(): 条件・predicate check・increment 抽出
- normalize_pattern8_bool_predicate_scan(): PoC stub(CoreExitPlan::Return 未統合)
- PLAN_EXTRACTORS テーブルに Pattern8 追加(3rd priority)
- エラーフォールバック: Plan normalization 失敗時 → legacy Pattern8 へ

## 動作フロー
Plan extraction MATCHED → normalization failed (PoC stub) → legacy Pattern8 MATCHED

## 検証結果
- Integration: phase286_pattern8_plan_poc_vm PASS (exit 7)
- Regression: quick 154 PASS, 0 FAILED

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 03:01:11 +09:00
1d24e9a106 feat(joinir): Phase 286 P2.3 + Phase 287 - Pattern9 Plan化 + Router table-driven
## Phase 286 P2.3: Pattern9 AccumConstLoop Plan化 PoC

- DomainPlan::Pattern9AccumConstLoop 追加
- PlanNormalizer::normalize_pattern9_accum_const_loop() 実装
  - PHI 2本(loop_var, acc_var)
  - const/var 両方 OK(sum = sum + 1 または sum = sum + i)
- Pattern9 は Pattern1 より優先(より具体的なパターン)
- Integration test: phase286_pattern9_frag_poc PASS (return: 3)
- Regression: quick 154 PASS

## Phase 287: Router table-driven Plan extraction

- PLAN_EXTRACTORS static table で Pattern6/7/4/9/1 を統一管理
- PlanExtractorEntry/PlanExtractorVariant 構造体追加
- try_plan_extractors() で ~100行 → 3行に集約
- メンテナンス性向上(新 Pattern 追加はテーブル1行追加のみ)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 02:38:09 +09:00
a824346e30 feat(joinir): Phase 286 P2/P2.1/P2.2 - JoinIR Line Absorption (Pattern1/4 Plan化 PoC + hygiene)
Phase 286 P2: Pattern4 (Loop with Continue) を Plan/Frag SSOT に移行
- DomainPlan::Pattern4Continue 追加
- PlanNormalizer::normalize_pattern4_continue() 実装(phi_bindings による PHI dst 優先参照)
- Router integration(Plan line routing → legacy fallback)
- Integration test PASS (output: 6), quick smoke 154/154 PASS

Phase 286 P2.1: Pattern1 (SimpleWhile) を Plan/Frag SSOT に移行
- DomainPlan::Pattern1SimpleWhile 追加
- PlanNormalizer::normalize_pattern1_simple_while() 実装(4ブロック、1 PHI、phi_bindings 流用)
- Router integration(Plan line routing → legacy fallback)
- Integration test PASS (return: 3), quick smoke 154/154 PASS

Phase 286 P2.2: hygiene(extractor重複排除 + router小整理)
- extractor helper化: extract_loop_increment_plan を common_helpers.rs に統一
  - Pattern1/Pattern4 が呼ぶだけに変更(重複排除 ~25行)
- router helper化: lower_via_plan() を追加し Pattern6/7/4/1 で共用
  - 3行パターン(normalize→verify→lower)を1関数に集約(ボイラープレート削減 ~40行)

成果物:
- DomainPlan 2パターン新規追加(Pattern1SimpleWhile, Pattern4Continue)
- Normalizer 2つの normalize 関数追加
- Router に Plan line ブロック追加 + lower_via_plan() helper
- Extractor に extract_pattern1_plan() 追加
- Integration fixtures 2個 + smoke tests 2個

検証:
- quick smoke: 154/154 PASS
- integration: phase286_pattern1_frag_poc PASS, phase286_pattern4_frag_poc PASS
- Plan line routing: route=plan strategy=extract で Pattern1/4 検出確認

🤖 Generated with Claude Code

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-26 02:03:22 +09:00
fa00ed3018 refactor(joinir): Split contract_checks.rs into 2 files (Phase 286C-4.3)
Split 1,239-line contract_checks.rs into responsibility-based modules
for better maintainability and clarity.

## Changes

1. **New file: debug_assertions.rs** (440 lines)
   - 6 debug-only verification functions (panic! on violation)
   - All functions guarded with #[cfg(debug_assertions)]
   - Excluded from release builds
   - Functions:
     * verify_loop_header_phis()
     * verify_exit_line()
     * verify_exit_phi_no_collision()
     * verify_valueid_regions()
     * verify_condition_bindings_consistent()
     * verify_header_phi_dsts_not_redefined()

2. **Updated: contract_checks.rs** (1,239 → 848 lines, -391 lines)
   - Kept 6 Fail-Fast functions (Result<(), String>)
   - Kept all 13 unit tests
   - Removed debug-only functions and imports

3. **Updated: mod.rs**
   - Added `mod debug_assertions;` declaration

## Responsibility Split

- **contract_checks.rs**: Fail-Fast contracts (production)
  - Return errors with diagnostic messages
  - Run in both debug and release builds

- **debug_assertions.rs**: Debug-only assertions (development)
  - Panic on contract violations
  - Excluded from release builds (#[cfg(debug_assertions)])

## Benefits

- Single Responsibility Principle (each file <850 lines)
- Clear separation: Fail-Fast vs Debug-only
- Improved maintainability (localized changes)
- Better build performance (debug code stripped in release)

## Test Results

-  Build: 0 errors
-  Smoke tests: 45/46 PASS (no regression)
-  core_direct_array_oob_set_rc_vm: FAIL (existing known issue)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 06:08:46 +09:00
ad1a8bd8ec feat(joinir): Add carrier_inputs completeness contract (Phase 286C-4.2)
Adds Fail-Fast contract to verify carrier_inputs completeness at plan stage,
preventing silent bugs where carrier collection is skipped.

## Changes

1. **contract_checks.rs**:
   - Added `verify_carrier_inputs_complete()` function
   - Checks all non-ConditionOnly carriers are present in carrier_inputs
   - Error tag: `[joinir/contract:C4]` for grep-friendly diagnostics
   - Added test helper `make_boundary()` for JoinInlineBoundary construction
   - Added 3 unit tests (missing carrier, ConditionOnly skip, valid case)

2. **instruction_rewriter.rs**:
   - Call `verify_carrier_inputs_complete()` after plan_rewrites()
   - Runs before apply_rewrites() for clean error state

## Contract

For each non-ConditionOnly exit_binding:
- `carrier_inputs[carrier_name]` must exist

Catches bugs where:
- CarrierInputsCollector fails to add a carrier
- plan_rewrites skips a carrier mistakenly
- exit_phi_builder receives incomplete carrier_inputs

## Test Results

-  json_lint_vm: PASS (was FAIL in 286C-4.1 before fix)
-  Full suite: 45/46 PASS (no regression)
-  core_direct_array_oob_set_rc_vm: FAIL (existing known issue)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 05:43:34 +09:00
86dfa30abe chore(joinir): Phase 286C-5 Step 3 - Remove unused imports
Ran `cargo fix --allow-dirty --lib` to automatically remove unused imports
across the codebase. This cleanup is standard maintenance and improves code
hygiene.

**Files Modified**:
- instruction_rewriter.rs: Removed 6 unused imports
  - block_remapper::remap_block_id
  - LoweringDecision
  - ParameterBindingBox
  - propagate_value_type_for_inst (2 occurrences)
  - apply_remapped_terminator
  - PhiAdjustment, ParameterBinding from scan_box
- Other files: Minor unused import cleanup (12 files total)

**No Functional Changes**: Pure cleanup, all tests expected to pass.

Phase 286C-5 progress: 3/4 steps complete

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:18:06 +09:00
14ff126934 refactor(joinir): Phase 286C-5 Step 1 - CarrierInputsCollector Box extraction
Extract duplicated carrier_inputs collection logic into a dedicated Box:

**DRY Achievement**:
- Remove duplication between Return fallback (lines 740-763) and ExitJump
  handling (lines 876-909)
- Single source of truth for carrier PHI fallback logic
- Reduced code size by ~30 lines (60 duplicated → 30 unified)

**Box Structure**:
- CarrierInputsCollector: Encapsulates carrier PHI collection from header
- Input: boundary + loop_header_phi_info
- Output: Vec<(carrier_name, block_id, value_id)>
- Filters ConditionOnly carriers automatically
- Handles DirectValue fallback to host_slot

**Files Modified**:
- instruction_rewriter.rs: Replace 2 inline blocks with Box calls
- carrier_inputs_collector.rs: New Box implementation (95 lines)
- rewriter/mod.rs: Export new module

**Contract Preserved**:
- Identical logic: ConditionOnly filter → header PHI → DirectValue fallback
- Same logging output format
- No behavior change, pure refactoring

Phase 286C-5 progress: 1/4 steps complete

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:16:22 +09:00
bfc63b0e3c fix(joinir): collect carrier_inputs for skippable ExitJump (Phase 286C-4.1)
After the Phase 286C-4 refactoring, carrier_inputs was not being
collected when a tail call's TailCallKind is ExitJump and the target
is a skippable continuation. This caused json_lint_vm to fail with:

  [joinir/phase118/exit_phi/missing_carrier_phi]
  exit_bindings carrier 'i' is missing from exit_carrier_phis

Root cause: The 3-stage pipeline refactoring separated Return→Jump
conversion (which collected carrier_inputs) from tail call handling.
When found_tail_call=true, the Return processing was skipped entirely,
but tail call handling didn't collect carrier_inputs.

Fix: Add carrier_inputs collection in the ExitJump (skippable) path
at lines 901-934. This mirrors the fallback logic from the Return
processing path.

Test results: 45/46 PASS (same as before refactoring)
- json_lint_vm: PASS (was FAIL)
- core_direct_array_oob_set_rc_vm: FAIL (unchanged, known issue)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:05:49 +09:00
e55665aa22 fix(joinir): verbose flag should not use env var (test pollution)
joinir_dev_enabled() was being used in verbose flags, causing debug
output to appear during smoke tests and polluting expected output.

Changed 3 locations from:
  let verbose = debug || crate::config::env::joinir_dev_enabled()
To:
  let verbose = debug

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 04:42:32 +09:00
5b74b3134a refactor(orchestrator): Phase 286C-4 Step 4 - Complete 3-stage pipeline (~1150 lines removed)
Transformed merge_and_rewrite() from monolithic function to orchestrator:

**File Reduction**:
- Before: 2437 lines
- After: 1289 lines
- Removed: 1148 lines (47% reduction)

**New Architecture**:
- Stage 1: scan_blocks() - Read-only analysis (~200 lines)
- Stage 2: plan_rewrites() - Generate rewritten blocks (~550 lines)
- Stage 3: apply_rewrites() - Mutate builder (~160 lines)

**merge_and_rewrite() Now**:
- Metadata setup (~80 lines)
- Call 3-stage pipeline (~50 lines)
- DirectValue processing (~50 lines)
- Result building (~20 lines)
- Total: ~200 lines (down from ~1350)

**Benefits**:
- Clear separation of concerns (scan/plan/apply)
- No builder mutation until apply stage
- Easier to test and maintain
- Preserves all functionality

Build passes successfully. Phase 286C-4 complete.
2025-12-25 04:09:11 +09:00
8619ed07b9 feat(apply): Phase 286C-4 Step 3 - Implement apply_rewrites() (~160 lines)
Implemented apply_rewrites() stage to mutate MirBuilder:

**Block Addition**:
- Add all new blocks to current function
- Debug logging for blocks with 4+ instructions

**Boundary Injection** (~100 lines):
- Call BoundaryInjector::inject_boundary_copies()
- Build value_map for join_inputs and condition_bindings
- Collect PHI dst IDs from loop_header_phi_info

**Context Updates**:
- Add phi_inputs to ctx.exit_phi_inputs
- Add carrier_inputs to ctx.carrier_inputs

**Fix**:
- Use `ref args` in tail_call_target destructuring to avoid move error

Build passes successfully.
2025-12-25 04:04:50 +09:00
21e855d62a feat(plan): Phase 286C-4 Step 2 - Complete plan_rewrites() (~370 lines)
Added parameter binding insertion and terminator conversion to plan_rewrites():

**Parameter Binding (~100 lines)**:
- Generate Copy instructions for tail call arguments
- Handle recursive/continuation/normal tail calls
- Skip bindings for loop header PHIs
- Record latch incoming for loop header PHI

**Terminator Conversion (~270 lines)**:
- Return → Jump conversion using ReturnConverterBox
- Exit value collection using ExitArgsCollectorBox
- Update result.phi_inputs and result.carrier_inputs
- Handle tail call Jump terminators with classification

Plan stage now generates complete RewrittenBlocks ready for apply stage.
Build passes with warnings only.
2025-12-25 04:01:44 +09:00
a78742b6d7 refactor(plan): Phase 286C-4 Step 2 - plan_rewrites() initial implementation
Extract block generation logic from merge_and_rewrite() into plan_rewrites():
- Function/block initialization (~70 lines)
- First pass: instruction filtering (~180 lines)
- Span synchronization (~20 lines)

Implemented:
- Instruction filtering using InstructionFilterBox
- Block ID remapping with local_block_map
- PHI dst protection for loop headers
- Deterministic function/block iteration

TODO (Step 2 continuation):
- Parameter binding insertion for tail calls (~100 lines)
- Terminator conversion logic (~270 lines)
- Exit PHI/carrier input collection

Current: ~290 lines extracted, target ~550 lines

Progress: Step 2/4 (plan_rewrites) partial

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 03:57:43 +09:00
a40ee8dda5 refactor(plan): Phase 286C-4 Step 1 - plan_helpers module
Create helper functions to support plan_rewrites() extraction:
- build_local_block_map(): Build block ID mapping for a function
- sync_spans(): Synchronize instruction spans after rewriting

These pure functions will be used by both the current monolithic
merge_and_rewrite() and the new plan_rewrites() function.

Progress: Step 1/4 (helpers) complete

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 03:53:42 +09:00
875c5e02fd refactor(joinir): Phase 286C-2.1 Steps 3-5 - Extract scan logic, fix debug output
Step 3 Complete:
- Extract 94 lines of scan logic into scan_blocks()
- Populate RewritePlan with TailCallRewrite, ReturnConversion
- Read-only analysis phase (no mutations)

Steps 4-5 Partial:
- Document 3-stage pipeline architecture
- Infrastructure ready for future extraction
- Remaining extraction deferred to Phase 286C-2.2

Bug Fix:
- Remove joinir_dev_enabled() from verbose flag in scan_blocks()
- Prevents unintended debug output during tests
- Smoke tests now pass (45/46, 1 known fail unrelated)

Current State:
- scan_blocks(): 94 lines  functional
- plan_rewrites(): stub (future extraction ~400 lines)
- apply_rewrites(): stub (future extraction ~200 lines)
- merge_and_rewrite(): ~1300 lines (target ~150 lines)

Build: cargo build --release 
Tests: 45/46 pass (1 known JoinIR pattern fail)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 03:45:16 +09:00