Commit Graph

2393 Commits

Author SHA1 Message Date
f740e6542f feat(phase285): Complete weak reference implementation (VM + LLVM harness)
Phase 285LLVM-1.1 to 1.4 + weak reference infrastructure:

**LLVM Harness** (Phase 285LLVM-1.x):
- 285LLVM-1.1: User Box registration & debug output
- 285LLVM-1.2: WeakRef basic operations (identity deferred)
- 285LLVM-1.3: InstanceBox field access (getField/setField)
- 285LLVM-1.4: print Handle resolution (type tag propagation)

**VM Runtime** (nyash_kernel):
- FFI functions: nyrt_weak_new, nyrt_weak_to_strong, nyrt_weak_drop
  (crates/nyash_kernel/src/lib.rs: +209 lines)
- WeakRef plugin invoke support
  (crates/nyash_kernel/src/plugin/invoke.rs: +250 lines)
- weak_handles.rs: WeakRef handle registry (NEW)

**LLVM Python Backend**:
- WeakRef instruction lowering (weak.py: NEW)
- Entry point integration (entry.py: +93 lines)
- Instruction lowering (instruction_lower.py: +13 lines)
- LLVM harness runner script (tools/run_llvm_harness.sh: NEW)

**MIR & Runtime**:
- WeakRef emission & validation
- MIR JSON export for weak instructions
- Environment variable support (NYASH_WEAK_*, HAKO_WEAK_*)

**Documentation**:
- CLAUDE.md: Phase 285 completion notes
- LANGUAGE_REFERENCE_2025.md: Weak reference syntax
- 10-Now.md & 30-Backlog.md: Phase 285 status updates

Total: +864 lines, 24 files changed

SSOT: docs/reference/language/lifecycle.md
Related: Phase 285W-Syntax-0, Phase 285W-Syntax-0.1
2025-12-25 00:11:34 +09:00
cc05c37ae3 feat(phase285w): Phase 285W-Syntax-0.1 - Reject weak(...) syntax (Parser-level Fail-Fast)
- Parser guard: Reject weak(...) with LPAREN check in parse_unary()
  - Error: "Use 'weak expr', not 'weak(expr)'" (helpful message)
  - Location: src/parser/expressions.rs:248-256
- MIR builder guard: Defense-in-depth for any bypassed cases
  - Location: src/mir/builder/calls/build.rs:37-46
- Rejection test: apps/tests/phase285w_weak_call_rejected.hako
- Smoke test: phase285w_weak_call_rejected_vm.sh (PASS )
- Documentation:
  - EBNF.md: Add ~ (BitNot) to unary operators
  - lifecycle.md: Document weak(expr) as invalid syntax
  - phase-285/README.md: Add Phase 285W-Syntax-0.1 entry

Test results: 5/6 phase285 tests PASS (1 unrelated failure)
SSOT: docs/reference/language/lifecycle.md

Closes: Phase 285W-Syntax-0.1
2025-12-25 00:04:55 +09:00
9227673ef7 feat(phase285w): Implement weak x unary operator syntax
Phase 285W-Syntax-0: Migrate weak reference syntax from function call
to unary operator for consistency and clarity.

**Changes**:
- Parser: Add UnaryOperator::Weak variant and parse_unary() handling
- MIR: Lower UnaryOp::Weak to emit_weak_new() (reuses existing path)
- AST: Add Weak to UnaryOperator enum + Display/JSON support
- Tests: Migrate 8 files from `weak(x)` to `weak x` syntax
  - 7 .hako test files updated
  - 1 smoke test shell script updated
- Cleanup: Remove obsolete weak(x) parser/MIR special cases
- Docs: Update Phase 285 README

**Syntax Change**:
- Old: `local w = weak(x)`  (function call)
- New: `local w = weak x`   (unary operator)

**Validation**: All migrated phase285* smoke tests pass (4/4 relevant)

**SSOT**: docs/reference/language/lifecycle.md

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 17:21:21 +09:00
5b2b5528a5 refactor(llvm): Phase 285LLVM-1.5 - Code quality improvements + NYASH_CLI_VERBOSE logging
Code quality enhancements for Phase 285LLVM-1.4 print handle resolution:

**New Infrastructure**:
- src/llvm_py/utils/resolver_helpers.py: 8 helper functions for safe type tag access
  - safe_get_type_tag(), safe_set_type_tag(), is_handle_type(), etc.
  - Eliminates 70-80% of hasattr/isinstance boilerplate

**Type Tag Unification**:
- Unified string/handle tracking: resolver.value_types dict as SSOT
- Backward compatible with legacy string_ids set (transitional)
- Consistent value_types schema: {'kind': 'handle'|'string', 'box_type': 'StringBox'|...}

**Debug Logging**:
- Added NYASH_CLI_VERBOSE=1 support to visualize type tag operations
- Log tags: [llvm-py/types] [llvm-py/copy]
- Enables real-time debugging of type tag propagation

**Code Metrics**:
- Total lines: 42 → 20 (52% reduction)
- Nesting levels: avg 5.7 → 1.3 (65% reduction)
- Modified files: 3 (copy.py, global_call.py, boxcall.py)
- New files: 1 (resolver_helpers.py)

**Files Modified**:
1. copy.py: Simplified type tag propagation + NYASH_CLI_VERBOSE logging
2. global_call.py: Simplified handle detection + logging
3. boxcall.py: Simplified getField tagging + logging
4. New: utils/resolver_helpers.py - Centralized resolver safety helpers
5. Docs: Phase 285 documentation updated with improvements

**Backward Compatibility**:  All changes backward compatible

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

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-24 16:43:30 +09:00
83c897eb5d feat(llvm): Phase 285LLVM-1.4 - print Handle Resolution (type tag propagation)
Fix LLVM print to output 42 instead of 4 (handle value) for field access.

Root cause: Type tags lost through MIR copy instruction chains
- getField tagged ValueId 16 as handle
- MIR copy chain: 16 → 17 → 18
- print used ValueId 18 (not tagged) → treated as raw integer

Solution: Type-tag based handle detection with copy propagation
- boxcall.py: Tag getField results as handles
- global_call.py: Skip boxing for handles in print
- copy.py: Propagate value_types tags through copy chains

Test coverage:
- apps/tests/phase285_print_raw_int.hako: Raw int regression check
- apps/tests/phase285_userbox_field_basic.hako: Field access parity

Result: VM/LLVM parity achieved (both output 42) 

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 16:01:38 +09:00
3aba574723 refactor(llvm): Phase 286B - Unify error handling with Result<T, LlvmRunError>
This refactoring consolidates 20+ duplicated error handling patterns in LLVM mode
into a unified Result-based error handling system.

New files:
- error.rs: LlvmRunError type with code, msg, and convenience constructors
- report.rs: emit_error_and_exit() - single exit point for all LLVM errors

Changes:
- harness_executor.rs: Returns Result<i32, LlvmRunError> instead of Option<i32>
- pyvm_executor.rs: Returns Result<i32, LlvmRunError> instead of Option<i32>
- fallback_executor.rs: Returns Result<i32, LlvmRunError> instead of i32
- mod.rs: Updated all error handling to use report::emit_error_and_exit()

Benefits:
1. Unified error handling with Result<T, LlvmRunError>
2. Clear separation: Executors return errors, orchestrator handles exit
3. Single exit point guarantees leak report consistency
4. Reduced code duplication (20+ patterns consolidated)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-24 11:10:57 +09:00
13545fd57e refactor(llvm): Phase 286 - Modularize llvm.rs into 10 boxes
Following Phase 33 success pattern:
- Single responsibility per box
- Testability through isolated boxes
- Reusability across backends

Before: 449 lines monolithic function
After: 229 line orchestrator + 10 focused boxes

Boxes created:
- plugin_init.rs (plugin initialization)
- using_resolver.rs (using/prelude handling)
- mir_compiler.rs (AST → MIR compilation)
- method_id_injector.rs (method_id injection)
- joinir_experiment.rs (JoinIR experiment, feature-gated)
- pyvm_executor.rs (PyVM harness, dev/test)
- object_emitter.rs (LLVM object emit)
- harness_executor.rs (LLVM harness execution)
- exit_reporter.rs (leak report, Phase 285LLVM-0)
- fallback_executor.rs (mock/legacy execution)

Test Results:
-  cargo build --release
-  cargo build --release --features llvm
-  18 VM/LLVM parity tests PASS
-  No regressions

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 10:45:17 +09:00
6b64e6415c docs(phase-286): Add complete llvm.rs modularization instructions
Created comprehensive, self-contained instructions for modularizing
llvm.rs (449 lines → 10 boxes + orchestrator), following Phase 33
success pattern.

Contents:
- Background & current problems (12 responsibilities in 1 function)
- Phase 33 success case reference
- Detailed box design (10 boxes with responsibilities/inputs/outputs)
- Step-by-step implementation guide (staged migration)
- Acceptance criteria (build/test requirements)
- Important warnings (PyVM preservation, feature-gated code)

Box breakdown:
1. plugin_init.rs - Plugin initialization
2. using_resolver.rs - Using/prelude handling
3. mir_compiler.rs - AST → MIR compilation
4. method_id_injector.rs - method_id injection
5. joinir_experiment.rs - JoinIR experiment (feature-gated)
6. pyvm_executor.rs - PyVM harness (dev/test, MUST PRESERVE)
7. object_emitter.rs - LLVM object emit
8. harness_executor.rs - LLVM harness execution
9. exit_reporter.rs - Leak report (Phase 285LLVM-0)
10. fallback_executor.rs - Mock/legacy execution

Expected improvements:
- Code quality: 449 lines → 150-200 orchestrator + 10 focused boxes
- Testability: Each box independently testable
- Reusability: Boxes reusable across backends
- Maintainability: Single responsibility per box

CRITICAL: PyVM executor (pyvm_executor.rs) MUST be preserved
- Used by 8 JSON AST smoke tests
- NOT removable legacy code

Ready for handoff to other AI (ChatGPT, etc.) for implementation.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 10:08:40 +09:00
af99ccab91 feat(llvm): Phase 285LLVM-0 - LLVM Conformance One-Pass
Step 0: SSOT/Reality Alignment
- Update Feature Matrix (lifecycle.md):
  - WeakRef: "285A1" → "285LLVM-1"
  - Leak Report: "partial" → "Parent process roots only (285LLVM-0)"
  - Add detailed LLVM limitation explanation
- Update SKIP reason (phase285_weak_basic_llvm.sh): "285A1" → "285LLVM-1"

Step 1: LLVM Leak Report Implementation
- Add emit_leak_report() calls to llvm.rs (success + error paths)
- Create phase285_leak_report_llvm.sh smoke test (3 test cases PASS)
- Add NYASH_LEAK_LOG documentation to environment-variables.md
- Manual test: All 3 cases PASS (no-log, LEVEL=1, LEVEL=2)
- Smoke test: 3/3 PASS

Step 2: WeakRef Design Preparation
- Create phase-285llvm-1-design.md
  - Runtime representation candidate (Option B with caveat)
  - FFI signatures definition
  - Implementation checklist
  - Test strategy
  - NO CODE IMPLEMENTATION (design-only phase)

Implementation:
- Minimal 10-20 line code change (as planned)
- Reuses existing leak_tracker.rs infrastructure
- LLVM limitation transparently documented
- Exit codes unchanged (0/1 preserved)
- Fixture SSOT: apps/tests/*.hako shared between VM/LLVM

Test Results:
-  Manual test: 3/3 cases PASS
-  Smoke test: 3/3 cases PASS
-  No regressions

Files Changed:
- src/runner/modes/llvm.rs (2 emit_leak_report() calls)
- docs/reference/language/lifecycle.md (Feature Matrix + LLVM limitation)
- docs/reference/environment-variables.md (NYASH_LEAK_LOG entry)
- tools/smokes/v2/profiles/quick/lifecycle/phase285_weak_basic_llvm.sh (SKIP reason)

Files Added:
- tools/smokes/v2/profiles/quick/lifecycle/phase285_leak_report_llvm.sh
- docs/development/current/main/phases/phase-285/phase-285llvm-1-design.md

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 09:58:00 +09:00
f9c21ea601 test(env): Phase 286A - Deprecated env warning regression test
Goal: Prevent regression where deprecated env vars warn even when unset

Changes:
- tools/smokes/v2/profiles/quick/env/phase286_deprecated_env_warnings.sh
  * Test Case 1: Unset env → No warnings (防止: 未設定で警告)
  * Test Case 2: NYASH_MACRO_TOPLEVEL_ALLOW=1 → Warning expected
  * Test Case 3: NYASH_MACRO_BOX_CHILD_RUNNER=1 → Warning expected
  * Uses env -u to truly unset variables (empty string counts as "set")

- docs/reference/environment-variables.md
  * Added "Deprecated 警告動作 (Phase 286A)" section
  * Clarified: warnings only appear when env var is explicitly set
  * Warning format: [macro][compat] <変数名> is deprecated; <推奨アクション>

Test Results:
 All 3 test cases pass
 Quick smoke: 45/46 tests pass (1 known failure unrelated)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 09:14:33 +09:00
80f3403049 refactor(config): Phase 286A/B/287 - Config system consolidation
Phase 286A: Macro environment variable consolidation
- src/config/env/macro_flags.rs: NYASH_MACRO_* flags centralized
- Removed duplicate ny_compiler_* functions (keep in selfhost_flags.rs)
- Fixed deprecation warning logic (return None when env var not set)
- Updated callers: src/macro/{ctx,engine,macro_box,macro_box_ny,mod}.rs

Phase 286B: Box Factory environment variable consolidation
- src/config/env/box_factory_flags.rs: NYASH_BOX_FACTORY_* flags centralized
- Updated callers: src/box_factory/mod.rs, src/runtime/plugin_loader*.rs

Phase 287: Config Catalog implementation
- src/config/env/catalog.rs: New catalog for all config modules

Fixes:
- Type mismatches: Added .unwrap_or(false) for Option<bool> returns (7 locations)
- Deprecation warnings: Fixed macro_toplevel_allow() & macro_box_child_runner() logic
- Module organization: Added module declarations in src/config/env.rs

Note: Files force-added with git add -f due to .gitignore env/ pattern

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 08:43:48 +09:00
ab76e39036 feat(parser): Phase 285A1.4 & A1.5 - Weak field sugar + Parser hang fix
A1.4: Add sugar syntax `public weak parent` ≡ `public { weak parent }`
A1.5: Fix parser hang on unsupported `param: Type` syntax

Key changes:
- A1.4: Extend visibility parser to handle weak modifier (fields.rs)
- A1.5: Shared helper `parse_param_name_list()` with progress-zero detection
- A1.5: Fix 6 vulnerable parameter parsing loops (methods, constructors, functions)
- Tests: Sugar syntax (OK/NG), parser hang (timeout-based)
- Docs: lifecycle.md, EBNF.md, phase-285a1-boxification.md

Additional changes:
- weak() builtin implementation (handlers/weak.rs)
- Leak tracking improvements (leak_tracker.rs)
- Documentation updates (lifecycle, types, memory-finalization, etc.)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 07:44:50 +09:00
a47f850d02 feat(parser): Phase 285A1.3 - Unify weak field parsing into fields.rs
Unified weak modifier parsing logic into fields.rs for extensibility.

Changes:
- fields.rs: Add weak handling in visibility block parser (~40 lines)
  - parse_weak_field() unified function for all weak parsing
  - Visibility block now supports "public { weak parent }" syntax
- mod.rs: Delegate WEAK parsing to fields.rs (thin wrapper)
  - Removed inline processing, now calls parse_weak_field()

Tests:
- phase285_weak_visibility_block.hako - public { weak parent }
- phase285_weak_mixed_members.hako - weak + method + visibility

Results:
- All 6 existing Phase 285A1 tests pass
- All 2 new tests pass
- Smoke tests: 46 PASS, 1 FAIL (pre-existing, unrelated)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 06:42:11 +09:00
dac57ec350 refactor(cleanup): Large-scale dead code elimination (Task 5)
Removed 966 lines of dead code identified by Rust compiler warnings.
4 files completely deleted, multiple pattern implementations cleaned up.

**Files Completely Deleted (4)**:
- src/mir/builder/control_flow/joinir/api/entry.rs (15 lines)
- src/mir/builder/control_flow/joinir/api/pipeline_contracts.rs (17 lines)
- src/mir/builder/control_flow/joinir/api/receiver.rs (21 lines)
- src/mir/builder/control_flow/joinir/patterns/pattern2_steps/promote_step_box.rs (33 lines)

**Pattern 7 (SplitScan) - 423 lines deleted**:
- Removed: can_lower(), lower(), cf_loop_pattern7_split_scan_impl()
- Removed helper functions: contains_methodcall(), contains_variable_step(), contains_push()
- Removed test code
- Kept: extract_split_scan_plan() (used by router.rs)

**Pattern 8 (BoolPredicate) - 222 lines deleted**:
- Removed: cf_loop_pattern8_bool_predicate_impl() (impl MirBuilder block)
- Kept: can_lower(), lower() (used by router.rs)

**Pattern 5 (InfiniteEarlyExit) - 95 lines deleted**:
- Removed: count_breaks_and_continues(), validate_continue_position(), validate_break_pattern()

**Pattern 6 (ScanWithInit) - 110 lines deleted**:
- Removed: contains_methodcall(), is_const_step_pattern()
- Removed 4 test functions

**JoinIR API - 53 lines deleted**:
- Removed module: api/entry.rs
- Removed module: api/pipeline_contracts.rs
- Removed module: api/receiver.rs

**EdgeCFG API - 30 lines deleted**:
- EdgeStub: Removed new(), with_target() methods

**Statistics**:
- Total lines deleted: 966
- Files deleted: 4
- Dead code warnings eliminated: Multiple pattern implementations

Build Status:  Release build successful (0 errors)

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 04:49:52 +09:00
f1ff305c08 refactor(cleanup): Remove unused BindingContext methods
Removed dead code from BindingContext after analysis of actual usage:

**Deleted Methods (3)**:
- contains() - never used
- len() - never used
- is_empty() - never used

**Feature Gate Fix**:
- binding_map(): Added #[cfg(feature = "normalized_dev")]
  - Method only used within normalized_dev feature gates
  - Prevents "never used" warning in standard builds

**Analysis**:
BindingContext is actively used via:
- lookup() - variable name to BindingId resolution
- insert() - variable registration
- remove() - variable removal
- binding_map() - internal map access (normalized_dev only)

Files using binding_ctx:
- vars/lexical_scope.rs (5 usages)
- pattern3_with_if_phi.rs (2 usages)
- pattern4_with_continue.rs (2 usages)
- trim_loop_lowering.rs (2 usages)
- pattern2_inputs_facts_box.rs (1 usage)

**Result**: All BindingContext dead_code warnings eliminated

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 04:18:24 +09:00
2da730de35 refactor(cleanup): Phase 285A1 Post-Implementation Cleanup
Code quality improvements after Phase 285A1 implementation:

**Task 1: Dead Code Cleanup**
- Removed unnecessary #[allow(dead_code)] from emit_weak_load()
- Function is actively used in weak_to_strong() method handler

**Task 2: Unused Import Removal (cargo fix)**
- edgecfg/api/mod.rs: Removed seq, if_, loop_, cleanup, verify_frag_invariants
- pattern3.rs: Removed BinaryOperator
- pattern2/api/mod.rs: Removed PromoteStepResult
- jump.rs: Removed EffectMask, Span
- Result: 6 unused imports eliminated

**Task 3: Deprecated Pattern Removal**
- Fixed 4 PlanKind::LoopWithPost deprecated warnings
- Updated to Phase 142 P0 architecture (statement-level normalization)
- Files: normalized_shadow_suffix_router_box.rs, routing.rs,
  execute_box.rs, plan.rs
- Removed 2 deprecated tests: test_loop_with_post_*

**Task 4: WeakFieldValidatorBox Boxification**
- Extracted weak field validation logic into dedicated Box
- New file: src/mir/builder/weak_field_validator.rs (147 lines)
- fields.rs: 277 → 237 lines (-40 lines, -14.4%)
- Added 5 unit tests for validation logic
- Follows Phase 33 boxification principles (single responsibility,
  testability, reusability)

**Metrics**:
- Code reduction: -40 lines in fields.rs
- Test coverage: +5 unit tests
- Warnings fixed: 4 deprecated warnings
- Imports cleaned: 6 unused imports

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 03:44:56 +09:00
cc8b27a1aa feat(weak): Phase 285A1 - Weak Field Contract (Strict Type Enforcement)
Remove automatic WeakNew conversion and enforce strict compile-time type
checking for weak field assignments. Only 3 assignment types allowed:
1. Result of weak(x) call (WeakRef type)
2. Existing WeakRef variable (e.g., me.parent = other.parent)
3. Void/null (clear operation)

**Implementation**:
- Added MirType::WeakRef to type system (src/mir/types.rs)
- Track WeakRef type in emit_weak_new() even in pure mode
- Weak field reads return WeakRef without auto-upgrade
- Removed automatic WeakNew conversion from field writes
- Implemented check_weak_field_assignment() with actionable errors
- Fixed null literal type tracking (Phase 285A1.1: Unknown → Void)

**Testing**:
- 5 test fixtures (3 OK, 2 NG cases) - all passing
- Smoke test: phase285_weak_field_vm.sh
- Error messages guide users to use weak() or null

**Documentation**:
- Updated lifecycle.md SSOT with weak field contract

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 03:17:30 +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
41d92bedb9 refactor(extractors): Phase 282 P9a - CommonExtractionHelpers SSOT統合(スコープ限定版)
# Phase 282 P9a 完了 (Scope-Limited Integration)

## 実装内容
- **common_helpers.rs 作成**: 4グループの共通ヘルパー統合 (316行)
  - Group 1: Control Flow Counting (count_control_flow - 汎用カウンター)
  - Group 2: Control Flow Detection (has_break/continue/return_statement)
  - Group 3: Condition Validation (extract_loop_variable, is_true_literal)
  - Group 4: Pattern5専用ヘルパー (validate_continue_at_end, validate_break_in_simple_if)

- **Pattern統合完了**: Pattern5 → Pattern4 → Pattern2 → Pattern1
  - Pattern5: ~90行削減 (5 tests PASS)
  - Pattern4: ~66行削減 (5 tests PASS)
  - Pattern2: ~67行削減 (4 tests PASS)
  - Pattern1: ~28行削減 (3 tests PASS)
  - Pattern3: 別フェーズに延期(pattern固有ロジック除外)

## 成果
- **コード削減**: ~251行(Pattern3除く、total ~400行見込み)
- **テスト**: 40 unit tests PASS (23 common_helpers + 17 extractors)
- **スモークテスト**: 45 PASS, 1 pre-existing FAIL(退行ゼロ)
- **ビルド警告**: 130 → 120 (-10)

## USER CORRECTIONS適用済み
1.  スコープ限定(共通ロジックのみ、pattern固有除外)
2.  Placeholder禁止(SSOT違反排除)
3.  統合順序変更(Pattern3を最後/別フェーズへ)

## 追加ドキュメント
- Phase 284 計画追加(Return as ExitKind SSOT)
- 10-Now.md, 30-Backlog.md 更新

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 11:14:28 +09:00
bf6f4faa1f test(smoke): Phase 283 P0 - Add VM/LLVM smoke tests + doc update
- VM smoke: phase283_p0_loop_if_phi_vm.sh (checks sum=9 output)
- LLVM smoke: phase283_p0_loop_if_phi_llvm.sh (checks Result: 0, exit=0)
- Documentation: Update phase-283 README with LLVM harness notes
  - LLVM harness suppresses program stdout
  - VM shows stdout, LLVM checks exit code only

Both tests verified:  PASS

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 08:34:19 +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
32ccccd272 feat(plan): Phase 282 P5 - Pattern3 ExtractionBased Migration & Classification
- Pattern3 extraction logic separated to extractors/pattern3.rs
- ExtractionBased strategy: pure functions, Fail-Fast, SSOT
- Pattern classification restored (AST-based pattern detection)
- Pattern1 extractor migrated (extractors/pattern1.rs)
- Documentation: phase-282 README updated, joinir-architecture updated

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 08:13:47 +09:00
c3fb3c5833 feat(joinir): Phase 282 P4 - Pattern2 ExtractionBased Migration
## Summary
Migrated Pattern2 (Loop with Conditional Break) from StructureBased to ExtractionBased detection following Pattern1 template (P3). Safety valve + extraction SSOT strategy with zero regression.

## Implementation
- **extractors/pattern2.rs**: 4-phase validation (condition, HAS break, NO continue/return, extraction)
- **pattern2_with_break.rs**: Updated can_lower() (safety valve + extraction) and lower() (re-extraction + ctx.skeleton)
- **extractors/mod.rs**: Registered pattern2 module

## Key Design Decisions
- **Lightweight Parts**: loop_var (String), is_loop_true (bool), break_count (usize) - no AST duplication
- **4-Phase Validation**: Lightweight checks only (condition, break presence, continue/return absence, extraction)
- **Hybrid loop(true) Handling**: Quick detection in extractor, deep validation in can_lower() via LoopTrueCounterExtractorBox
- **SSOT Carrier Validation**: Deferred to CommonPatternInitializer in can_lower() (Step 4)
- **ctx.skeleton Usage**: Re-uses existing ctx.skeleton instead of new env var (避けenv増殖)

## Testing Results
-  Unit tests: 4/4 PASS (extractors::pattern2)
-  Build: 0 errors
-  Regression: 46/49 PASS (zero regression, 1 unrelated pre-existing failure)
- ⚠️ Pattern2 smoke test: Pre-existing PHI bug confirmed (not a regression)

## Migration Template
This implementation provides a template for Pattern3-5 ExtractionBased migration:
1. Lightweight Parts structure (validation results only)
2. 4-phase extraction validation
3. Safety valve (pattern_kind) + extraction (SSOT)
4. Re-extraction in lower() (no caching)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:49:49 +09:00
8d0808b6d4 feat(joinir): Phase 282 P3 - Pattern1 ExtractionBased Migration
Migrated Pattern1 (Simple While Loop) from StructureBased to ExtractionBased
detection, creating a migration template for Pattern2-5.

**Changes**:
1. Created extractors/mod.rs - Module entry point with design principles
2. Created extractors/pattern1.rs - Pure extraction functions with 4-phase validation
3. Updated pattern1_minimal.rs - can_lower() + lower() use extraction
4. Updated mod.rs - Registered extractors module

**Pattern1Parts Design** (Lightweight):
- Stores only loop_var (AST reused from ctx, no heavy copies)
- Validation: 比較条件 + no break/continue/if-else + 単純step (i = i ± const)
- Return statements allowed (not loop control flow)

**4-Phase Validation**:
1. Validate condition structure (比較演算, left=variable)
2. Validate body (no break/continue/if-else-phi)
3. Validate step pattern (simple i = i ± const only)
4. Extract loop variable

**Safety Valve Strategy**:
- pattern_kind as O(1) early rejection guard
- Extraction as SSOT authoritative check
- Re-extraction in lower() (no caching from can_lower)

**Testing**:
- Unit tests: 3/3 PASS
- Build: 0 errors
- Regression: 45/46 PASS (zero regression)

**Migration Template**:
- Result<Option<Parts>, String> return type (Pattern8/9 model)
- Pure functions (no builder mutations)
- Fail-Fast error handling (Err for logic bugs, Ok(None) for non-matches)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:09:57 +09:00
a2be79b875 docs(router): Phase 282 P2 - Comment archaeology + TODO cleanup
Step 2: Router comment updates
- Update Phase references (183, 273, 282 retained)
- Document ExtractionBased status (Pattern8/9 already done)
- Remove obsolete Phase references (187, 193, 195)

Step 3: TODO cleanup
- pattern5: Remove completed TODO (lowering fully implemented)
- pattern_pipeline: Clarify loop_update_summary status (reserved)
- apply_policy: Mark current_static_box_name as low-priority refactor

Step 4: Pattern3 legacy references
- Simplify module docstring (remove legacy mode details)
- Update inline comments (legacy removal Phase 242-EX-A)

Changes: Comment/docstring only (zero behavior change)
Test: cargo build --release (0 errors)
2025-12-23 05:35:42 +09:00
519e58a977 docs(router): Phase 282 P0+P1 - Router shrinkage SSOT + entrypoint logging
P0: Documentation SSOT (~80 lines added)
- Router Responsibilities SSOT (DOES/DOESN'T split)
- Ok(None)/Err boundary rules (Fail-Fast principle)
- Entrypoint table (Plan/JoinIR/None, 収束先明記)
- Pattern番号 = 症状ラベル定義(最小記述)

P1: Minimal Code (~10 lines)
- 4 trace statements modified (router.rs)
- Entrypoint-based logging (route=plan/joinir/none)
- Pattern names preserved (backward compatible)
- No new environment variables (既存trace機構のみ)

Test Results:
- quick profile: 45 PASS / 1 FAIL (既知failure)
- Pattern6 VM: PASS (phase258_p0_index_of_string_vm.sh)
- Pattern6 LLVM: PASS (phase258_p0_index_of_string_llvm_exe.sh)
- Zero regression 

Phase 282 Goal Achieved:
- Router shrinkage complete (SSOT positioning clear)
- Pattern numbers → symptom labels transition documented
- CFG construction converges to emit_frag() SSOT
2025-12-23 05:03:25 +09:00
a744be929a feat(edgecfg): Phase 281 P3 - cleanup Normal wiring + docs 2025-12-23 04:11:02 +09:00
2d5607930c docs(edgecfg): Phase 280 - Frag Composition SSOT Positioning (A→B→C)
## Purpose

Stop pattern number enumeration proliferation by establishing Frag composition API
as the Single Source of Truth (SSOT) for structured control flow → CFG lowering.

Pattern numbers (1-9+) are **symptom labels** for regression tests, NOT architectural
concepts. The architectural SSOT is **Frag composition rules** (seq/if/loop/cleanup).

## Changes Summary

**Phase A (Docs-only, no code)**: SSOT Positioning
- edgecfg-fragments.md: Status Draft → Active SSOT (+243 lines)
  - Added 5 sections: Composition SSOT, Rules, Laws, Fail-Fast, Ownership
  - Documented 3-tier ownership model (Normalizer/Composition/Lowerer)
  - Established composition as pattern absorption destination
- joinir-architecture-overview.md: Pattern absorption documentation (+90 lines)
  - Added Section 0.2: Pattern Number Absorption Destination
  - JoinIR vs Plan comparison (different extraction, same SSOT)
  - Pattern absorption status table (Pattern6/7 as Phase 280 targets)
- phase-280/README.md: Full roadmap (new)

**Phase B (API solidification)**: Contract Verification
- compose.rs: Module-level + function-level Phase 280 docs (+149 lines)
  - Documented composition SSOT, ownership model, usage example
  - Added constraint/composition law sections to seq/if/loop/cleanup
  - Contract verification: All seq/if/loop contracts verified (no gaps)
  - Test gap analysis: No missing tests (wires/exits separation explicitly tested)

**Phase C (Pattern preparation)**: Documentation-only
- normalizer.rs: Pattern6/7 TODO comments (+10 lines)
  - Pattern6: Early exit doesn't fit compose::if_() → cleanup() target
  - Pattern7: 挙動不変保証難 → compose::if_() migration deferred to Phase 281

## Impact

- **Net +460 lines** (docs-heavy, minimal code)
- **4 files modified**, 1 directory created
- **SSOT established**: Frag composition is now THE absorption destination
- **導線固定**: Clear migration path for Pattern6/7 (Phase 281+)
- **No behavior change**: Documentation-only for Phase C (tests not run)

## Phase 280 Goal Achieved

 SSOT positioning + 導線固定 (NOT full migration - that's Phase 281)
 Phase A complete: Docs updated to "Active SSOT"
 Phase B complete: API contract verified and documented
 Phase C complete: Pattern6/7 hand-rolled locations documented

## Next Phase (Phase 281+)

- Phase 281: Full Pattern6/7 absorption (replace hand-rolled with compose_*)
- Phase 282: Router shrinkage (pattern numbers → test labels)
- Phase 283+: Pattern8 and beyond

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 01:18:36 +09:00
6f1d0df187 docs(plan): Phase 273 P4 - Plan Line SSOT Documentation Finalization
Phase 273 P4 では、Plan ライン(Extractor → Normalizer → Verifier → Lowerer)を
"current operational SSOT" として文書化し、アーキテクチャの収束を明文化した。

## Changes

### router.rs docstring 更新
- "Phase 273 P3: Plan Line is Current SSOT for Pattern6/7" セクション追加
- ルーティング戦略を明示(Plan entry points → legacy table)
- SSOT Entry Points を列挙(Pattern6/7 Normalizer, Pattern1-5 各 Lowerer)

### phase-273/README.md 更新
- P3 completion section 追加(generalized CoreLoopPlan 移行完了)
- P3+ Legacy Removal section 追加(~174 lines 削除記録)
- P4 Proposal section 追加(Documentation Finalization チェックリスト)
- SSOT Documentation Entry Points リスト追加(5 つの SSOT 入口)

### joinir-architecture-overview.md 更新
- Section 2.1.2 "Plan-Based Patterns (Pattern6-7, Phase 273 P3)" 追加
- Plan Extractor, Normalizer, Verifier, Lowerer の Box 構造を文書化
- Plan line vs JoinIR line 比較表追加(収束性・SSOT 特性の対比)
- SSOT characteristics リスト追加(Normalizer SSOT, emit_frag SSOT 等)

## SSOT Entry Points(Phase 273 P3 完了時点)

1. **ルーティング**: `router.rs::route_loop_pattern()` - Pattern6/7 Plan entry points
2. **型定義**: `plan/mod.rs` - DomainPlan/CorePlan 固定語彙
3. **正規化**: `plan/normalizer.rs` - Pattern 固有知識一元管理
4. **検証**: `plan/verifier.rs` - fail-fast 不変条件(V2-V9)
5. **降格**: `plan/lowerer.rs` - Pattern-agnostic MIR emission

## Test

-  VM regression: phase254_p0_index_of_vm.sh (PASS)
-  LLVM regression: phase258_p0_index_of_string_llvm_exe.sh (PASS)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 00:34:38 +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
0664526d99 feat(plan): Phase 273 P3 - Plan Lowering SSOT Finalize
Phase 273 P3 完成: CoreLoopPlan SSOT 化、legacy fallback 撤去

Changes:
- CoreLoopPlan: Option<...> → 必須フィールド化(構造で "揺れ" を消す)
  - block_effects, phis, frag, final_values が必須に
  - legacy fields 削除 (header_effects, step_effects, carriers, loop_var_name)
- Lowerer: lower_loop_legacy() 撤去、generalized 経路のみ
  - emit_scan_with_init_edgecfg() 参照が完全に消えた
- Normalizer: Pattern6/7 両方が generalized fields のみを使用
- Verifier: generalized 専用の不変条件追加 (V7-V9)
  - V7: PHI non-empty
  - V8: frag.entry == header_bb
  - V9: block_effects contains header_bb

Acceptance Criteria:
-  Lowerer から pattern 固有参照が消えている
-  Pattern6/7 が generalized CoreLoopPlan を使用
-  legacy fallback 撤去、欠落時は型エラー (Fail-Fast)
-  VM テスト PASS (phase254/256/258)
-  LLVM テスト 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:01:58 +09:00
e4b5a8e832 feat(plan): Phase 273 P2 Step 3-6 - Pattern7 (SplitScan) to Plan line
Migrate Pattern7 from legacy lowering to Plan architecture:

DomainPlan (mod.rs):
- Added SplitScan(SplitScanPlan) variant
- SplitScanPlan: s_var, sep_var, result_var, i_var, start_var

Extractor (pattern7_split_scan.rs):
- extract_split_scan_plan() returning DomainPlan
- Reuses existing extract_split_scan_parts()

Router (router.rs):
- Pattern7 now uses Plan line (Normalize→Verify→Lower)
- Removed from LOOP_PATTERNS table

Normalizer (normalizer.rs):
- normalize_split_scan() - 400+ lines migrated from impl
- 6 blocks: preheader/header/body/then/else/step/after
- 4 PHIs: header(2) + step(2) for i/start carriers
- Side effect: push with EffectMask::MUT

Bug fixes:
- Pattern6 extractor returns Ok(None) for non-match (allows fallback)
- Reverse scan filtered early in extractor (P1 scope)

Tests:
- phase256_p0_split_vm: PASS (exit=3)
- phase258_p0_index_of_string_vm: PASS (exit=6)

Lowerer no longer contains "split" - pattern-agnostic achieved!

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 23:35:43 +09:00
d16800741f feat(plan): Phase 273 P2 Step 1-2 - CoreLoopPlan generalization
Generalize CoreLoopPlan for Pattern7+ support:

New structures (mod.rs):
- CorePhiInfo: PHI info with block, dst, inputs, tag
- CoreLoopPlan new optional fields:
  - block_effects: Vec<(BasicBlockId, Vec<CoreEffectPlan>)>
  - phis: Vec<CorePhiInfo>
  - frag: Frag (EdgeCFG)
  - final_values: Vec<(String, ValueId)>

Normalizer (normalizer.rs):
- Pattern6 now populates all new fields
- Frag construction matches emit_scan_with_init_edgecfg
- SSOT ordering: preheader → header → body → step

Lowerer (lowerer.rs):
- lower_loop() dispatches to generalized or legacy path
- lower_loop_generalized(): emit blocks → PHI → emit_frag()
- lower_loop_legacy(): backward compatible fallback

Test: phase258_p0_index_of_string_vm PASS (exit=6)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 23:18:51 +09:00
ec792983cc feat(plan): Phase 273 P2 Step 0 - CoreEffectPlan side effect support
Prepare CoreEffectPlan::MethodCall for Pattern7 (split) support:
- dst: ValueId → Option<ValueId> (for void methods like push)
- effects: EffectMask field added (PURE+Io vs MUT)

Changes:
- plan/mod.rs: MethodCall struct updated
- plan/lowerer.rs: emit_effect() uses dst/effects from plan
- plan/normalizer.rs: MethodCall with explicit effects
- plan/verifier.rs: Handle Option<ValueId> dst

Test: phase258_p0_index_of_string_vm PASS (exit=6)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 23:07:49 +09:00
960241795d feat(mir/llvm): Phase 273 P0-P1 DomainPlan→CorePlan + LLVM arg fix
Phase 273 P0-P1: Two-layer plan architecture
- DomainPlan: Pattern-specific knowledge (ScanWithInit)
- CorePlan: Fixed vocabulary (Seq, Loop, If, Effect, Exit)
- ValueId references only (String expressions forbidden)
- Pipeline: Extractor→Normalizer→Verifier→Lowerer

New plan/ module:
- mod.rs: Type definitions, SSOT spec
- normalizer.rs: DomainPlan→CorePlan + ID allocation
- verifier.rs: V1-V6 invariant checks (fail-fast)
- lowerer.rs: CorePlan→MIR (pattern-agnostic)

LLVM fix (ChatGPT):
- function_lower.py: Fix argument reference bug
- Phase 258 index_of_string now PASS on LLVM backend

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-22 22:42:56 +09:00
f07c2e7874 feat(mir): Phase 279 P0 - Type propagation pipeline SSOT unification
Eliminate "2本のコンパイラ" problem by unifying type propagation into single SSOT entry.

SSOT implementation:
- src/mir/type_propagation/pipeline.rs - SSOT type propagation pipeline
- TypePropagationPipeline::run() - Single entry point for all routes

Pipeline steps (fixed order):
1. Copy propagation (initial)
2. BinOp re-propagation (numeric promotion: Int+Float→Float)
3. Copy propagation (propagate promoted types)
4. PHI type inference (private step - cannot bypass)

Callers (both routes now use SSOT):
- lifecycle.rs::finalize_module() - Builder lifecycle route
- joinir_function_converter.rs::propagate_types() - JoinIR bridge route

Fail-fast guard (structural guarantee):
- PHI type inference is private step inside TypePropagationPipeline
- lifecycle.rs and joinir_function_converter.rs cannot call PhiTypeResolver directly
- Only public API: TypePropagationPipeline::run()
- Order drift is structurally impossible (private encapsulation)

Code reduction:
- ~500 lines of duplicate BinOp re-propagation logic removed
- 2 implementations consolidated into 1 SSOT

Files changed:
- New: src/mir/type_propagation/mod.rs
- New: src/mir/type_propagation/pipeline.rs (~300 lines)
- Modified: src/mir/mod.rs
- Modified: src/mir/builder/lifecycle.rs (~400 lines removed)
- Modified: src/mir/join_ir_vm_bridge/joinir_function_converter.rs (~100 lines removed)

Regression testing:
 Lifecycle route (VM backend): Phase 275 fixture
 JoinIR route (VM backend): loop_min_while.hako
 LLVM harness: Phase 275 fixture

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 15:34:03 +09:00
264940ef51 feat(llvm/phi): Phase 278 P0 - remove deprecated PHI debug env vars
## Changes
- debug_helper.py: Remove backward compatibility (warning → error + exit 1)
- environment-variables.md: Migrate deprecated section with migration guide
- phase278_p0_deprecated_env_fail.sh: Add smoke test for deprecated var detection

## Removed Variables (5)
- NYASH_LLVM_PHI_DEBUG
- NYASH_PHI_TYPE_DEBUG
- NYASH_PHI_ORDERING_DEBUG
- NYASH_LLVM_TRACE_PHI
- NYASH_LLVM_VMAP_TRACE

## SSOT Variables (3) - Unchanged
- NYASH_LLVM_DEBUG_PHI=1
- NYASH_LLVM_DEBUG_PHI_TRACE=1
- NYASH_LLVM_PHI_STRICT=1

## Benefits
-  Deprecated vars cause fail-fast error (not silent)
-  Error messages include replacement hints
-  Documentation reflects removal (migration guide included)
-  Smoke test verifies deprecated var rejection
-  No regressions in existing tests

## Testing
 Test 1: Deprecated NYASH_LLVM_PHI_DEBUG rejected
 Test 2: Deprecated NYASH_LLVM_TRACE_PHI rejected
 Test 3: SSOT vars work normally
 Regression tests: strict=OFF, strict=ON, debug mode - all pass

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 15:08:50 +09:00
939efbca9b feat(llvm/phi): Phase 277 P1.5 - structured error handling + import organization
## Changes
- P1.5.1: import整理 - debug_helper imports をモジュールトップへ移動
- P1.5.2: PhiStrictError 箱化 - エラーハンドリング構造化 (error_helpers.py新規)
- P1.5.3: wiring.py で PhiStrictError を使用 - 3箇所のエラーパターン統一

## Benefits
-  エラーメッセージ生成の一元化(SSOT化)
-  Python import 慣習準拠(関数内import削除)
-  エラーコンテキスト構造化(block_id/dst_vid/next_file)

## Testing
 strict=OFF - passes without errors
 strict=ON - passes without errors
 debug mode - verification connected and running

🤖 Generated with Claude Code

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-22 14:59:24 +09:00
757193891f feat(llvm/phi): Phase 277 P1 - fail-fast validation for PHI strict mode
## Summary
Implemented fail-fast validation for PHI ordering and value resolution in strict mode.

## Changes

### P1-1: Strict mode for "PHI after terminator"
- File: `src/llvm_py/phi_wiring/wiring.py::ensure_phi`
- Behavior: `NYASH_LLVM_PHI_STRICT=1` → RuntimeError if PHI created after terminator
- Default: Warning only (no regression)

### P1-2: Strict mode for "fallback 0"
- File: `src/llvm_py/phi_wiring/wiring.py::wire_incomings`
- Behavior: Strict mode forbids silent fallback to 0 (2 locations)
  - Location 1: Unresolvable incoming value
  - Location 2: Type coercion failure
- Error messages point to next debug file: `llvm_builder.py::_value_at_end_i64`

### P1-3: Connect verify_phi_ordering() to execution path
- File: `src/llvm_py/builders/function_lower.py`
- Behavior: Verify PHI ordering after all instructions emitted
- Debug mode: Shows " All N blocks have correct PHI ordering"
- Strict mode: Raises RuntimeError with block list if violations found

## Testing
 Test 1: strict=OFF - passes without errors
 Test 2: strict=ON - passes without errors (no violations in test fixtures)
 Test 3: debug mode - verify_phi_ordering() connected and running

## Scope
- LLVM harness (Python) changes only
- No new environment variables (uses existing 3 from Phase 277 P2)
- No JoinIR/Rust changes (root fix is Phase 279)
- Default behavior unchanged (strict mode opt-in)

## Next Steps
- Phase 278: Remove deprecated env var support
- Phase 279: Root fix - unify "2本のコンパイラ" pipelines

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 14:48:37 +09:00
6e749b791e feat(phase277-p0-p1-a1): 完全実装 - デッドコード削除+SSOT使用+Void検出
Phase 277 P0/P1 + Phase 275 A1 完全実装

【Task 1: Phase 277 P0 - box_from_f64 削除】
- kernel/lib.rs から2関数削除(デッドコード)
  - nyash.box.from_f64
  - nyash.float.box_from_f64
- 理由: Phase 275 Float SSOT化により unboxed double 採用

【Task 2: Phase 277 P1 - dst_type_to_llvm_type 使用推進】
- wiring.py の型変換ロジックを type_helper 経由に統一
- SSOT原則の完全適用(型変換ロジック1箇所に集約)

【Task 3: Phase 275 A1 - Void検出修正】
- branch.py の Void/VoidBox 検出ロジック強化
- エラーメッセージ追加(fail-fast原則)
- VM動作確認: TypeError("Void in boolean context")

【Task 4: LLVM smoke tests - 3本全部PASS】
- test_p275_debug.hako:  VM/LLVM parity (exit=3)
- test_p275_debug2.hako:  VM/LLVM parity (exit=3)
- test_p275.hako: ⚠️ String問題(Phase 275外)

【検証】
- ビルド成功: 0 errors 
- Float PHI完全動作: VM/LLVM parity達成 
- Void検出fail-fast: VMError確認 
- SSOT原則完全適用: 型変換統一 

【影響範囲】
- Kernel: 2関数削除(デッドコード)
- LLVM harness: 2ファイル(型変換SSOT + Void検出)
- ドキュメント: 10-Now.md更新

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 14:08:00 +09:00
03aa54a422 feat(phase277-p2): PHI環境変数統合 8個→3個 - ユーザビリティ向上
Phase 277 P2: PHI関連環境変数の統合・整理

【問題】
- PHI関連環境変数が8個に乱立
- ユーザーが覚える変数が多すぎる
- 保守性が低い(関連設定が分散)

【解決】
1. debug_helper.py 新規作成(SSOT)
   - is_phi_debug_enabled(): 一般デバッグ(3変数統合)
   - is_phi_trace_enabled(): 詳細トレース(2変数統合)
   - is_phi_strict_enabled(): 厳格モード(既存維持)

2. 環境変数統合(8個→3個)
   統合後:
   - NYASH_LLVM_DEBUG_PHI: 一般PHIデバッグ
   - NYASH_LLVM_DEBUG_PHI_TRACE: 詳細トレース
   - NYASH_LLVM_PHI_STRICT: 厳格モード(既存維持)

   統合前(廃止予定):
   - NYASH_LLVM_PHI_DEBUG → NYASH_LLVM_DEBUG_PHI
   - NYASH_PHI_TYPE_DEBUG → NYASH_LLVM_DEBUG_PHI
   - NYASH_PHI_ORDERING_DEBUG → NYASH_LLVM_DEBUG_PHI
   - NYASH_LLVM_TRACE_PHI → NYASH_LLVM_DEBUG_PHI_TRACE
   - NYASH_LLVM_VMAP_TRACE → NYASH_LLVM_DEBUG_PHI_TRACE

3. 後方互換性対応
   - 旧環境変数使用時に非推奨警告表示
   - Phase 278 で削除予定

【効果】
-  ユーザビリティ向上: 覚える変数 8個→3個(62%削減)
-  保守性向上: 環境変数チェック 30+箇所→1箇所(SSOT)
-  ドキュメント簡潔化: environment-variables.md 整理
-  SSOT原則適用: debug_helper.py に環境変数ロジック集約

【影響範囲】
- 新規: debug_helper.py (SSOT)
- 修正: 9ファイル(PHI関連Python)
- ドキュメント: environment-variables.md, 10-Now.md

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 13:57:33 +09:00
9a76a199ee feat(phase276-p0): Quick Win improvements - type helper SSOT + debug cleanup
Phase 276 P0 post-Phase 275 robustness improvements:

1. Debug cleanup (wiring.py L100-103):
   - Remove traceback.format_stack() output
   - Cleaner debug logs after Phase 275 completion

2. box_from_f64 usage investigation:
   - Confirmed ZERO usage (Rust/Python/MIR)
   - Ready for deletion (Phase 275 unboxed double SSOT)
   - crates/nyash_kernel/src/lib.rs L244-252, L971-982

3. Type resolution SSOT ( most important):
   - New file: src/llvm_py/phi_wiring/type_helper.py (72 lines)
   - Unified 3 duplicate logic sites:
     * tagging.py: inst.get("dst_type") → type_helper.get_phi_dst_type()
     * llvm_builder.py: 9 lines → 2 lines (-7)
     * wiring.py: 18 lines → 5 lines (-13)
   - Priority: MIR JSON dst_type > resolver.value_types
   - Benefits: SSOT principle, bug prevention, easy extension

4. Type mismatch warning enhancement (wiring.py L63-79):
   - CRITICAL warning for predeclared PHI type mismatch
   - PhiManager.invalidate_phi() notification
   - Early bug detection with ⚠️  marker

Effects:
- Type resolution logic: 3 sites → 1 SSOT (type_helper.py)
- Code reduction: -20 lines duplicate logic
- Robustness: SSOT principle, CRITICAL warnings, Fail-Fast
- Debuggability: cleaner logs, prominent type mismatch alerts

Testing:
- LLVM harness: exit=3 verified (/tmp/test_p275_debug2.hako)
- NYASH_PHI_TYPE_DEBUG=1: correct type resolution confirmed

Docs:
- Phase 276 P0 completion: docs/.../phase-276/P0-COMPLETION.md
- 10-Now.md: Phase 276 P0 , Phase 275 P0 completed section

Next steps (Phase 277 P0 recommended):
- Delete box_from_f64 (nyash.box.from_f64, nyash.float.box_from_f64)
- Adopt dst_type_to_llvm_type() helper

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 13:39:55 +09:00
60cffb1948 feat(phase275-p0): Float型PHI完全対応 - MIR型伝播→LLVM IR生成
Phase 275 P0: Float型PHIノードの完全実装

【問題】
- PHI v36 が i64 型で生成されるが、incoming value v12 が f64 型
- LLVM IR parsing error: 型不一致により実行失敗

【解決】
1. MIR型伝播順序修正 (lifecycle.rs)
   - BinOp repropagation → PHI resolution に変更
   - Int+Float → Float promotion を PHI推論前に実行

2. MIR JSON Float型出力 (mir_json_emit.rs)
   - PHI dst_type に Float case 追加(2箇所)

3. LLVM PHI型対応 (wiring.py, tagging.py, llvm_builder.py)
   - ensure_phi に dst_type パラメータ追加
   - f64 の場合 ir.DoubleType() PHI 生成
   - 型互換性チェック付き predeclared PHI 再利用

4. LLVM Float演算対応
   - compare.py: ensure_double helper (Float unboxing for fcmp)
   - binop.py: Int+Float → sitofp→fadd (unboxed double)

【検証】
- LLVM IR: phi double [%"float_int_add", %"bb0"] 
- VM/LLVM parity: exit=3 
- PHI duplicate 解消: 型チェックで再利用 

【影響範囲】
- Rust MIR builder: 3ファイル (型伝播ロジック)
- LLVM harness: 5ファイル (PHI型対応)
- Kernel: 1ファイル (box_from_f64 helper - 予備)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 13:31:53 +09:00
f071b4cc3c refactor(joinir): Eliminate call instruction generation duplication
Problem:
- 3 duplicate call instruction patterns
- Lines ~404-417 (handle_call non-tail)
- Lines ~506-518 (exit block tail call)
- Lines ~530-540 (unconditional jump tail call)

Solution:
- Use existing call_generator.rs helpers
- emit_call_pair() for current_instructions (no separate spans)
- emit_call_pair_with_spans() for BasicBlock with spans

Result:
-  ~15 lines eliminated (3 duplicate patterns removed)
-  Tests pass, no regression
-  Cleaner handle_jump implementation

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 04:15:37 +09:00
f7437957b7 refactor(joinir): Eliminate merge variable copy duplication
Problem:
- 4 duplicate merge variable copy patterns
- Lines ~652-660, 667-675, 785-791, 800-806

Solution:
- Use existing merge_variable_handler.rs
- Unified merge copy emission with emit_merge_copies()
- MergeBranch enum (Then/Else) for branch selection

Result:
-  ~20 lines eliminated (4 duplicate loops removed)
-  Tests pass, no regression
-  Cleaner handle_select implementation

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 04:12:52 +09:00
3cdeb95cbc refactor(joinir): Eliminate block allocation duplication with BlockAllocator
Problem:
- joinir_block_converter.rs had 4 duplicate block allocation patterns
- Lines 260-265, 487-489, 635-639, 740-748 all manually allocating BasicBlockIds
- Total duplication: 27 lines across 4 sites

Solution:
- Use existing BlockAllocator (Phase 260 P0.2) for all block allocations
- Replace manual patterns with allocate_two(), allocate_three(), allocate_n()

Changes:
- Site 1/4 (handle_conditional_method_call): 6 lines → 3 lines (-3)
- Site 2/4 (handle_jump): 4 lines → 3 lines (-1)
- Site 3/4 (handle_if_merge): 6 lines → 3 lines (-3)
- Site 4/4 (handle_nested_if_merge): 11 lines → 8 lines (-3)

Result:
-  10 lines eliminated
-  Improved readability (clear intent)
-  Improved maintainability (SSOT for allocation)
-  No behavior change (all tests pass)
-  No regression: phase269_p1_2, phase259_p0, phase269_p0 PASS

Follow-up potential:
- MergeVariableHandlerBox duplication (lines 652-660, 667-675, 785-791, 800-806)
- CallInstructionGeneratorBox duplication (lines 403-406, 511-514, 536-546)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 03:58:12 +09:00
4ef2261e97 fix(joinir): Phase 269 P1.2 - static call normalization for this.method()
Problem:
- `this.method()` calls in static box loops were using string constant "StringUtils" as receiver
- This violated Box Theory (static box this should not be runtime object)
- Pattern8 was trying to pass receiver to JoinIR, causing SSA/PHI issues

Solution (3-part fix):
1. **MeResolverBox Fail-Fast** (stmts.rs): Remove string fallback, error message cleanup
2. **ReceiverNormalizeBox** (calls/build.rs): Normalize `this/me.method()` → static call at compile-time
3. **Pattern8 Skip Static Box** (pattern8_scan_bool_predicate.rs): Reject Pattern8 for static box contexts

Key changes:
- **stmts.rs**: Update error message - remove MeBindingInitializerBox mentions
- **calls/build.rs**: Add This/Me receiver check, normalize to static call if current_static_box exists
- **calls/lowering.rs**: Remove NewBox-based "me" initialization (2 locations - fixes Stage1Cli regression)
- **pattern8_scan_bool_predicate.rs**: Skip Pattern8 for static boxes (use Pattern1 fallback instead)

Result:
-  phase269_p1_2_this_method_in_loop_vm.sh PASS (exit=7)
-  No regression: phase259_p0_is_integer_vm PASS
-  No regression: phase269_p0_pattern8_frag_vm PASS
-  Stage1Cli unit tests PASS
-  MIR uses CallTarget::Global, no const "StringUtils" as receiver

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 03:33:30 +09:00
5f891b72ad docs(phase269): document P1 completion - SSA fix and type annotation
- Update 10-Now.md: Phase 269 P1 complete (SSA + type SSOT)
- Update 30-Backlog.md: Add P1.2 investigation task
- Update phases/phase-269/README.md: Document P1.0 and P1.1 details

Phase 269 P1 achievements:
- Pattern8 SSA correctness with PHI nodes
- call_method return type SSOT propagation
- Module signature as single source of truth

Known issue: this.method() in loops (pre-existing, tracked as P1.2)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 01:41:34 +09:00
5f22fe8fcd feat(pattern8): Phase 269 P1 - SSA fix and call_method type annotation
Phase 269 P1.0: Pattern8 SSA correctness
- Add PHI node for loop variable `i` in pattern8_scan_bool_predicate.rs
- Ensure proper SSA form: i_current = phi [(preheader, i_init), (step, i_next)]
- Create loop_predicate_scan.rs for Pattern8 Frag emission
- Pre-allocate PHI destination before block generation
- Use insert_phi_at_head_spanned() for span synchronization

Phase 269 P1.1: call_method return type SSOT propagation
- Add callee_sig_name() helper in annotation.rs for function name formatting
- Annotate call_method return types in emit_unified_call_impl()
- Use module signature as SSOT for return type resolution (no hardcoding)
- Arity-aware function name: "BoxName.method/arity"

Fixes: is_integer() now correctly returns Bool instead of String
Test: Simple call_method test returns exit=7 (loop test has pre-existing bug)
Unit tests: All 1389 tests passing

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 01:41:19 +09:00