Modified extract_loop_condition() to use ConditionEnv for variable lookup:
- Now returns ValueId instead of i64 for loop limit
- Uses lower_value_expression() for both literals and variables
- Integrated ConditionEnvBuilder in Pattern 3 if-sum path
This enables realistic loop patterns like `loop(i < len)` in if-sum.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduced ConditionPatternBox to detect if condition complexity:
- Simple comparisons (var CmpOp literal): use AST-based if-sum lowerer
- Complex conditions (BinaryOp, etc.): fallback to legacy P3 lowerer
This fixes loop_if_phi.hako which was broken by Phase 219's
is_if_sum_pattern() changes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add expr_result handling in merge_joinir_mir_blocks
- When expr_result matches a carrier, return carrier PHI dst
- Enables expr-position loops to properly return accumulator values
Note: Phase 219 regression (loop_if_phi.hako) to be fixed in next commit
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace sequential value_counter (0u32) with JoinValueSpace allocator
in Pattern 3 (If-PHI) lowering for unified ValueId management.
Changes:
- loop_with_if_phi_minimal.rs: Replace value_counter with join_value_space.alloc_local()
- pattern3_with_if_phi.rs: Create JoinValueSpace and pass to lowerer
- loop_patterns/with_if_phi.rs: Update legacy wrapper to use JoinValueSpace
Benefits:
- Consistent with Pattern 2 implementation (Phase 201)
- Prevents ValueId collision in Local region (1000+)
- Clean separation: Param region (100-999) vs Local region (1000+)
Test status:
- All unit tests pass (5/5)
- E2E tests pass: loop_if_phi.hako, loop_if_phi_continue.hako
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Migrated Pattern 1 (Simple While) to use JoinValueSpace for unified
ValueId allocation, following the same pattern as Pattern 2 (Phase 201).
Changes:
- simple_while_minimal.rs: Added join_value_space parameter, replaced
value_counter with join_value_space.alloc_local()
- pattern1_minimal.rs: Create JoinValueSpace before calling lowerer
- loop_view_builder.rs: Create JoinValueSpace in try_pattern1()
Pattern 1 uses Local region (1000+) only, since it doesn't need
ConditionEnv (no Param region allocation required).
Tested:
- cargo build --release --lib: Success (0 errors, 4 warnings)
- cargo test --release --lib pattern: 119 passed
- E2E test apps/tests/loop_min_while.hako: Outputs "0 1 2" correctly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Key changes to prevent ValueId collision between frontend and lowerer:
1. loop_step params now use ConditionEnv ValueIds (Param region: 100+)
- i_param = env.get(loop_var_name) - ensures condition lowering works
- carrier_param_ids from CarrierInfo.join_id
2. main() params and intermediate values use alloc_local() (Local region: 1000+)
- No collision with frontend's param allocations
3. CarrierInfo.join_id is now properly set in frontend
- carrier.join_id = Some(carrier_join_id) during allocation
This fixes the "use of undefined value" error where frontend allocated
ValueId(100+) but lowerer used ValueId(0+), causing remapper mismatch.
Test results:
- All 821 library tests pass
- E2E: phase200d_capture_minimal.hako outputs 30 ✓
- Pattern 4: loop_continue_pattern4.hako outputs 25 ✓
- Multi-carrier: loop_continue_multi_carrier.hako outputs 100,10 ✓
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 201 introduces JoinValueSpace to prevent ValueId collisions between
Pattern 2 frontend (alloc_join_value) and JoinIR lowering (alloc_value).
ValueId Space Layout:
- PHI Reserved (0-99): For LoopHeader PHI dst
- Param Region (100-999): For ConditionEnv, CarrierInfo, CapturedEnv
- Local Region (1000+): For Const, BinOp, etc. in pattern lowerers
Changes:
- Add join_value_space.rs with JoinValueSpace struct (10 tests)
- Add ConditionEnvBuilder v2 API using JoinValueSpace
- Wire Pattern 2 frontend to use JoinValueSpace for param allocation
Note: E2E tests fail until Task 201-5 wires lowerers to alloc_local()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added type and skeleton infrastructure for function-scoped variable
capture, preparing for Phase 200-B integration with ConditionEnv.
New Types:
- CapturedVar: { name, host_id, is_immutable }
- CapturedEnv: Collection of captured variables
- ParamRole: { LoopParam, Condition, Carrier, ExprResult }
New Functions (Skeletons):
- analyze_captured_vars(): Detects function-scoped "constants"
- build_with_captures(): ConditionEnvBuilder v2 entry point
- add_param_with_role(): Role-based parameter routing
New File:
- src/mir/loop_pattern_detection/function_scope_capture.rs
Design Principles:
- Infra only: Types and skeletons, no behavior changes
- Existing behavior maintained: All current loops work identically
- Box-first: New responsibilities in new file
- Documentation: Future implementation plans in code comments
Test Results:
- 6 new unit tests (function_scope_capture: 3, param_role: 3)
- All 804 existing tests PASS (0 regressions)
Next: Phase 200-B (actual capture detection and integration)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>