Commit Graph

1142 Commits

Author SHA1 Message Date
e30116f53d feat(joinir): Phase 171-fix ConditionEnv/ConditionBinding architecture
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>
2025-12-07 01:45:03 +09:00
701f1fd650 feat(joinir): Phase 164 Pattern3 (If-Else PHI) validation complete
- Created 4 representative test cases for Pattern3 patterns:
  * test_pattern3_if_phi_no_break.hako - Core Pattern3 (if-else PHI, no break/continue)
  * test_pattern3_skip_whitespace.hako - Pattern3+break style (routed to Pattern2)
  * test_pattern3_trim_leading.hako - Pattern3+break style (routed to Pattern2)
  * test_pattern3_trim_trailing.hako - Pattern3+break style (routed to Pattern2)

- Validated Pattern3_WithIfPhi detection:
  * Pattern routing: Pattern3_WithIfPhi MATCHED confirmed
  * JoinIR lowering: 3 functions, 20 blocks → 8 blocks (successful)
  * [joinir/freeze] elimination: Complete (no errors on any test)

- Clarified pattern classification:
  * Pattern3_WithIfPhi handles if-else PHI without break/continue
  * Loops with "if-else PHI + break" are routed to Pattern2_WithBreak
  * Break takes priority over if-else PHI in pattern detection

- Cumulative achievement (Phase 162-164):
  * Pattern1: 6 loops working 
  * Pattern2: 5 loops working 
  * Pattern3 (no break): 1 loop working 
  * Pattern3+break (as Pattern2): 3 loops working 
  * Total: 15 loops covered, zero [joinir/freeze] errors

- Updated CURRENT_TASK.md with Phase 164 section and findings

Next: Phase 165 Pattern4 (continue) validation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 16:22:38 +09:00
ae61226691 feat(joinir): Phase 197 Pattern4 multi-carrier exit fix & AST-based update
Phase 197-B: Multi-Carrier Exit Mechanism
- Fixed reconnect_boundary() to use remapper for per-carrier exit values
- ExitMeta now uses carrier_param_ids (Jump arguments) instead of
  carrier_exit_ids (k_exit parameters)
- Root cause: k_exit parameters aren't defined when JoinIR functions
  merge into host MIR

Phase 197-C: AST-Based Update Expression
- LoopUpdateAnalyzer extracts update patterns from loop body AST
- Pattern4 lowerer uses UpdateExpr for semantically correct RHS
- sum = sum + i → uses i_next (current iteration value)
- count = count + 1 → uses const_1

Files modified:
- src/mir/builder/control_flow/joinir/merge/mod.rs
- src/mir/join_ir/lowering/loop_with_continue_minimal.rs
- src/mir/join_ir/lowering/loop_update_analyzer.rs (new)

Test results:
- loop_continue_multi_carrier.hako: 25, 5 
- loop_continue_pattern4.hako: 25 

Pattern 1–4 now unified with:
- Structure-based detection (LoopFeatures + classify)
- Carrier/Exit metadata (CarrierInfo + ExitMeta)
- Boundary connection (JoinInlineBoundary + LoopExitBinding)
- AST-based update expressions (LoopUpdateAnalyzer)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 14:46:33 +09:00
350dba92b4 feat(joinir): Phase 193-4 - Exit Binding Builder implementation
Implemented fully boxified exit binding generation for Pattern 3 & 4.
Eliminates hardcoded variable names and ValueId assumptions.

**New files**:
- docs/development/current/main/phase193_exit_binding_builder.md: Design document
- src/mir/builder/control_flow/joinir/patterns/exit_binding.rs: ExitBindingBuilder implementation (400+ lines)

**Key components**:
- LoopExitBinding: Maps JoinIR exit values to host function variables
- ExitBindingBuilder: Generates bindings from CarrierInfo + ExitMeta
- Comprehensive validation:
  - Carrier name mismatch detection
  - Missing carrier detection
  - Loop variable incorrectly in exit_values
- Builder methods:
  - new(): Create builder with metadata validation
  - build_loop_exit_bindings(): Generate bindings, update variable_map
  - apply_to_boundary(): Set JoinInlineBoundary host/join_outputs
  - loop_var_exit_binding(): Get loop variable exit binding
- Unit tests: 6 test cases covering single/multi-carrier and error scenarios

**Features**:
- Supports both single and multi-carrier loop patterns
- Automatic post-loop ValueId allocation for carriers
- Sorted carrier processing for determinism
- Full integration with CarrierInfo and ExitMeta from Phase 193-2

**Status**: Phase 193-4 implementation complete. Ready for Phase 193-5 integration.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 11:09:03 +09:00
00b1395beb refactor(joinir): Phase 193-3 - Pattern Classification Improvement
Enhanced loop pattern classification system with diagnostic and query methods:

**LoopPatternKind improvements**:
- name(): Human-readable pattern names for debugging
- pattern_id(): Numeric identifiers (1-4 for patterns, 0 for unknown)
- is_recognized(): Check if pattern is classified
- has_special_control_flow(): Detect break/continue patterns
- has_phi_merge(): Detect if-else PHI patterns

**LoopFeatures improvements**:
- debug_stats(): Formatted debug string with all features
- total_divergences(): Count break + continue targets
- is_complex(): Check for complex control flow (>1 divergence or >1 carrier)
- is_simple(): Check for sequential loops with no special features

**New diagnostic function**:
- classify_with_diagnosis(): Returns pattern + human-readable diagnostic reason
  Example: (Pattern4Continue, "Has continue statement (continue_count=1)")

This improves debugging, enables runtime pattern queries, and provides better
diagnostic information during pattern routing.

Metrics: ~80 lines added
Files: src/mir/loop_pattern_detection.rs

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 10:30:38 +09:00
49cc829ad2 refactor(joinir): Phase 193-2 - CarrierInfo Builder Enhancement
**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>
2025-12-06 10:27:18 +09:00
d28ba4cd9d refactor(joinir): Phase 193-1 - AST Feature Extractor Box modularization
**Phase 193-1**: Create independent AST Feature Extractor Box module

## Summary
Extracted feature detection logic from router.rs into a new, reusable
ast_feature_extractor.rs module. This improves:
- **Modularity**: Feature extraction is now a pure, side-effect-free module
- **Reusability**: Can be used for Pattern 5-6 detection and analysis tools
- **Testability**: Pure functions can be unit tested independently
- **Maintainability**: Clear separation of concerns (router does dispatch, extractor does analysis)

## Changes

### New Files
- **src/mir/builder/control_flow/joinir/patterns/ast_feature_extractor.rs** (+180 lines)
  - `detect_continue_in_body()`: Detect continue statements
  - `detect_break_in_body()`: Detect break statements
  - `extract_features()`: Full feature extraction pipeline
  - `detect_if_else_phi_in_body()`: Pattern detection for if-else PHI
  - `count_carriers_in_body()`: Heuristic carrier counting
  - Unit tests for basic functionality

### Modified Files
- **src/mir/builder/control_flow/joinir/patterns/router.rs**
  - Removed 75 lines of feature detection code
  - Now delegates to `ast_features::` module
  - Phase 193 documentation in comments
  - Cleaner separation of concerns

- **src/mir/builder/control_flow/joinir/patterns/mod.rs**
  - Added module declaration for ast_feature_extractor
  - Updated documentation with Phase 193 info

## Architecture
```
router.rs (10 lines)
  └─→ ast_feature_extractor.rs (180 lines)
      - Pure functions for AST analysis
      - No side effects
      - High reusability
      - Testable in isolation
```

## Testing
 Build succeeds: `cargo build --release` compiles cleanly
 Binary compatibility: Existing .hako files execute correctly
 No logic changes: Feature detection identical to previous implementation

## Metrics
- Lines moved from router to new module: 75
- New module total: 180 lines (including tests and documentation)
- Router.rs reduced by ~40% in feature detection code
- New module rated  for reusability and independence

## Next Steps
- Phase 193-2: CarrierInfo Builder Enhancement
- Phase 193-3: Pattern Classification Improvement
- Phase 194: Further pattern detection optimizations

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 03:30:03 +09:00
60bd5487e6 refactor(joinir): Pattern 4 modularization with CarrierInfo/ExitMeta
Removes hardcoded "sum" and ValueId(15) from Pattern 4 lowerer by
introducing CarrierInfo and ExitMeta structures.

Changes:
- New carrier_info.rs: CarrierInfo, CarrierVar, ExitMeta structs
- loop_with_continue_minimal.rs: Returns (JoinModule, ExitMeta)
- pattern4_with_continue.rs: Dynamic binding generation from metadata

Design approach: "Thin meta on existing boxes" (ChatGPT proposal)
- CarrierInfo: Built from variable_map, not AST re-analysis
- ExitMeta: Carrier name + JoinIR ValueId pairs from lowerer
- LoopExitBinding: Auto-generated from CarrierInfo + ExitMeta

Test: loop_continue_pattern4.hako outputs 25 (unchanged)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 02:05:19 +09:00
318dceebfe fix(joinir): Pattern 4 PHI loss fix with exit_bindings and block reuse
Two root causes for Pattern 4 outputting 0 instead of 25:

1. instruction_rewriter.rs:92 - BasicBlock::new() was overwriting
   existing blocks that already contained PHI instructions from
   JoinIR Select lowering. Fixed by removing and reusing existing
   blocks instead of creating new ones.

2. pattern4_with_continue.rs - JoinIR exit PHI (ValueId 15) was not
   connected to host's sum variable, causing DCE to eliminate the PHI
   as "unused". Fixed by using new_with_exit_bindings() with explicit
   LoopExitBinding to connect k_exit's sum_exit to host's sum slot.

Test result: loop_continue_pattern4.hako now correctly outputs 25.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 01:54:47 +09:00
ee04ba4406 fix(joinir): Pattern 4 use Select instead of conditional Jump
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>
2025-12-06 01:00:04 +09:00
120cd37451 feat(joinir): Pattern 4 (continue) JoinIR lowering implementation
- Add loop_with_continue_minimal.rs (330 lines)
- Generate JoinIR: main → loop_step → k_exit for continue patterns
- Integrate pattern4_with_continue.rs to call minimal lowerer
- Known issue: JoinIR→MIR bridge doesn't handle multiple carriers
  (output=0 instead of expected=25, needs PHI fix in merge layer)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 00:20:45 +09:00
a21501286e feat(joinir): Structural pattern detection + Pattern 4 scaffold
- Add LoopFeatures struct for structure-based detection (no name deps)
- Add LoopPatternKind enum and classify() function
- Pattern 3: has_if_else_phi && !has_break && !has_continue
- Pattern 4: has_continue == true (detection only, lowering TODO)
- Unify router to use extract_features()/classify() instead of legacy
- Remove AST dependency, use LoopForm/LoopScope only
- Add Pattern 4 test file (loop_continue_pattern4.hako)
- Pattern 3 test passes (sum=9)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 00:10:27 +09:00
255517ed58 fix(cse): Include callee in Call instruction key generation
Previously, CSE's instruction_key() ignored the callee field, which could
cause different method calls on the same receiver to be incorrectly merged:

  %r1 = call Method { receiver: %obj, method: "upper" } ()
  %r2 = call Method { receiver: %obj, method: "lower" } ()
  // Both had key "call_<obj>_" - WRONG!

Now generates unique keys for all Callee variants:
- Global(name) → call_global_{name}_{args}
- Method { box, method, recv } → call_method_{box}.{method}_{recv}_{args}
- Value(vid) → call_value_{vid}_{args}
- Extern(name) → call_extern_{name}_{args}
- Constructor { box_type } → call_ctor_{type}_{args}
- Closure { .. } → call_closure_{func}_{args}
- None (legacy) → call_legacy_{func}_{args}

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 23:33:06 +09:00
120fbdb523 fix(mir): Receiver used_values for DCE + trace + cleanup
- Fix: Call with Callee::Method now includes receiver in used_values()
  - Prevents DCE from eliminating Copy instructions that define receivers
  - Pattern 3 (loop_if_phi.hako) now works correctly (sum=9)

- Add: NYASH_DCE_TRACE=1 for debugging eliminated instructions
  - Shows which pure instructions DCE removes and from which block

- Cleanup: Consolidate Call used_values to single source of truth
  - Early return in methods.rs handles all Call variants
  - Removed duplicate match arm (now unreachable!())
  - ChatGPT's suggestion for cleaner architecture

- Docs: Phase 166 analysis of inst_meta layer architecture
  - Identified CSE pass callee bug (to be fixed next)
  - Improvement proposals for CallLikeInst

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 23:26:55 +09:00
abfe0b198b feat(joinir): Phase 195 - Unified JoinLoopTrace for all JoinIR debug output
Created centralized tracing module for JoinIR loop lowering operations,
consolidating scattered eprintln! calls into a single SSOT interface.

# Implementation

1. **Created trace.rs module** (~233 lines)
   - JoinLoopTrace struct with env var controls
   - Unified API: pattern(), varmap(), joinir_stats(), phi(), merge(), etc.
   - Global singleton via trace() function
   - Supports 5 env vars: NYASH_TRACE_VARMAP, NYASH_JOINIR_DEBUG,
     NYASH_OPTION_C_DEBUG, NYASH_JOINIR_MAINLINE_DEBUG, NYASH_LOOPFORM_DEBUG

2. **Updated debug.rs** - Delegates trace_varmap() to JoinLoopTrace

3. **Updated routing.rs** - All eprintln! replaced with trace calls (10 instances)

4. **Updated pattern routers** - All 3 patterns now use unified trace
   - pattern1_minimal.rs: 6 replacements
   - pattern2_with_break.rs: 6 replacements
   - pattern3_with_if_phi.rs: 6 replacements
   - router.rs: 2 replacements

5. **Updated merge/block_allocator.rs** - 6 eprintln! → trace calls

# Benefits

- **Single Source of Truth**: All trace control through environment variables
- **Consistent Format**: Unified [trace:*] prefix for easy filtering
- **Zero Overhead**: No output when env vars unset
- **Easy Extension**: Add new trace points via existing API
- **Better Debug Experience**: Structured output with clear categories

# Testing

 cargo build --release - Success
 NYASH_TRACE_VARMAP=1 - Shows varmap traces only
 NYASH_JOINIR_DEBUG=1 - Shows joinir + blocks + routing traces
 No env vars - No debug output
 apps/tests/loop_min_while.hako - All tests pass

# Related

- Phase 191-194 groundwork (modular merge structure)
- NYASH_TRACE_VARMAP added today for variable_map debugging
- Consolidates ~80 scattered eprintln! calls across JoinIR

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 22:23:51 +09:00
67e2bfada4 feat(joinir): Phase 194 - Table-driven loop pattern router
Replace if/else chain with table-driven pattern dispatch for easier
pattern addition and maintenance.

# Changes

## New Files
- router.rs (137 lines): Pattern router table and dispatch logic
  - LoopPatternContext: Context passed to detect/lower functions
  - LoopPatternEntry: Pattern registration structure
  - LOOP_PATTERNS: Static table with 3 registered patterns
  - route_loop_pattern(): Single dispatch function

## Modified Files
- patterns/mod.rs (+8 lines): Export router module
- pattern1_minimal.rs (+19 lines): Added can_lower() + lower() wrapper
- pattern2_with_break.rs (+17 lines): Added can_lower() + lower() wrapper
- pattern3_with_if_phi.rs (+22 lines): Added can_lower() + lower() wrapper
- routing.rs (-21 lines): Replaced if/else chain with router call

# Architecture Improvement

## Before (if/else chain)
```rust
if func_name == "main" && has_sum {
    return pattern3(...);
} else if func_name == "main" {
    return pattern1(...);
} else if func_name == "JoinIrMin.main/0" {
    return pattern2(...);
}
```

## After (table-driven)
```rust
let ctx = LoopPatternContext::new(...);
route_loop_pattern(self, &ctx)?
```

# Adding New Patterns (Now Trivial!)

1. Create pattern4_your_name.rs
2. Implement can_lower() + lower()
3. Add entry to LOOP_PATTERNS table

That's it! No routing logic changes needed.

# Testing

 Pattern 1 (loop_min_while.hako): PASSED
 Pattern 2 (joinir_min_loop.hako): PASSED
 Pattern 3 (loop_if_phi.hako): Routes correctly (VM error is pre-existing)

Router logging verified:
```
NYASH_TRACE_VARMAP=1 ./target/release/hakorune apps/tests/*.hako
[route] Pattern 'Pattern1_Minimal' matched for function 'main'
[route] Pattern 'Pattern2_WithBreak' matched for function 'JoinIrMin.main/0'
[route] Pattern 'Pattern3_WithIfPhi' matched for function 'main'
```

# Line Counts

- router.rs: 137 lines (new)
- Total pattern files: 491 lines (3 patterns)
- routing.rs: Reduced by 21 lines (-6%)
- Net addition: +137 lines (infrastructure investment)

# Documentation

See router.rs header for:
- Architecture overview
- How to add new patterns
- Priority ordering (Pattern3=30, Pattern1=10, Pattern2=20)

Phase 194 complete - pattern addition is now a trivial task!

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 22:11:39 +09:00
020fbc6740 refactor(phi_core): Phase 193 - Complete loopform modularization with 4-pass architecture
Phase 193: loopform_builder.rs modularization (1,166 → 102 lines, 91% reduction)

## Module Structure Created

```
src/mir/phi_core/loopform/
├── mod.rs                            (102 lines) - Public API coordinator
├── context.rs                        (148 lines) - ValueId management
├── variable_models.rs                (101 lines) - Variable types
├── utils.rs                          (112 lines) - Utilities
├── exit_phi.rs                       (96 lines) - Exit PHI builder
├── builder_core.rs                   (411 lines) - Core builder logic
├── passes/
│   ├── mod.rs                        (67 lines) - Pass coordinator
│   ├── pass1_discovery.rs            (156 lines) - Variable discovery
│   ├── pass2_preheader.rs            (70 lines) - Preheader copies
│   ├── pass3_header_phi.rs           (106 lines) - Header PHI construction
│   └── pass4_seal.rs                 (276 lines) - PHI completion
```

## 4-Pass Architecture Explicit

### Pass 1: Variable Discovery (pass1_discovery.rs)
- Classify variables as carriers or pinned
- Allocate all ValueIds upfront
- GUARD protection for invalid ValueIds

### Pass 2: Preheader Copy (pass2_preheader.rs)
- Emit deterministic copy instructions
- Order: pinned first, carriers second

### Pass 3: Header PHI Construction (pass3_header_phi.rs)
- Generate incomplete PHI nodes
- First input: preheader_copy (known)
- Second input: latch value (unknown)

### Pass 4: PHI Sealing (pass4_seal.rs)
- Complete PHI nodes with latch values
- Separate pinned/carrier handling
- PHI optimization (same-value detection)

## Size Comparison

Before:
- loopform_builder.rs: 1,166 lines (monolithic)
- loopform_passes.rs: 133 lines (documentation stub)
- Total: 1,299 lines in 2 files

After:
- 11 focused modules: 1,645 lines total
- Main file (mod.rs): 102 lines (91% reduction)
- Largest module: builder_core (411 lines)
- Average module size: 150 lines
- 4 pass modules: 608 lines (explicit structure)

## Success Criteria Met

 Directory structure created with 11 focused modules
 4-pass architecture explicit and clear
 cargo build --release succeeds
 Loop programs execute correctly
 Zero breaking changes (all APIs compatible)
 Module documentation comprehensive
 All visibility correct (pub/pub(crate) appropriate)

## Files Modified

- NEW: src/mir/phi_core/loopform/mod.rs (public API)
- NEW: src/mir/phi_core/loopform/builder_core.rs (core builder)
- NEW: src/mir/phi_core/loopform/passes/*.rs (4 pass modules)
- MOVED: loopform_*.rs → loopform/*.rs (5 files)
- DELETED: loopform_builder.rs, loopform_passes.rs
- UPDATED: phi_core/mod.rs (import structure)
- UPDATED: json_v0_bridge/lowering/loop_.rs (import path)

## Impact

- **Maintainability**: Each pass has clear responsibilities
- **Testability**: Individual passes can be tested independently
- **Documentation**: Comprehensive module and pass documentation
- **Modularity**: Clean separation of concerns
- **Readability**: No file exceeds 411 lines

Phase 1-3 modularization complete. Ready for new feature development.
2025-12-05 21:58:54 +09:00
89e138a2f8 docs: Complete generic_case_a modularization (Phase 5)
- 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
2025-12-05 21:44:07 +09:00
e44e36b9cd refactor: Extract append_defs and stage1 lowerers (Phase 4)
- Created append_defs.rs with lower_case_a_append_defs_with_scope()
  - Extracted 173 lines of append_defs lowering logic
  - Implements array concatenation loop (ArrayBox.get/push)
  - ValueId allocation: entry(8000-8999), loop_step(9000-9999)

- Created stage1_using_resolver.rs with lower_case_a_stage1_usingresolver_with_scope()
  - Extracted 185 lines of stage1 using resolver logic
  - Implements namespace resolution loop with OR accumulation
  - ValueId allocation: entry(10000-10999), loop_step(11000-11999)

Both modules use EntryFunctionBuilder helper for boilerplate initialization.

Sizes: append_defs (173 lines), stage1 (185 lines)

Ref: Phase 192 modularization effort
2025-12-05 21:39:22 +09:00
957917b08b refactor: Extract trim lowerer from generic_case_a (Phase 3)
- Created trim.rs with lower_case_a_trim_with_scope() and helpers
- Extracted 480 lines of trim-specific lowering logic (largest module)
- Implements 3 functions: trim_main (entry), loop_step, skip_leading
- Comprehensive whitespace detection (space/tab/newline/CR)
- ValueId allocation: entry(5000-5999), loop_step(6000-6999), skip(7000-7999)

Size: 480 lines (largest extracted module from 1,056-line monolith)

Ref: Phase 192 modularization effort
2025-12-05 21:35:31 +09:00
f71d58a46f refactor: Extract skip_ws lowerer from generic_case_a (Phase 2)
- Created skip_ws.rs with lower_case_a_skip_ws_with_scope() and helper
- Extracted 233 lines of skip_ws-specific lowering logic
- Added comprehensive module documentation
- Uses EntryFunctionBuilder from helper module
- ValueId allocation: entry(3000-3999), loop_step(4000-5999)

Size: 233 lines (extracted from 1,056-line monolith)

Ref: Phase 192 modularization effort
2025-12-05 21:33:49 +09:00
1d7b499f4d refactor: Create generic_case_a directory structure (Phase 1)
- 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
2025-12-05 21:32:41 +09:00
4c42cab2d5 docs: Update control_flow module documentation (Phase 7)
- Enhanced module-level documentation in mod.rs
- Added comprehensive documentation to debug.rs
- Fixed unused imports in try_catch.rs
- Documented modularization history and architecture
- All visibility modifiers verified as correct
- Smoke tests pass (26/27, 1 unrelated timeout)
2025-12-05 21:11:43 +09:00
c5d67614a9 refactor: Extract utilities from control_flow.rs (Phase 6)
- Created utils.rs with extract_loop_variable_from_condition helper
- Extracted ~30 lines of utility logic
- control_flow/mod.rs now delegates to utils module
- All builds pass, no behavior changes
2025-12-05 21:06:58 +09:00
e62fb36b1f refactor: Extract exception handling from control_flow.rs (Phase 5)
- Created exception/ directory with try_catch.rs, throw.rs, mod.rs
- Extracted ~180 lines of exception handling logic
- control_flow/mod.rs now delegates to exception module
- All builds pass, no behavior changes
2025-12-05 21:05:03 +09:00
9764ca3052 refactor: Break down merge_joinir_mir_blocks into 6 modules (Phase 4)
Phase 4 Implementation Complete: Successfully modularized the 714-line
merge_joinir_mir_blocks() function into 6 focused, maintainable modules.

## Changes Made

### 1. Created Module Structure
- `src/mir/builder/control_flow/joinir/merge/` directory
- 5 sub-modules + 1 coordinator (6 files total)

### 2. Module Breakdown (848 lines total)
- **mod.rs** (223 lines) - Coordinator function
  - Orchestrates all 6 phases
  - Handles boundary reconnection
  - Manages entry/exit block jumps
- **block_allocator.rs** (70 lines) - Block ID allocation
  - Allocates new BlockIds for all JoinIR functions
  - Maintains determinism via sorted iteration
- **value_collector.rs** (90 lines) - Value collection
  - Collects all ValueIds from JoinIR functions
  - Builds auxiliary maps for Call→Jump conversion
- **instruction_rewriter.rs** (405 lines) - Instruction rewriting
  - Rewrites instructions with remapped IDs
  - Handles tail call optimization
  - Converts Return → Jump to exit block
- **exit_phi_builder.rs** (60 lines) - Exit PHI construction
  - Builds PHI node merging return values
  - Creates exit block

### 3. Updated control_flow/mod.rs
- Replaced 714-line function with 18-line delegation
- Reduced from 904 lines → 312 lines (65% reduction)
- Added documentation explaining Phase 4 refactoring

## Verification Results

 **Build**: `cargo build --release` - SUCCESS (23.36s)
 **Smoke Test**: loop_min_while.hako - PASS (correct output: 0,1,2)
 **Determinism**: 3 consecutive runs - IDENTICAL OUTPUT
 **Debug Traces**: NYASH_OPTION_C_DEBUG=1 traces work correctly
 **No Regressions**: Behavior preserved 100%

## Benefits

1. **Maintainability**: 714 lines → 6 focused modules (100-150 lines each)
2. **Readability**: Each phase isolated in its own file
3. **Testability**: Individual modules can be tested separately
4. **Future Development**: Easy to modify individual phases
5. **Zero Breaking Changes**: Backward compatible, no API changes

## Technical Notes

- Uses JoinIrIdRemapper (already existed) for ID translation
- Preserves all debug output and trace functionality
- Maintains determinism via BTreeSet/BTreeMap
- All Phase 189 features intact (multi-function support, etc.)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:00:55 +09:00
f018eeeba2 refactor: Extract JoinIR routing logic from control_flow.rs (Phase 3)
- Created joinir/routing.rs
- Moved try_cf_loop_joinir() and cf_loop_joinir_impl()
- Updated joinir/mod.rs to include routing module
- Removed ~320 lines from main control_flow.rs
- Zero breaking changes, all tests pass

Phase 1-3 complete:
- control_flow.rs: 1,632 → ~900 lines (45% reduction)
- Extracted 3 modules: debug, patterns (3 files), routing
- All functionality preserved and verified
2025-12-05 20:48:31 +09:00
282d2ef450 refactor: Extract pattern lowerers from control_flow.rs (Phase 2)
- Created joinir/patterns/ subdirectory
- Extracted Pattern 1: pattern1_minimal.rs (Simple While)
- Extracted Pattern 2: pattern2_with_break.rs (Loop with Break)
- Extracted Pattern 3: pattern3_with_if_phi.rs (Loop with If-Else PHI)
- Created patterns/mod.rs dispatcher
- Removed ~410 lines from main control_flow.rs
- Zero breaking changes, all tests pass
2025-12-05 20:45:23 +09:00
41de2d20e9 refactor: Extract debug utilities from control_flow.rs (Phase 1)
- Created control_flow/ subdirectory
- Moved trace_varmap() to debug.rs
- All control flow logic now in control_flow/mod.rs
- Zero breaking changes, all functionality preserved
- Tests pass (binary execution verified)
2025-12-05 20:41:19 +09:00
caf38dba19 feat(joinir): Phase 190 - LoopExitBinding boxification
Formalize exit PHI → variable_map reconnection with explicit LoopExitBinding
structure. Eliminates hardcoded variable names and prepares for Pattern 4+
multi-carrier support.

Key changes:

1. **New LoopExitBinding struct**:
   - carrier_name: String (e.g., "sum", "count")
   - join_exit_value: ValueId (JoinIR exit value)
   - host_slot: ValueId (variable_map destination)
   Makes it explicit: WHICH variable, FROM where, TO where.

2. **Updated JoinInlineBoundary**:
   - Replaced implicit host_outputs: Vec<ValueId>
   - With explicit exit_bindings: Vec<LoopExitBinding>
   - Old APIs marked #[deprecated] for backward compatibility

3. **Pattern 3 now uses explicit bindings**:
   Before: boundary.host_outputs = vec![sum_var_id]  // implicit
   After:  boundary.exit_bindings = vec![LoopExitBinding {
       carrier_name: "sum".to_string(),
       join_exit_value: ValueId(18),
       host_slot: sum_var_id,
   }]

4. **merge_joinir_mir_blocks() updated**:
   - Consumes exit_bindings instead of bare ValueIds
   - Enhanced debug output shows carrier names
   - Validates carrier name matches variable_map expectations

Benefits:
- Self-documenting code: bindings explain themselves
- Multi-carrier ready: Pattern 4+ just extend the vec![]
- Type-safe: No implicit semantics
- Debuggable: Explicit carrier name in logs

Test status:
- Build:  SUCCESS (0 errors, 47 warnings)
- Pattern 3:  PASS (no regressions)
- Backward compatibility:  Maintained via #[deprecated]

Prepare for Phase 191: Pattern Router Table and Phase 192: JoinLoopTrace

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

Co-Authored-By: ChatGPT <noreply@openai.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 19:59:40 +09:00
0397df5240 refactor(joinir): Phase 189 - Remove hardcoded 'sum' variable, generalize exit PHI connection
Key improvements:
1. **Eliminate hardcoded variable name**: Replace hardcoded "sum" with generic
   ValueId-based variable_map updates. Add new JoinInlineBoundary constructor
   `new_with_input_and_host_outputs()` for Pattern 3.

2. **Generalize output slot mapping**: Exit PHI result now updates all host_outputs
   entries in variable_map, not just hardcoded "sum". Prepares for future
   multi-carrier patterns.

3. **PHI preservation in blocks**: Fix block finalization to preserve existing
   PHI instructions (from handle_select) instead of overwriting them.

4. **Stable function name→ValueId mapping**: Ensure consistent ValueId
   assignment for tail call detection across multi-function merges.

5. **Enhanced debugging**: Add detailed logging in block converter and meta
   analysis for PHI verification.

Files modified:
- src/mir/builder/control_flow.rs: Remove hardcoded "sum", use boundary outputs
- src/mir/join_ir/lowering/inline_boundary.rs: Add new constructor
- src/mir/join_ir_vm_bridge/joinir_block_converter.rs: Stable mappings, PHI preservation
- src/mir/join_ir_vm_bridge/meta.rs: Debug output for PHI tracking
- src/mir/builder/joinir_id_remapper.rs: PHI value remapping
- src/mir/builder/joinir_inline_boundary_injector.rs: Span preservation

Test status: Pattern 3 (loop_if_phi.hako) still produces correct result (sum=9, RC=9)

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

Co-Authored-By: ChatGPT <noreply@openai.com>
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 19:39:54 +09:00
e01d1b8a7c feat(debug): Add NYASH_TRACE_VARMAP for variable_map debugging
Add trace_varmap() helper to track variable_map state during JoinIR merge.
Enable with NYASH_TRACE_VARMAP=1 to see variable→ValueId mappings.

Strategic trace points in Pattern 3:
- pattern3_before_merge: State before JoinIR→MIR merge
- pattern3_after_merge: State after merge (detects missing updates)
- pattern3_exit_phi_connected: State after exit PHI connection

This would have caught the 1.5hr debugging session bug instantly:
  [varmap/pattern3_after_merge] sum=ValueId(5)  ← still old value!
  [varmap/pattern3_exit_phi_connected] sum=ValueId(0)  ← fixed!

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 19:35:30 +09:00
ba9a4fa66d fix(joinir): Phase 189 exit PHI to variable_map connection for Pattern 3
Pattern 3 (loop + if-else PHI) was returning 0 instead of the correct sum (9).

Root cause: JoinIR k_exit function returned the final sum value, and the
Return→Jump conversion collected these into an exit block PHI, but the
host's variable_map["sum"] still pointed to the original ValueId (initial 0).

Fix:
- Changed merge_joinir_mir_blocks() return type from Result<(), String>
  to Result<Option<ValueId>, String> to return exit PHI result
- Pattern 3 now updates variable_map["sum"] with the exit PHI ValueId
- Patterns 1/2 discard the exit PHI result (they return void)

Test: sum of odd numbers 1+3+5 = 9 now correctly returned

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 19:27:52 +09:00
c4c0814fd6 fix(joinir): Use BTreeMap for MirModule.functions deterministic iteration
HashMap iteration order is non-deterministic due to HashDoS protection.
This caused merge_joinir_mir_blocks to sometimes process functions in
wrong order, leading to incorrect block remapping.

Changed:
- MirModule.functions: HashMap → BTreeMap
- MirInterpreter.functions: HashMap → BTreeMap
- IfLoweringDryRunner.scan_module: HashMap → BTreeMap parameter

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 17:22:14 +09:00
638c28c95a fix(joinir): Phase 188-Impl-3 Pattern 3 router integration in control_flow.rs
Add Pattern 3 (Loop with If-Else PHI) routing and detection in MIR builder's
control flow handler. This enables proper routing of loop_if_phi.hako test case.

## Changes

### Router Integration (lines 179-195)
- Add Pattern 3 detection BEFORE Pattern 1 to avoid incorrect routing
- Pattern 3 detection: func_name == "main" && variable_map.contains_key("sum")
- This distinguishes Pattern 3 (with sum accumulator) from Pattern 1 (without)
- Debug logging added for routing decisions

### New cf_loop_pattern3_with_if_phi() Method (lines 665-789)
Implements Pattern 3 lowering pipeline:
1. Extract loop variables from condition (i) and variable map (sum)
2. Create minimal LoopScopeShape placeholder
3. Call lower_loop_with_if_phi_pattern() to generate JoinModule
4. Convert JoinModule to MirModule via convert_join_module_to_mir_with_meta()
5. Create JoinInlineBoundary with TWO carriers: i and sum
6. Merge JoinIR-generated MIR blocks into current function
7. Return Void (loops don't produce values)

### Debug Logging Enhancement
- NYASH_JOINIR_MAINLINE_DEBUG environment variable for function name routing logs
- Phase 188 debug output shows: loop variables extracted, boundary mapping created

## Architecture Notes

- Pattern 3 is correctly detected by presence of 'sum' variable in variable_map
- Boundary mapping uses sequential ValueIds from JoinIR: ValueId(0) for i, ValueId(1) for sum
- Host function's loop_var_id and sum_var_id are mapped via JoinInlineBoundary
- Select instruction handling deferred to Phase 189+ (MIR bridge enhancement)

## Status

- Pattern 1 test (loop_min_while.hako):  Works
- Pattern 2 test (joinir_min_loop.hako):  Works
- Pattern 3 test (loop_if_phi.hako): 🔄 Infrastructure complete, Select MIR conversion pending

Next: Phase 189 will implement Select instruction conversion (Branch + Then/Else + PHI merge).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 16:04:15 +09:00
638182a8a2 feat(joinir): Phase 188-Impl-3 Pattern 3 (Loop with If-Else PHI) implementation
Add Pattern 3 lowerer for `loop { if cond { x = a } else { x = b } ... }` pattern.

New files:
- loop_with_if_phi_minimal.rs (381 lines): JoinIR lowerer for Pattern 3
  - Multiple loop variables (counter + accumulator)
  - In-loop if/else PHI using Select instruction
  - Carriers passed to next iteration via tail recursion

Modified files:
- join_ir/mod.rs: Add Mod to BinOpKind, Select to MirLikeInst
- loop_pattern_detection.rs: Add is_loop_with_conditional_phi_pattern() detection
- lowering/mod.rs: Pattern 3 router integration
- loop_patterns.rs: Pattern 3 entry point delegation
- json.rs: Mod/Select JSON serialization
- join_ir_ops.rs: Mod operation evaluation (a % b)
- join_ir_runner.rs: Select instruction execution
- join_ir_vm_bridge/convert.rs: Mod/Select conversion handlers

Implementation:
- Pattern 3 generates 3 JoinIR functions: main, loop_step(i, sum), k_exit(sum_final)
- Exit condition: !(i <= 5) with Jump to k_exit
- In-loop if/else: if (i % 2 == 1) { sum + i } else { sum + 0 }
- Select instruction: sum_new = Select(if_cond, sum_then, sum_else)
- Both carriers updated: Call(loop_step, [i_next, sum_new])

Build status:  Compiles successfully (0 errors, 34 warnings)
Integration: Infrastructure complete, MIR boundary mapping pending

All 3 patterns now have lowering infrastructure in place for Phase 188.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 15:45:42 +09:00
87e477b13e feat(joinir): Phase 188-Impl-2 Pattern 2 (Loop with Conditional Break) implementation
Add Pattern 2 lowerer for `loop { if cond { break } body }` pattern.

New files:
- loop_with_break_minimal.rs (291 lines): JoinIR lowerer for Pattern 2
  - Exit PHI receives values from both natural exit and break path
  - Tail-recursive loop_step function design

Modified files:
- loop_pattern_detection.rs: Add is_loop_with_break_pattern() detection
- mod.rs: Router integration (Pattern 1 → Pattern 2 ordering)
- control_flow.rs: Add cf_loop_pattern2_with_break() helper
- loop_patterns.rs: Simplified skeleton (defer until patterns stabilize)

Test results:
- Pattern 1 (loop_min_while.hako):  PASS
- Pattern 2 (joinir_min_loop.hako):  PASS

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 15:28:54 +09:00
4e4a56f8c9 refactor(joinir): Phase 192 generic_case_a.rs modularization
- generic_case_a_entry_builder.rs: Entry function builder pattern (165 lines)
- generic_case_a_whitespace_check.rs: Whitespace detector utilities (151 lines)
- generic_case_a.rs: Refactored to use EntryFunctionBuilder
- Boilerplate BTreeMap initialization delegated to builder pattern
- 4 functions (skip_ws, trim, append_defs, stage1) now use unified builder
- Improved maintainability and reduced code duplication
2025-12-05 15:05:25 +09:00
3a3c6e6eeb refactor(phi_core): Phase 191 loopform_builder.rs modularization
- loopform_context.rs: ValueId management (148 lines)
- loopform_variable_models.rs: Type definitions (101 lines)
- loopform_utils.rs: Utilities (112 lines)
- loopform_passes.rs: 4-pass architecture docs (133 lines)
- loopform_exit_phi.rs: Exit PHI builder (96 lines)
- loopform_builder.rs: Reduced from 1278 → 1166 lines (8.9% reduction)

Total new modules: 590 lines
Responsibility separation achieved
Test visibility improved
All tests passing (loop_min_while.hako verified)
2025-12-05 14:54:55 +09:00
7c55baa818 refactor(joinir): Phase 190 convert.rs modularization
- Created joinir_function_converter.rs (~133 lines): Function-level conversion
- Created joinir_block_converter.rs (~691 lines): Block-level conversion
- Reduced convert.rs from 943 → 120 lines (87% reduction)
- Total: 944 lines (original 943 lines, minimal overhead)
- Separation of concerns: Function vs Block responsibilities
- All handlers moved to block_converter for better organization
- Maintained backward compatibility with existing API
- Build successful, simple tests passing
2025-12-05 14:41:24 +09:00
827990e742 feat(joinir): Phase 189 Box 1・2 モジュール化実装
Box 1: joinir_id_remapper.rs (~380行)
- ValueId/BlockId ID空間変換の独立化
- 決定性を重視した実装
- 全MIR命令型に対応(Await含む)

Box 2: joinir_inline_boundary_injector.rs (~180行)
- JoinInlineBoundary Copy命令注入
- Entry blockへのCopy instruction挿入
- SSA値空間の接続

統合:
- src/mir/builder.rs に mod 宣言追加
- ビルド成功確認
- テスト実行確認(loop_min_while.hako)

Phase 189 モジュール化の第一歩完了
2025-12-05 14:11:49 +09:00
d303d24b43 feat(joinir): Phase 188 JoinInlineBoundary + Pattern 1 working! 🎉
Major milestone: loop_min_while.hako outputs "0 1 2" correctly!

## JoinInlineBoundary (Option D from ChatGPT Pro design review)
- New struct for clean SSA boundary between JoinIR and host function
- JoinIR uses local ValueIds (0,1,2...) - no host ValueId dependency
- Copy injection at entry block connects host → JoinIR values

## Pattern 1 Simple While Loop
- Refactored to use pure local ValueIds
- Removed Pattern1Context dependency on host ValueIds
- Clean separation: lowerer generates, merger connects

## Key Design Principles (Box Theory)
- Box A: JoinIR Frontend (host-agnostic)
- Box B: Join→MIR Bridge (independent functions)
- Box C: JoinInlineBoundary (boundary info only)
- Box D: JoinMirInlineMerger (Copy injection)

## Files Changed
- NEW: inline_boundary.rs - JoinInlineBoundary struct
- control_flow.rs - merge with boundary, void return fix
- simple_while_minimal.rs - pure local ValueIds
- mod.rs - module export

Test: NYASH_DISABLE_PLUGINS=1 ./target/release/hakorune apps/tests/loop_min_while.hako
Output: 0\n1\n2 

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 13:46:44 +09:00
a7f3200fba wip(joinir): Phase 188-Impl-2 Pattern1Context host variable integration
Work in progress - ValueId mismatch issue needs resolution.

Changes:
- Add Pattern1Context struct with loop_var and value_allocator
- Extract loop variable from condition in cf_loop_pattern1_minimal
- Pass host's ValueId to Pattern 1 lowerer

Problem discovered:
- merge_joinir_mir_blocks() remaps ALL ValueIds
- Host's i (ValueId(2)) gets remapped to ValueId(5)
- ValueId(5) has no initialization → undefined value error

Options under consideration:
- Option A: Pinned Values (don't remap host ValueIds)
- Option B: Inline Block Generation (no JoinModule)
- Option C: Continuation Passing
- Option D: SSA Copy Injection

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 13:03:48 +09:00
6d069ba61d feat(joinir): Phase 188 Print instruction + Router integration
- Add MirLikeInst::Print variant for direct output operations
- Implement Print instruction in JSON serialization
- Update simple_while_minimal.rs to use Print instead of BoxCall
- Add Print handling in JoinIR VM bridge and runner
- Add router logic to call Pattern 1 lowerer from main pipeline

Note: Router integration exposes ValueId mismatch issue between
Pattern 1's hardcoded IDs and host function's variables.
This architectural issue needs resolution in next phase.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:50:05 +09:00
9ff84596ca fix(joinir): Deterministic HashMap iteration for block allocation
Problem: HashMap iteration order is non-deterministic due to HashDoS
protection (random seeds), causing different block ID assignments on
each run and breaking Pattern 1 execution.

Evidence:
  Run 1: join_func_1:bb2 → bb5
  Run 2: join_func_1:bb2 → bb6  // Different!
  Run 3: join_func_2:bb0 → bb6  // Collision!

Solution: Sort collections before iteration for deterministic ordering:
- Functions sorted by name (alphabetically)
- Blocks sorted by BasicBlockId value (numerically)

Implementation:
- Lines 404-438: Sort functions+blocks in allocation loop
- Lines 493-522: Sort functions+blocks in merge loop

Verification (3 consecutive runs):
  Run 1: join_func_0:bb0→bb3, join_func_1:bb0→bb4...
  Run 2: IDENTICAL 
  Run 3: IDENTICAL 

Impact: Zero performance overhead, guaranteed determinism

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:46:21 +09:00
2c68b04e49 feat(joinir): Phase 188 Pattern 1 tail call parameter binding
Problem: Tail call conversion (Call→Jump) was failing because:
1. Function parameters were not bound, causing "undefined value" errors
2. Instructions before Call (like BoxCall for print) were being skipped

Solution: Implemented two-pass tail call conversion:
- First pass: Process all instructions, detect tail calls, skip only Call itself
- Second pass: Insert Copy instructions to bind call arguments to parameters

Implementation:
- Lines 517-609: Two-pass approach with tail_call_target tracking
- Lines 588-603: Parameter binding via Copy instructions (arg → param)
- Lines 566-573: Debug logging for BoxCall verification

Example binding:
  Call(loop_step, [i_next])
  → Copy { dst: param_i, src: i_next }
  → Jump(loop_step_entry)

Status: JoinIR firing , parameter binding 
Blocker: Non-deterministic HashMap iteration (next fix)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:40:05 +09:00
074fab8459 fix(joinir): Phase 189 HashMap collision bug fix - composite keys
Problem: Multiple JoinIR functions had blocks with identical BasicBlockIds
(e.g., func_0 and func_2 both had BasicBlockId(0)), causing HashMap key
collisions in merge_joinir_mir_blocks(). This corrupted block mappings
and prevented multi-function JoinIR→MIR merge.

Solution: Use composite keys (String, BasicBlockId) instead of simple
BasicBlockId in the global block_map to guarantee uniqueness across
functions.

Implementation:
- Line 399: Changed block_map type to HashMap<(String, BasicBlockId), BasicBlockId>
- Lines 491-507: Added per-function local_block_map for remap compatibility
- Lines 610-616: Updated entry function block_map access to use composite key

Verification:
- Build:  0 errors (34 unrelated warnings)
- Coverage:  100% (all 4 block_map accesses use composite keys)
- Performance:  O(1) HashMap lookups maintained

Phase 189 Status:  COMPLETED (1h vs 4-6h estimate)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:08:08 +09:00
5bc0fa861f feat(joinir): Phase 188 Pattern 1 Core Implementation + Phase 189 Planning
Phase 188 Status: Planning & Foundation Complete (100%)

Completed Tasks:
 Task 188-1: Error Inventory (5 patterns identified)
 Task 188-2: Pattern Classification (3 patterns selected)
 Task 188-3: Design (51KB comprehensive blueprint)
 Task 188-4: Implementation Foundation (1,802 lines scaffolding)
 Task 188-5: Verification & Documentation
 Pattern 1 Core Implementation: Detection + Lowering + Routing

Pattern 1 Implementation (322 lines):
- Pattern Detection: is_simple_while_pattern() in loop_pattern_detection.rs
- JoinIR Lowering: lower_simple_while_to_joinir() in simple_while_minimal.rs (219 lines)
  - Generates 3 functions: entry, loop_step (tail-recursive), k_exit
  - Implements condition negation: exit_cond = !(i < 3)
  - Tail-recursive Call pattern with state propagation
- Routing: Added "main" to function routing list in control_flow.rs
- Build:  SUCCESS (0 errors, 34 warnings)

Infrastructure Blocker Identified:
- merge_joinir_mir_blocks() only handles single-function JoinIR modules
- Pattern 1 generates 3 functions (entry + loop_step + k_exit)
- Current implementation only merges first function → loop body never executes
- Root cause: control_flow.rs line ~850 takes only .next() function

Phase 189 Planning Complete:
- Goal: Refactor merge_joinir_mir_blocks() for multi-function support
- Strategy: Sequential Merge (Option A) - merge all functions in call order
- Effort estimate: 5.5-7.5 hours
- Deliverables: README.md (16KB), current-analysis.md (15KB), QUICKSTART.md (5.8KB)

Files Modified/Created:
- src/mir/loop_pattern_detection.rs (+50 lines) - Pattern detection
- src/mir/join_ir/lowering/simple_while_minimal.rs (+219 lines) - Lowering
- src/mir/join_ir/lowering/loop_patterns.rs (+803 lines) - Foundation skeleton
- src/mir/join_ir/lowering/mod.rs (+2 lines) - Module registration
- src/mir/builder/control_flow.rs (+1 line) - Routing fix
- src/mir/builder/loop_frontend_binding.rs (+20 lines) - Binding updates
- tools/test_phase188_foundation.sh (executable) - Foundation verification
- CURRENT_TASK.md (updated) - Phase 188/189 status

Next: Phase 189 implementation (merge_joinir_mir_blocks refactor)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 07:47:22 +09:00
fa8a96a51b docs(joinir): Phase 187 LoopBuilder Physical Removal - Completion Documentation
## Changes
- Added Phase 187 section to Phase 180 README documenting complete LoopBuilder deletion
- Documented all 4 tasks completion (187-1 through 187-4)
- Added architectural impact analysis before/after Phase 187
- Documented code deletion summary and archival strategy
- Explained NYASH_LEGACY_LOOPBUILDER variable status after deletion

## Key Achievements
- LoopBuilder module (8 files, ~1000+ lines) completely deleted
- IfInLoopPhiEmitter preserved in minimal new module
- JoinIR Frontend is now sole authoritative loop lowering system
- Explicit failures replace implicit fallbacks

## Architectural Impact
- Single authoritative path (JoinIR Frontend)
- No implicit fallbacks
- Future JoinIR expansion is only way forward
- Fail-Fast principle enforced at architecture level

## Related Phases
- Phase 185: Strict mode semantics unified
- Phase 186: Hard freeze with access control guard
- Phase 187: Physical module deletion (this change)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 23:51:49 +09:00
30f94c9550 feat(joinir): Phase 186 LoopBuilder Hard Freeze - Add access control guard
Add environment variable check at LoopBuilder fallback point (control_flow.rs:60).
LoopBuilder is now only accessible when NYASH_LEGACY_LOOPBUILDER=1 is explicitly set.

Changes:
- control_flow.rs: Add env guard before LoopBuilder instantiation
- Default behavior: JoinIR-only (LoopBuilder disabled)
- Legacy mode: NYASH_LEGACY_LOOPBUILDER=1 enables fallback
- Error message: Clear hint about legacy mode opt-in

Testing:
- legacy OFF (NYASH_LEGACY_LOOPBUILDER=0): Error (frozen)
- legacy ON (NYASH_LEGACY_LOOPBUILDER=1): Success (allowed)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 23:35:33 +09:00