10e6a15552
refactor: unify string helpers and pattern2 derived slot
2025-12-28 13:22:02 +09:00
ca91be349d
Refactor JoinIR lowerers and boundary
2025-12-28 03:52:52 +09:00
3e2086cc78
refactor(expr_lowerer): split types and tests
2025-12-28 03:21:43 +09:00
79c2953a1f
refactor(modules): split kernel exports and join_ir lowerers
2025-12-28 02:38:51 +09:00
0269fc2ed4
Reduce build warnings
2025-12-28 01:34:46 +09:00
b104d6af5f
Fix snake case in scan_with_init_minimal
2025-12-28 01:18:58 +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
88ead0df9f
builder: split MirBuilder core methods
2025-12-27 16:45:13 +09:00
ad469ec2ff
ownership: split ast_analyzer into modules
2025-12-27 16:24:51 +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
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
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
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
843d094598
refactor(joinir): Phase 286 P1-P3 - Boundary contract context enrichment
...
- P1: Add alloc_join_param()/alloc_join_local() API to JoinValueSpace
- Prevents future API misuse (thin wrappers with explicit "JoinIR" context)
- Updated docs with footnote-style number references
- P2: Enrich error context with host_fn for better diagnostics
- Added context: &str parameter to verify_boundary_contract_at_creation()
- Error format now shows: [merge_joinir_mir_blocks host=<fn> ...]
- P3: Add join-side info to error context (continuation count + boundary summary)
- Uses boundary.continuation_func_ids.len() for join=
- Adds [conts=X exits=Y conds=Z] suffix with fixed key names
- Enables faster debugging with log-searchable format
Error format: [merge_joinir_mir_blocks host=X join=Y [conts=A exits=B conds=C]]
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-12-25 02:15:40 +09:00
48048425e5
refactor(joinir): Phase 286C - Normalized module box modularization
...
Extract 3 boxes from normalized.rs (1,280 → 563 lines, 56% reduction):
- pattern1_normalizer.rs: Pattern 1 (simple while loops) normalization
- pattern2_normalizer.rs: Pattern 2/3/4 (loops with carriers) normalization
- env_layout_builder.rs: Environment layout construction utilities
Changes:
- Replace large function implementations with re-exports
- Add module declarations for new boxes
- Fix JoinInst import in shape_guard/mod.rs
- Maintain backward compatibility via legacy function wrappers
Acceptance:
- Build passes: cargo build --release
- Quick smoke tests: 17/18 PASS (1 pre-existing failure)
- No regressions in existing functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com >
2025-12-25 00:39:08 +09:00
b0eeb14c54
refactor(phase284): P1 SSOT Consolidation - Block Remapper & Return Emitter
...
## Summary
Refactored Phase 284 P1 codebase to consolidate scattered logic into SSOT
(Single Source of Truth) modules, improving maintainability and enabling
Pattern4/5 code reuse.
## New Modules
### 1. Block Remapper SSOT
**File**: `src/mir/builder/control_flow/joinir/merge/block_remapper.rs` (152 lines)
- **Purpose**: Consolidate block ID remapping logic (Phase 284 P1 fix)
- **Function**: `remap_block_id(block_id, local_block_map, skipped_entry_redirects)`
- **Rule**: local_block_map priority > skipped_entry_redirects (prevents ID collision)
- **Tests**: 4 unit tests (priority cascade, collision handling, etc.)
### 2. Return Jump Emitter
**File**: `src/mir/join_ir/lowering/return_jump_emitter.rs` (354 lines)
- **Purpose**: Reusable return handling helper for Pattern4/5
- **Function**: `emit_return_conditional_jump(loop_step_func, return_info, k_return_id, ...)`
- **Scope**: P1 - unconditional return + conditional (loop_var == N) only
- **Tests**: 3 unit tests (unconditional, no return, conditional)
## Modified Files
**merge/instruction_rewriter.rs** (-15 lines):
- Replaced inline block remapping with `remap_block_id()` call
- Cleaner Branch remap logic
**merge/rewriter/terminator.rs** (-43 lines):
- Delegates remap_jump/remap_branch to block_remapper SSOT
- Simplified duplicate logic
**lowering/loop_with_continue_minimal.rs** (-108 lines):
- Replaced ~100 line return handling with `emit_return_conditional_jump()` call
- Extracted helper functions to return_jump_emitter.rs
- Line reduction: 57% decrease in function complexity
**merge/mod.rs, lowering/mod.rs**:
- Added new module exports (block_remapper, return_jump_emitter)
**phase-284/README.md**:
- Updated completion status (P1 Complete + Refactored)
- Added SSOT consolidation notes
- Documented module architecture
## Code Quality Improvements
| Metric | Before | After | Change |
|--------|--------|-------|--------|
| Duplicate block remap logic | 2 places | SSOT | -15 lines |
| Return handling code | inline (100L) | helper call | -99 lines |
| Testability | Limited | Unit tests (7) | +7 tests |
| Module cohesion | Low (scattered) | High (consolidated) | Better |
## Testing
✅ Build: Success (cargo build --release)
✅ Smoke tests: All pass (46 PASS, 1 pre-existing FAIL)
✅ Regression: Zero
✅ Unit tests: 7 new tests added
## Future Benefits
1. **Pattern5 Reuse**: Direct use of `emit_return_conditional_jump()` helper
2. **Phase 285 (P2)**: Nested if/loop returns via same infrastructure
3. **Maintainability**: SSOT reduces debugging surface area
4. **Clarity**: Each module has single responsibility
## Architectural Notes
**Block Remapper SSOT Rule**:
```
remap_block_id(id, local_block_map, skipped_entry_redirects):
1. Check local_block_map (function-local priority)
2. Fall back to skipped_entry_redirects (global redirects)
3. Return original if not found
```
Prevents function-local block ID collisions with global remap entries.
**Return Emitter Pattern**:
```
emit_return_conditional_jump(func, return_info, k_return_id, alloc_value):
- Pattern1-5: All use same infrastructure
- P1 scope: top-level return only (nested if/loop → P2)
- Returns: JoinInst::Jump(cont=k_return, cond=Some(return_cond))
```
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2025-12-23 14:37:01 +09:00
661bbe1ab7
feat(phase284): P1 Complete - Return in Loop with Block Remap Fix
...
## Summary
Completed Phase 284 P1: Enable return statements in Pattern4/5 loops via
JoinInst::Ret infrastructure (100% pre-existing, no new infrastructure needed).
**Critical Bug Fix**: Block ID remap priority
- Fixed: local_block_map must take precedence over skipped_entry_redirects
- Root cause: Function-local block IDs can collide with global remap entries
(example: loop_step:bb4 vs k_exit:bb4 after merge allocation)
- Impact: Conditional Jump else branches were incorrectly redirected to exit
- Solution: Check local_block_map FIRST, then skipped_entry_redirects
## Implementation
### New Files
- `src/mir/join_ir/lowering/return_collector.rs` - Return detection SSOT (top-level only, P1 scope)
- `apps/tests/phase284_p1_return_in_loop_min.hako` - Test fixture (exit code 7)
- Smoke test scripts (VM/LLVM)
### Modified Files
- `loop_with_continue_minimal.rs`: Return condition check + Jump generation
- `pattern4_with_continue.rs`: K_RETURN registration in continuation_funcs
- `canonical_names.rs`: K_RETURN constant
- `instruction_rewriter.rs`: Fixed Branch remap priority (P1 fix)
- `terminator.rs`: Fixed Jump/Branch remap priority (P1 fix)
- `conversion_pipeline.rs`: Return normalization support
## Testing
✅ VM: exit=7 PASS
✅ LLVM: exit=7 PASS
✅ Baseline: 46 PASS, 1 FAIL (pre-existing emit issue)
✅ Zero regression
## Design Notes
- JoinInst::Ret infrastructure was 100% complete before P1
- Bridge automatically converts JoinInst::Ret → MIR Return terminator
- Pattern4/5 now properly merge k_return as non-skippable continuation
- Correct semantics: true condition → return, false → continue loop
## Next Phase (P2+)
- Refactor: Block remap SSOT (block_remapper.rs)
- Refactor: Return jump emitter extraction
- Scope: Nested if/loop returns, multiple returns
- Design: Standardize early exit pattern (return/break/continue as Jump with cond)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2025-12-23 14:21:27 +09:00
bfbc9b26bf
fix(joinir): Phase 283 P0 - Pattern3 Undefined ValueId Bug Fix
...
- Fix: extract_if_condition() moved after local_cond_env construction
(loop_with_if_phi_if_sum.rs:175)
- Root cause: condition extraction before i_param/sum_param creation
- Result: i % 2 referenced caller's ConditionEnv with unmapped ValueId
- Fail-Fast: Add condition_bindings validation in merge (mod.rs)
- Fixture: Update loop_if_phi.hako for C2 compatibility (sum.toString())
- Verified: VM execution outputs sum=9 ✅
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-23 08:14:27 +09:00
1b7fd7a0ff
refactor(plan): Phase 273 P3+ - Legacy code removal
...
Phase 273 P3+ 完成: レガシーコード削除 + 未使用 import 整理
Removed Legacy Items:
1. emit_scan_with_init_edgecfg() - Pattern6 固有の emission 関数
- File deleted: src/mir/builder/emission/loop_scan_with_init.rs (~144 lines)
- Replaced by: generalized Frag API (Phase 273 P2)
2. CoreCarrierInfo struct - Legacy carrier representation
- Removed from: src/mir/builder/control_flow/plan/mod.rs (~15 lines)
- Replaced by: CorePhiInfo (generalized PHI representation)
3. verify_carrier() function - CoreCarrierInfo validator
- Removed from: src/mir/builder/control_flow/plan/verifier.rs (~15 lines)
- Replaced by: generalized PHI verification (V7-V9)
Code Cleanup:
- cargo fix applied: unused imports removed (~30 files)
- Verifier invariants updated: V1→V2-V9 (carrier→PHI model)
- Module declaration cleanup in emission/mod.rs
Impact:
- Total lines removed: ~174 lines (net reduction)
- Pattern-agnostic architecture strengthened
- All legacy Pattern6 references eliminated
Tests:
- ✅ VM tests PASS (phase254/256/258)
- ✅ LLVM tests PASS (phase256/258)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2025-12-23 00:11:20 +09:00
1fe5be347d
refactor(mir): phase260 p0.1 strangler hardening + smoke fixtures
2025-12-21 05:47:37 +09:00
4dfe3349bf
refactor(mir): phase260 p0 edge-args plumbing (strangler) + ssot api + docs
2025-12-21 04:34:22 +09:00
a767f0f3a9
feat(joinir): Phase 259 P0 - Pattern8 BoolPredicateScan + Copy binding fix
...
Pattern8 (Boolean Predicate Scan) implementation for is_integer/1:
- New pattern detection for `loop + if not predicate() { return false }`
- JoinIR lowerer with main/loop_step/k_exit structure
- Me receiver passed as param (by-name 禁止)
Key fixes:
1. expr_result = Some(join_exit_value) (Pattern7 style)
2. Tail-call: dst: None (no extra Ret instruction)
3. instruction_rewriter: Add `&& is_loop_header_with_phi` check
- Pattern8 has no carriers → no PHIs → MUST generate Copy bindings
- Without this, ValueId(103/104/105) were undefined
Status: Copy instructions now generated correctly, but exit block
creation issue remains (next step: Step A-C in指示書).
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2025-12-21 02:40:07 +09:00
23531bf643
feat(joinir): Phase 258 P0 dynamic needle window scan
2025-12-21 00:29:50 +09:00
9ba89bada2
feat(pattern6): support reverse scan for last_index_of
...
Extend Pattern6 (ScanWithInit) to handle both forward and reverse scans:
- Forward: i=0, loop(i < len), i=i+1 (existing)
- Reverse: i=len-1, loop(i >= 0), i=i-1 (NEW)
Implementation:
- Added ScanDirection enum (Forward/Reverse)
- Updated extract_scan_with_init_parts() to detect both patterns
- Created lower_scan_with_init_reverse() lowerer
- Pattern6 now selects appropriate lowerer based on scan direction
Files modified:
- src/mir/builder/control_flow/joinir/patterns/pattern6_scan_with_init.rs
- src/mir/join_ir/lowering/scan_with_init_reverse.rs (new)
- src/mir/join_ir/lowering/mod.rs
Known issue (pre-existing):
- PHI predecessor mismatch bug exists in Pattern6 (both forward and reverse)
- This bug existed BEFORE Phase 257 P0 implementation
- Out of scope for Phase 257 P0 - will be addressed separately
Phase 257 P0
2025-12-20 20:28:41 +09:00
edc7355937
refactor(joinir): unify boundary join_inputs SSOT (pattern4/6/7)
...
Apply Phase 256.8 SSOT fix to Pattern4/6/7:
- Use join_module.entry.params.clone() instead of hardcoded ValueIds
- Add fail-fast validation for params count mismatch
- Remove ValueId(0), ValueId(PARAM_MIN + k) patterns
- Clean up unused PARAM_MIN imports
This prevents entry_param_mismatch errors structurally and maintains
consistency with Pattern2/3.
Changes:
- pattern4_with_continue.rs: Lines 442-476 (SSOT extraction + validation)
- pattern6_scan_with_init.rs: Lines 447-471 (SSOT extraction + validation)
- pattern7_split_scan.rs: Lines 495-526 (SSOT extraction + validation)
All patterns now use the same SSOT principle:
1. Extract entry function (priority: join_module.entry → fallback "main")
2. Use params as SSOT: join_inputs = entry_func.params.clone()
3. Build host_inputs in expected order (pattern-specific)
4. Fail-fast validation: join_inputs.len() == host_inputs.len()
Verification:
- cargo build --release: ✅ PASS (no PARAM_MIN warnings)
- Quick profile: ✅ First FAIL still json_lint_vm (baseline maintained)
- Pattern6 smoke: ✅ PASS (index_of test)
- Pattern7 smoke: Pre-existing phi pred mismatch (not introduced by SSOT)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-20 20:05:11 +09:00
4439d64da3
refactor(joinir): make jump_args layout explicit (Phase 256)
2025-12-20 13:04:24 +09:00
cb8a6984d4
refactor: modularize shape_guard.rs and separate canonicalizer tests
...
shape_guard.rs (1401 lines → 6 files):
- pattern2.rs: Break-loop patterns (132 lines)
- pattern3.rs: If-sum patterns (67 lines)
- pattern4.rs: Continue patterns (152 lines)
- selfhost.rs: Selfhost-specific detectors (245 lines)
- utils.rs: Shared helpers (33 lines)
- mod.rs: API coordination & tests (776 lines)
canonicalizer.rs (1863 lines → 433 lines):
- Separated 1430 lines of tests to canonicalizer_tests.rs
Benefits:
- Improved maintainability (smaller, focused files)
- Clear separation of concerns (pattern families)
- Preserved API compatibility (re-exports)
- No new warnings
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2025-12-20 07:29:26 +09:00
077657b7a1
feat(joinir): Phase 256 P1.5-P1.7 contracts and naming SSOT
2025-12-20 06:38:21 +09:00
64f679354a
fix(joinir): Phase 256 P1 - Carrier PHI wiring and parameter mapping (in progress)
...
**Status**: Core carrier PHI issue partially resolved, debugging loop body
**Progress**:
✅ Task 1: split_scan_minimal.rs Carriers-First ordering (6 locations)
✅ Task 2: pattern7_split_scan.rs boundary configuration (host/join inputs, exit_bindings, expr_result)
✅ Result now flows from k_exit to post-loop code (RC issue resolved)
⚠️ Loop body instruction execution needs review
**Key Fixes**:
1. Fixed host_inputs/join_inputs to match main() params Carriers-First order
2. Added result to exit_bindings (CarrierRole::LoopState)
3. Added result back to loop_invariants for variable initialization
4. Added expr_result=join_exit_value_result for loop expression return
5. Fixed jump args to k_exit to include all 4 params [i, start, result, s]
**Current Issue**:
- Loop body type errors resolved (String vs Integer fixed)
- New issue: Loop body computations (sep_len) undefined in certain blocks
- Likely cause: JoinIR→MIR conversion of local variables needs review
**Next Steps**:
- Review JoinValueSpace allocation and ValueId mapping in conversion
- Verify loop_step instruction ordering and block structure
- May need to refactor bound computation or revisit split algorithm
🤖 Generated with Claude Code
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2025-12-20 01:24:04 +09:00
575a5d750f
refactor(joinir): Phase 255 P2 - loop_invariants + var() unification + Phase 256 prep
...
## Task A: Loop Invariants Architecture (Option A - Boundary Extension)
Introduced explicit loop_invariants concept for variables that are:
- Used in loop body but never modified (e.g., substring needle in index_of)
- Need header PHI (all iterations use same value)
- Do NOT need exit PHI (not a LoopState)
Implementation:
- Added `loop_invariants: Vec<(String, ValueId)>` field to JoinInlineBoundary
- Added `with_loop_invariants()` method to JoinInlineBoundaryBuilder
- Modified Pattern 6 to use loop_invariants instead of ConditionOnly misuse
* s (haystack) and ch (needle) now properly classified
* exit_bindings simplified to only LoopState carriers
- Extended LoopHeaderPhiBuilder to generate invariant PHIs
* Entry PHI: from host
* Latch PHI: self-reference (same value every iteration)
- Updated instruction_rewriter to handle invariant latch incoming
Files Modified:
- src/mir/join_ir/lowering/inline_boundary.rs (structure + builder)
- src/mir/join_ir/lowering/inline_boundary_builder.rs (builder method)
- src/mir/builder/control_flow/joinir/patterns/pattern6_scan_with_init.rs
- src/mir/builder/control_flow/joinir/merge/loop_header_phi_builder.rs
- src/mir/builder/control_flow/joinir/merge/mod.rs
- src/mir/builder/control_flow/joinir/merge/instruction_rewriter.rs
## Task B: Code Quality - var() Helper Unification
Created common module to eliminate var() duplication:
- New module: src/mir/builder/control_flow/joinir/patterns/common/
- Centralized var() helper in ast_helpers.rs
- Updated Pattern 6 and Pattern 2 to use common var()
- Test code (5 occurrences) deferred to Phase 256+ per 80/20 rule
Result: Eliminated 2 duplicate var() functions, 5 test occurrences remain
Files Created:
- src/mir/builder/control_flow/joinir/patterns/common/ast_helpers.rs
- src/mir/builder/control_flow/joinir/patterns/common/mod.rs
Files Modified:
- src/mir/builder/control_flow/joinir/patterns/mod.rs
- src/mir/builder/control_flow/joinir/patterns/pattern6_scan_with_init.rs
- src/mir/builder/control_flow/joinir/patterns/policies/balanced_depth_scan_policy.rs
## Task C: Documentation - PostLoopEarlyReturnPlan Usage Examples
Enhanced post_loop_early_return_plan.rs with:
- Architecture explanation (exit PHI usage prevents DCE)
- Pattern 2 example (Less: balanced_depth_scan)
- Pattern 6 example (NotEqual: index_of)
- Builder defer decision: when 4+ patterns emerge, add builder
Files Modified:
- src/mir/builder/control_flow/joinir/patterns/policies/post_loop_early_return_plan.rs
## Task D: Phase 256 Preparation
Analyzed next failure from smoke tests:
- `StringUtils.split/2` with variable-step loop
- Not constant step (i += len or similar)
- Three implementation options identified
Created Phase 256 README with:
- Minimal reproduction code
- Root cause analysis
- Implementation options with trade-offs
- Clear next steps
Files Created:
- docs/development/current/main/phases/phase-256/README.md
## Verification Results
✅ All tests passing:
- pattern254_p0_index_of_vm.sh: PASS
- No regression in Pattern 1-5
- Smoke test progresses past json_lint_vm to next failure
✅ Architecture achievements:
- Semantic clarity: loop_invariants vs exit_bindings properly separated
- ConditionOnly misuse eliminated
- PHI generation correct for all carrier types
- Code quality: var() duplication reduced
- Next phase clearly defined
## Summary
Phase 255 P2 achieves root-cause fix for multi-param loop support:
- Boundary concept expanded (loop_invariants field)
- Pattern 6 architecture corrected (no ConditionOnly misuse)
- Code quality improved (var() centralized)
- Next pattern (variable-step) is now the challenge
✨ Box-first principles maintained: clean separation, explicit roles, minimal coupling
🧠 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2025-12-19 23:48:49 +09:00
2d9c6ea3c6
feat(joinir): Phase 254-255 - Pattern 6 (ScanWithInit) + exit PHI DCE fix
...
## Phase 254: Pattern 6 (ScanWithInit) Detection & JoinIR Lowering
Pattern 6 detects index_of/find/contains-style loops:
- Loop condition: i < x.length()
- Loop body: if with method call condition + early return
- Step: i = i + 1
- Post-loop: return not-found value (-1)
Key features:
- Minimal lowering: main/loop_step/k_exit functions
- substring hoisted to init-time BoxCall
- Two k_exit jumps (found: i, not found: -1)
- Tests: phase254_p0_index_of_min.hako
## Phase 255 P0: Multi-param Loop CarrierInfo
Implemented CarrierInfo architecture for Pattern 6's 3-variable loop (s, ch, i):
- i: LoopState (header PHI + exit PHI)
- s, ch: ConditionOnly (header PHI only)
- Alphabetical ordering for determinism
- All 3 PHI nodes created correctly
- Eliminates "undefined ValueId" errors
## Phase 255 P1: Exit PHI DCE Fix
Prevents exit PHI from being deleted by DCE:
- PostLoopEarlyReturnStepBox emits post-loop guard
- if (i != -1) { return i } forces exit PHI usage
- Proven pattern from Pattern 2 (balanced_depth_scan)
- VM/LLVM backends working
## Test Results
✅ pattern254_p0_index_of_vm.sh: PASS (exit code 1)
✅ pattern254_p0_index_of_llvm_exe.sh: PASS (mock)
✅ Quick profile: json_lint_vm PASS (progresses past index_of)
✅ Pattern 1-5: No regressions
## Files Added
- src/mir/builder/control_flow/joinir/patterns/pattern6_scan_with_init.rs
- src/mir/join_ir/lowering/scan_with_init_minimal.rs
- apps/tests/phase254_p0_index_of_min.hako
- docs/development/current/main/phases/phase-254/README.md
- docs/development/current/main/phases/phase-255/README.md
🧠 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2025-12-19 23:32:25 +09:00
0dd9ec9704
feat(normalization): Phase 252 P1 - DebugOutputBox unification + this.methodcall tests
...
**P1-1: Local Refactor**:
- loop_with_if_phi_if_sum.rs: Replace 8 eprintln! with DebugOutputBox
- Default output: 0 lines (clean)
- With NYASH_JOINIR_DEBUG=1: Rich trace output
**P1-2: Unit Tests** (3/3 PASS):
- test_this_methodcall_in_condition: BoxCall generation
- test_this_methodcall_requires_context: Static box requirement
- test_this_methodcall_disallowed_method: Method whitelist enforcement
**P1-3: v2 Smoke Fixture**:
- phase252_p0_this_methodcall_break_cond_min.hako
- StringUtils.count_leading_digits with this.is_digit break condition
- VM + LLVM integration test scripts
**P1-4: Test Fixes**:
- condition_lowering_box.rs: current_static_box_name: None
- loop_with_break_minimal/tests.rs: current_static_box_name: None
🧪 Tests:
- cargo test condition_lowerer: 3 new tests PASS
- cargo check --lib: PASS (0 errors)
📊 Quick Profile Status:
- json_pp_vm: ✅ PASS
- json_lint_vm: ❌ FAIL (deferred to Phase 253)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-19 20:30:58 +09:00
6a3b6deb20
feat(anf): Phase 145 P0/P1/P2 - ANF (A-Normal Form) transformation
...
Implement ANF transformation for impure expressions to fix evaluation order:
Phase 145 P0 (Skeleton):
- Add anf/ module with contract/plan/execute 3-layer separation
- AnfDiagnosticTag, AnfOutOfScopeReason, AnfPlan enums
- Stub execute_box (always returns Ok(None))
- 11 unit tests pass
Phase 145 P1 (Minimal success):
- String.length() whitelist implementation
- BinaryOp + MethodCall pattern: x + s.length() → t = s.length(); result = x + t
- Exit code 12 verification (VM + LLVM EXE)
- 17 unit tests pass
Phase 145 P2 (Generalization):
- Recursive ANF for compound expressions
- Left-to-right, depth-first evaluation order
- Patterns: x + s.length() + z, s1.length() + s2.length()
- ANF strict mode (HAKO_ANF_STRICT=1)
- Diagnostic tags (joinir/anf/*)
- 21 unit tests pass, 0 regression
Also includes Phase 143 P2 (else symmetry) completion.
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-19 16:19:49 +09:00
845ae70cb7
chore: Remove unused imports in normalized_shadow modules
...
Cleaned up unused imports after Phase 143 execution fix (5e662eaaf ).
**Priority files (Phase 143)**:
- if_as_last_join_k.rs: removed ValueId, BTreeMap
- loop_true_break_once.rs: added #[cfg(test)] for test-only imports
- post_if_post_k.rs: removed ValueId, BTreeMap
- normalized_helpers.rs: added #[cfg(test)] for Span
**Additional cleanup**:
- contract_checks.rs: removed BasicBlockId
- joinir/mod.rs: removed Info struct re-exports (functions kept)
- patterns/mod.rs: removed Info struct re-exports (functions kept)
- ast_feature_extractor.rs: removed EscapeSkipPatternInfo
- plan_box.rs: added #[cfg(test)] for PlanKind
**Verification**:
- 0 unused import warnings (was 20+)
- All 69 normalized_shadow tests pass
- Clean build with --release
Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-19 08:36:45 +09:00
d5a36cf818
refactor(joinir): Phase 132-R0 - Continuation SSOT + legacy isolation
...
**Task 1: Continuation SSOT 一本化** ✅
- Add JoinInlineBoundary::default_continuations()
- Replace all BTreeSet::from([JoinFuncId::new(2)]) hardcoding (7 locations)
- Single source of truth for continuation function IDs
**Task 2: merge 契約 docs SSOT 化** ✅
- New: src/mir/builder/control_flow/joinir/merge/README.md
- Document continuation contracts, skip conditions, forbidden behaviors
- Prohibit by-name/by-id classification
**Task 3: テスト配置正規化** ✅
- New: src/mir/builder/control_flow/joinir/merge/tests/continuation_contract.rs
- Move tests from instruction_rewriter.rs to dedicated test file
- Add 4 test cases (Case A-D)
**Task 4: legacy 導線隔離** ✅
- New: src/mir/builder/control_flow/joinir/legacy/
- Move routing_legacy_binding.rs → legacy/routing_legacy_binding.rs
- Add legacy/README.md with removal conditions
- No cfg(feature="legacy") (docs-only isolation for now)
**Task 5: ノイズ除去** ✅
- Remove unused imports (ConstValue, MirInstruction)
- Clean warnings in touched files
Changes:
- src/mir/join_ir/lowering/inline_boundary.rs: +default_continuations()
- src/mir/builder/control_flow/joinir/merge/README.md: +140 lines
- src/mir/builder/control_flow/joinir/merge/tests/: +180 lines
- src/mir/builder/control_flow/joinir/legacy/: +3 files
Test results:
- cargo test --lib: 1176 PASS
- All Phase 131/132/97 smokes: PASS
Benefits:
- Continuation definition centralized (SSOT)
- Merge contracts documented and tested
- Legacy code path clearly isolated
- Code quality improved (warnings reduced)
Related: Phase 132 infrastructure improvements
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-18 21:52:21 +09:00
02c4c313e5
feat(control_tree): Phase 131 P1.5-P2 DirectValue exit reconnection
...
Implement DirectValue mode for Normalized shadow exit handling:
**P1.5 Changes**:
- Add ExitReconnectMode::DirectValue (skip exit PHI generation)
- Carry remapped_exit_values through merge result
- Update host variable_map directly with exit values
- Fix loop(true) { x = 1; break }; return x to return 1 correctly
**P2 Changes**:
- Normalize k_exit continuation entry/exit edges
- Rewrite TailCall(k_exit) → Jump(exit_block) for proper merge
- Add verify_all_terminator_targets_exist contract check
- Extend ExitLineReconnector to handle DirectValue mode
**Infrastructure**:
- tools/build_llvm.sh: Force TMPDIR under target/ (EXDEV mitigation)
- llvm_exe_runner.sh: Add exit_code verification support
- Phase 131 smokes: Update for dev-only + exit code validation
**Contracts**:
- PHI-free: Normalized path uses continuations only
- Exit values reconnect via remapped ValueIds
- Existing patterns unaffected (既定挙動不変)
Related: Phase 131 loop(true) break-once Normalized support
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-18 17:48:05 +09:00
432fc96082
refactor(joinir): extract IfSumExitMetaBuilderBox for Fail-Fast carrier binding
...
Phase 118 refactoring: Box modularization for ExitMeta generation.
# Changes
- Created `exit_meta_builder.rs` with IfSumExitMetaBuilderBox
- Extracted ExitMeta generation logic from loop_with_if_phi_if_sum.rs
- Implemented Fail-Fast contract (carrier name validation)
- Added comprehensive unit tests (5 tests, all passing)
# Design
- **Responsibility**: Builds ExitMeta from carrier name + ValueId
- **Fail-Fast**: Validates carrier names immediately
- **Reusability**: Can be used by other patterns (Pattern 4, etc.)
# Test Results
- Unit tests: 5/5 PASS
- Phase 118 smoke tests: PASS (VM + LLVM)
- Phase 117 regression: PASS
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2025-12-18 03:56:10 +09:00
1080dee58f
fix(joinir): Phase 118 Pattern3 exit carrier PHI SSOT
2025-12-18 03:43:00 +09:00
2ab460f0a8
feat(joinir): error_tags freeze_with_hint
...
- Add freeze_with_hint(tag, msg, hint) API
- Format: "[joinir/<tag>] <msg> Hint: <hint>"
- Panic on empty hint (must provide actionable suggestion)
- Keep existing freeze() for backward compatibility
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com >
2025-12-17 23:45:40 +09:00
aa29dc8085
feat(joinir): emit balanced depth-scan derived vars
2025-12-17 22:32:50 +09:00
f1a570fd45
feat(joinir): Phase 107 balanced depth-scan policy (analysis-only)
2025-12-17 22:25:34 +09:00
ae2a1d4339
refactor(joinir): boxify Pattern2 routing and schedule facts
2025-12-17 21:24:46 +09:00
27fd9720d0
feat(joinir): string accumulator emitter (JoinIR)
...
- Add StringAccumulatorEmitter in join_ir/lowering/common/
- Emit string concat as BinOp(Add) for polymorphic VM/LLVM handling
- Ensure VM/LLVM same semantics
- Fail-Fast: RHS must be Variable (not Literal/MethodCall)
- Pattern2 wiring: string carrier昇格 + type refinement + validation
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-17 16:33:18 +09:00
468977e9b3
feat(joinir): allow accumulator as LoopState carrier (Pattern2 + ScopeManager delegation)
...
- Integrate MutableAccumulatorAnalyzer into pattern2_with_break.rs
- Delegate read-only check to ScopeManager (SSOT search order)
- Promote valid accumulators to mutable LoopState carriers
- Accumulator updates handled by existing carrier mechanism
- Fail-Fast: mutable RHS (not supported yet)
- Allow LoopBodyLocal RHS (validated later in lowering)
- loop_body_local_init.rs: Align receiver search order with SSOT (ConditionEnv first)
- Error prefix: [joinir/mutable-acc]
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-17 06:10:50 +09:00
0661e92225
feat(joinir): phase 100 P1 - pinned local analyzer and wiring into CapturedEnv
...
- Implement PinnedLocalAnalyzer box to identify pinned loop-outer locals
* Pure AST analysis (no MIR dependencies)
* Detects locals: defined before loop, referenced in loop, NOT assigned in loop
* 5 unit tests covering all edge cases (no assignment, assigned, empty body, etc.)
- Integrate PinnedLocalAnalyzer into pattern2_with_break.rs
* Call analyzer with loop body AST and candidate locals from variable_map
* Wire pinned locals into CapturedEnv with CapturedKind::Pinned
* Fail-Fast on host_id lookup failure or analyzer errors
- Update loop_body_local_init.rs resolver to search CapturedEnv
* New search order: LoopBodyLocalEnv → ConditionEnv → CapturedEnv
* Access via cond_env.captured (already integrated in ConditionEnv)
* Updated error message to show full search order
- All existing tests pass (1101 passed, 1 unrelated failure)
- Smoke tests verified: phase96_json_loader_next_non_ws_vm, phase94_p5b_escape_e2e
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2025-12-17 05:32:35 +09:00
0c7ea21cac
refactor(joinir): phase 100 P1 - add CapturedKind (Explicit/Pinned) to CapturedVar
...
- Add CapturedKind enum to types.rs (Explicit for traditional, Pinned for Phase 100)
- Update CapturedVar struct to include kind field
- Add insert() and insert_pinned() helper methods to CapturedEnv
- Update analyzers.rs to specify kind field in all CapturedVar instantiations
- Export CapturedKind from function_scope_capture module
- Update scope_manager.rs test to include kind field
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com >
2025-12-17 05:32:17 +09:00
7ab459503b
feat(joinir): Phase 94 - P5b escape full E2E (derived ch + +1/+2)
2025-12-17 00:59:33 +09:00
c213ecc3c0
refactor(mir): Phase 93 リファクタリング - 箱化モジュール化
...
## 概要
Phase 93 P0実装後のコード整理。スケジュール決定ロジックとbreak semanticsを
明確化し、デバッグログを統一。
## 変更内容
### 1. スケジュール決定ロジックの関数化 (step_schedule.rs)
- `ScheduleDecision`構造体追加(判定結果+理由+デバッグコンテキスト)
- `decide_pattern2_schedule()` - スケジュール決定のSSOT
- `build_pattern2_schedule_from_decision()` - 新しい決定ベースAPI
- 判定理由が4種類で明確化(ConditionOnly → body-local → loop-local → default)
- 後方互換性維持(`Pattern2ScheduleContext`はwrapperに)
### 2. ConditionOnlyRecipe強化 (condition_only_emitter.rs)
- `BreakSemantics` enum追加(WhenMatch vs WhenNotMatch)
- `generate_break_condition()` - semanticsに基づくAST生成
- `from_trim_helper_condition_only()` - factory method追加
- break semanticsがrecipeに明示的に含まれる
### 3. trim_loop_lowering.rs簡素化
- `generate_condition_only_break_condition()`削除(DRY原則)
- `recipe.generate_break_condition()`で統一
- break条件生成ロジックが1箇所に集約
### 4. デバッグログ統一
- `[phase93/schedule]` - スケジュール決定
- `[phase93/condition-only]` - ConditionOnlyレシピ作成
- `[phase93/break-cond]` - break条件生成
- 既存の`joinir_dev_enabled()`使用(新規env var不要)
## テスト結果
- step_schedule: 10 tests PASS
- condition_only_emitter: 4 tests PASS
- 後方互換性維持
## 統計
- 3ファイル変更
- +249行 / -57行 = +192 net
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com >
2025-12-16 23:43:03 +09:00