Clarifies that LoopScopeShape has two complementary construction paths
for different contexts (AST-based vs LoopForm-based).
## Analysis
After investigating, discovered these builders serve **different purposes**:
1. **AST-based** (`patterns/loop_scope_shape_builder.rs`):
- Builds from AST during MIR generation
- Extracts body_locals from ASTNode::Local declarations
- Used in Pattern 1-4 lowerers
2. **LoopForm-based** (`loop_scope_shape/builder.rs`):
- Builds from LoopForm during JoinIR lowering
- Analyzes LoopFormIntake snapshots
- Used in generic_case_a and pattern routing
These are NOT duplicates - they're complementary paths!
## Changes
1. **Cross-Reference Documentation**:
- `patterns/loop_scope_shape_builder.rs`: Added Phase 183-3 section
- `loop_scope_shape/builder.rs`: Added Phase 183-3 section
- Both now reference each other for clarity
2. **LoopScopeShape Struct Documentation**:
- Added "Phase 183-3: Construction Paths" section
- Documents two construction paths and their contexts
- Explains when to use each builder
3. **Clarified Responsibilities**:
- AST-based: For MIR building phase
- LoopForm-based: For JoinIR lowering phase
- Both maintain consistent field initialization
## Benefits
- **Clear separation**: Documented different contexts for each builder
- **Maintainability**: Future developers understand which builder to use
- **No code changes**: Pure documentation improvement
- **Cross-references**: Easy navigation between related modules
## Testing
✅ All loop_scope_shape tests pass (24 tests)
✅ No behavioral changes
✅ Documentation-only refactoring
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Makes CarrierInfo::from_variable_map() the primary initialization method.
Common pattern initializer now delegates to this centralized logic.
## Changes
1. **Primary Method: CarrierInfo::from_variable_map()**:
- Now the single source of truth for CarrierInfo construction
- Used by both MIR and JoinIR contexts
- Documented as primary initialization method (Phase 183-2)
2. **CommonPatternInitializer Refactoring**:
- Converted to thin wrapper around `CarrierInfo::from_variable_map()`
- Delegates carrier collection to primary method
- Only adds pattern-specific exclusion filtering
- Reduced code duplication (~30 lines removed)
3. **Documentation Updates**:
- `carrier_info.rs`: Added Phase 183-2 section explaining primary role
- `common_init.rs`: Documented delegation strategy
- Clear separation of concerns between modules
4. **Removed Duplicate Logic**:
- Eliminated manual carrier collection in `common_init.rs`
- Removed `CarrierVar` import (no longer directly constructed)
- Unified sorting and validation in one place
## Benefits
- **Single source of truth**: CarrierInfo construction logic in one module
- **Consistency**: Same initialization algorithm across MIR/JoinIR
- **Maintainability**: Changes to carrier logic only needed once
- **Testability**: Primary logic tested in carrier_info module
## Testing
✅ All carrier_info tests pass (7 tests)
✅ All pattern tests pass (124 tests)
✅ No behavioral changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Consolidates duplicate pattern detection logic across two routing layers.
## Changes
1. **Unified Detection Documentation**:
- Added Phase 183 comments to `loop_pattern_detection::classify()`
- Documented that this is the single source of truth for pattern classification
- Both routers now reference this centralized function
2. **Router Documentation Updates**:
- `patterns/router.rs`: Added Phase 183 comments explaining structure-based routing
- `loop_pattern_router.rs`: Added unified detection section
- Both routers now explicitly reference shared detection logic
3. **Improved Debug Output**:
- Added `pattern_kind` to debug message in `route_loop_pattern()`
- Helps diagnose pattern matching failures
## Benefits
- **Single source of truth**: Pattern classification logic in one place
- **Consistency**: Both routers use same detection algorithm
- **Maintainability**: Changes to classification rules only needed once
- **Documentation**: Clear references between routers and detection module
## Testing
✅ All loop_pattern_detection tests pass
✅ Pattern 2 tests pass
✅ No behavioral changes, pure documentation/organization refactoring
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Phase 179 Task 1: Modular separation for single responsibility
Changes:
- NEW: carrier_update_emitter.rs (416 lines)
- emit_carrier_update() function + 6 unit tests
- Focused module for UpdateExpr → JoinInst conversion
- REDUCED: loop_with_break_minimal.rs (998→597 lines, -401 lines)
- Removed emit_carrier_update() and carrier_update_tests module
- Now imports from carrier_update_emitter
- UPDATED: mod.rs - added carrier_update_emitter module
Benefits:
- Single responsibility: carrier update emission isolated
- Reusability: can be used by Pattern 3, 4, and future patterns
- Testability: independent unit tests
- Maintainability: 40% size reduction in loop_with_break_minimal.rs
Note: Pre-existing test failure in test_pattern2_accepts_loop_param_only
is unrelated to this refactoring (test expects 1 var but gets 3 due to
literal "10" and "5" being counted as variables).
Task 176-1: Pattern2 limitation investigation
- Identified 10 limitation points where only position carrier was handled
- Added TODO markers for Phase 176-2/3 implementation
- Created phase176-pattern2-limitations.md documentation
Task 176-2: CarrierUpdateLowerer helper implementation
- Implemented emit_carrier_update() helper function
- Supports CounterLike and AccumulationLike UpdateExpr patterns
- Added 6 unit tests (all passing)
- Fail-Fast error handling for carrier/variable not found
Task 176-3: Pattern2 lowerer multi-carrier extension
- Extended header PHI generation for all carriers
- Implemented loop update for all carriers using emit_carrier_update()
- Extended ExitLine/ExitMeta construction for all carriers
- Updated function call/jump args to include all carriers
- 9/10 tests passing (1 pre-existing test issue)
Task 176-4: E2E testing and bug fixes
- Fixed Trim pattern loop_var_name overwrite bug (pattern2_with_break.rs)
- Fixed InstructionRewriter latch_incoming mapping bug
- All E2E tests passing (RC=0): pos + result dual-carrier loops work
- test_jsonparser_parse_string_min2.hako verified
Task 176-5: Documentation updates
- Created phase176-completion-report.md
- Updated phase175-multicarrier-design.md with completion status
- Updated joinir-architecture-overview.md roadmap
- Updated CURRENT_TASK.md with Phase 176 completion + Phase 177 TODO
- Updated loop_pattern_space.md F-axis (multi-carrier support complete)
Technical achievements:
- Pattern2 now handles single/multiple carriers uniformly
- CarrierInfo architecture proven to work end-to-end
- Two critical bugs fixed (loop_var overwrite, latch_incoming mapping)
- No regressions in existing tests
Next: Phase 177 - Apply to JsonParser _parse_string full implementation
Builder pattern for JoinInlineBoundary construction, reduces field manipulation scattering.
# Changes
- NEW: src/mir/join_ir/lowering/inline_boundary_builder.rs (165 lines)
- JoinInlineBoundaryBuilder with 7 fluent methods
- Complete unit test coverage (4 tests)
- MODIFIED: src/mir/join_ir/lowering/mod.rs (+2 lines)
- Export inline_boundary_builder module
- Public re-export of JoinInlineBoundaryBuilder
- MODIFIED: src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs
- Replace direct boundary field manipulation with builder pattern
- 9 lines of field assignments → fluent builder chain
# Benefits
- **Centralized**: All boundary construction logic in builder
- **Readable**: Fluent API shows construction intent clearly
- **Maintainable**: Changes to boundary structure isolated to builder
- **Type Safe**: Builder validates field consistency
# Tests
✅ All builder unit tests pass (4/4)
✅ All pattern module tests pass (30+)
✅ Library build succeeds with no errors
🤖 Generated with Claude Code (https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
## Problem
Pattern 4 (loop with continue) was producing SSA-undef errors due to function_params
key mismatch. function_params uses 'join_func_0'/'join_func_1' format (from join_func_name()),
but code was looking for 'main'/'loop_step'.
## Solution
- Fix mod.rs: Use correct function keys 'join_func_0' and 'join_func_1'
- Add warning logs to detect future key mismatches immediately
- Update pattern4_with_continue.rs: Mark as fully implemented (not stub)
- Remove unused imports: MergeResult, TailCallKind, classify_tail_call, etc.
## Testing
- Pattern 3 (If PHI): sum=9 ✅
- Pattern 4 (Continue): 25 ✅ (1+3+5+7+9)
- No SSA-undef errors
- No new warnings on successful execution
## Debug Improvements
Added pre-flight checks in merge/mod.rs Phase 33-21:
```
[cf_loop/joinir] WARNING: function_params.get('join_func_0') returned None.
Available keys: [...]
```
This will save significant debugging time for future parameter mapping issues.
🤖 Generated with Claude Code
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Wire LoopUpdateSummary box into real code paths:
- Add `update_summary: Option<LoopUpdateSummary>` field to LoopFeatures
- Add `detect_with_updates()` method to CaseALoweringShape
- Uses UpdateKind (CounterLike/AccumulationLike) for classification
- Single CounterLike carrier → StringExamination
- AccumulationLike present → ArrayAccumulation or IterationWithAccumulation
- Update loop_to_join.rs to use detect_with_updates()
- Update deprecated detect() to use detect_with_updates() internally
- Set update_summary: None in AST-based feature extraction
Carrier name heuristics now encapsulated in LoopUpdateSummary box.
No regression: 15/16 loop smoke tests pass (1 failure is pre-existing).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add UpdateKind/LoopUpdateSummary types for loop update pattern analysis.
Currently uses carrier name heuristics internally (same as 170-C-1),
but provides clean interface for future AST/MIR-based analysis.
New types:
- UpdateKind: CounterLike | AccumulationLike | Other
- CarrierUpdateInfo: name + kind pair
- LoopUpdateSummary: collection with helper methods
Helper methods:
- has_single_counter(): for StringExamination detection
- has_accumulation(): for ArrayAccumulation detection
Design doc: docs/development/current/main/phase170-c2-update-summary-design.md
- Describes LoopFeatures.update_summary integration plan
- Migration path to AST/MIR analysis
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add detect_with_carrier_name() to improve CaseALoweringShape detection
accuracy by using carrier variable names as a heuristic.
Since LoopUpdateAnalyzer operates at AST level (not accessible from MIR),
use carrier naming conventions instead:
- Typical index names (i, e, idx, pos, start, end) → StringExamination
- Other names (result, items, defs) → ArrayAccumulation
This reduces Generic fallback cases for single-carrier loops.
Changes:
- case_a_lowering_shape.rs: Add detect_with_carrier_name(), is_typical_index_name()
- loop_to_join.rs: Extract progress_carrier name, call new detection function
Phase 170-C-2 can add MIR-based update pattern analysis for higher accuracy.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace hardcoded function name routing with CaseALoweringShape-based
dispatch in LoopToJoinLowerer::lower_with_scope().
Design: Hybrid approach with backward compatibility
1. Detect shape from LoopScopeShape (structure-based, name-agnostic)
2. If shape is recognized → use corresponding lowerer
3. If shape is Generic/NotCaseA → fallback to name-based whitelist
Shape to lowerer mapping:
- StringExamination → skip_ws lowerer (Main.skip/1, trim patterns)
- ArrayAccumulation → append_defs lowerer
- IterationWithAccumulation → stage1 lowerer
This enables gradual migration: existing name-based code continues to
work, while new patterns can be added purely by structure detection.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Clarify design principle: CaseALoweringShape does NOT look at function names.
Input must be LoopFeatures/LoopPatternKind only (structure-based detection).
Changes:
- Add detect_from_features(LoopFeatures, carrier_count, has_progress_carrier)
- Deprecate detect(LoopScopeShape) with backward-compat wrapper
- Case-A now rejects loops with `has_continue` (only break is allowed)
- Document Phase 170-B future work (loop body AST analysis)
Design Principle:
> "CaseALoweringShape は 関数名を見ない。LoopFeatures/LoopPatternKind だけを入力にする"
This ensures generic routing works for ANY structurally matching loop.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Proper HOST↔JoinIR ValueId separation for condition variables:
- Add ConditionEnv struct (name → JoinIR-local ValueId mapping)
- Add ConditionBinding struct (HOST/JoinIR ValueId pairs)
- Modify condition_to_joinir to use ConditionEnv instead of builder.variable_map
- Update Pattern2 lowerer to build ConditionEnv and ConditionBindings
- Extend JoinInlineBoundary with condition_bindings field
- Update BoundaryInjector to inject Copy instructions for condition variables
This fixes the undefined ValueId errors where HOST ValueIds were being
used directly in JoinIR instructions. Programs now execute (RC: 0),
though loop variable exit values still need Phase 172 work.
Key invariants established:
1. JoinIR uses ONLY JoinIR-local ValueIds
2. HOST↔JoinIR bridging is ONLY through JoinInlineBoundary
3. condition_to_joinir NEVER accesses builder.variable_map
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Phase 193-2**: Add flexible builder methods to CarrierInfo and ExitMeta
## Summary
Enhanced CarrierInfo and ExitMeta with convenient builder methods that support
multiple construction patterns. This reduces boilerplate and makes carrier info
generation more flexible for different lowering scenarios.
## Changes
### CarrierInfo New Methods
- **from_variable_map()**: Automatically extract carriers from variable_map
- Eliminates manual carrier listing for simple cases
- Auto-discovers all non-loop-control variables
- Deterministic sorting for reproducibility
- **with_explicit_carriers()**: Selective carrier extraction
- Choose which variables to treat as carriers
- Useful for Pattern 5+ with complex variable sets
- Validates all carriers exist in variable_map
- **with_carriers()**: Direct CarrierVar construction
- Most explicit method for advanced use cases
- Use when CarrierVar structs already exist
- Auto-sorts for determinism
### CarrierInfo Query Methods
- **carrier_count()**: Get number of carriers
- **is_multi_carrier()**: Check if multi-carrier loop
- **find_carrier()**: Lookup specific carrier by name
### ExitMeta New Methods
- **binding_count()**: Get number of exit bindings
- **is_empty()**: Check if any exit values exist
- **find_binding()**: Lookup exit value by carrier name
- **with_binding()**: Chainable binding addition
## Design Benefits
| Aspect | Benefit |
|--------|---------|
| **Flexibility** | 3 construction patterns for different scenarios |
| **Clarity** | Explicit method names document intent |
| **Ergonomics** | Reduced boilerplate in lowerers |
| **Validation** | Error handling for missing variables |
| **Determinism** | Automatic sorting in all methods |
## Usage Examples
```rust
// Pattern 1: Auto-discover from variable_map
let info = CarrierInfo::from_variable_map("i", &variable_map)?;
// Pattern 2: Selective carriers
let info = CarrierInfo::with_explicit_carriers(
"i", loop_id,
vec!["sum".into(), "count".into()],
&variable_map
)?;
// Pattern 3: Manual construction
let info = CarrierInfo::with_carriers("i", loop_id, carriers);
// Query methods
if info.is_multi_carrier() {
println!("Multi-carrier loop with {} carriers", info.carrier_count());
}
// ExitMeta chaining
let meta = ExitMeta::empty()
.with_binding("sum".into(), ValueId(15))
.with_binding("count".into(), ValueId(16));
```
## Metrics
- CarrierInfo: +3 construction methods, +3 query methods
- ExitMeta: +4 new methods (existing 3 methods unchanged)
- Total lines added: ~150 (including docs)
- Build time: 1m 05s ✅
- Zero regressions ✅
## Next Steps
- Phase 193-3: Pattern Classification Improvement
- Phase 194: Further optimization opportunities
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Change from dual-path (continue Jump + normal Call) to single-path
using Select to merge sum values before tail call.
- Replace conditional Jump with Select instruction
- sum_merged = Select(continue_cond, sum_param, sum_next)
- Single tail call: Call(loop_step, [i_next, sum_merged])
Known issue: PHI generated at JoinIR level but lost in MIR merge.
Need to investigate JoinIR→MIR merge layer.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Updated mod.rs with comprehensive module organization documentation
- Documented before/after line counts and size reductions
- Removed old generic_case_a_old.rs monolith file
- Verified all imports are clean (no unused warnings)
- Verified all visibility is correct (pub(crate) for public API)
Final statistics:
- Before: 1,056 lines in single file
- After: 1,634 lines across 7 focused modules
- Main coordinator: 93 lines (91% reduction)
- Average module size: 233 lines (manageable, focused)
- Largest module: trim.rs at 537 lines (still maintainable)
All success criteria met:
✅ All 7 modules created
✅ cargo build --release succeeds
✅ Zero breaking changes (all APIs compatible)
✅ Module documentation comprehensive
✅ All visibility correct
Ref: Phase 192 modularization effort
- Created src/mir/join_ir/lowering/generic_case_a/ directory
- Moved entry_builder.rs and whitespace_check.rs into new directory
- Created mod.rs with public API exports and comprehensive documentation
- Renamed old generic_case_a.rs to generic_case_a_old.rs temporarily
- Updated parent mod.rs to import from new structure
Ref: Phase 192 modularization effort