## Problem
Exit PHI generation was using header_id as predecessor, but when
build_expression(condition) creates new blocks, the actual branch
instruction is emitted from a different block, causing:
"phi pred mismatch: no input for predecessor BasicBlockId(X)"
## Solution
- Modified build_exit_phis() to accept branch_source_block parameter
- Capture actual block after condition evaluation in loop_builder.rs
- Use branch_source_block instead of header_id for PHI inputs
## Progress
- Error changed from ValueId(5941)/BasicBlockId(4674) to
ValueId(5927)/BasicBlockId(4672), showing partial fix
- Added comprehensive test suite in mir_loopform_exit_phi.rs
- Added debug logging to trace condition block creation
## Status
Partial fix - unit tests pass, but Test 2 (Stage-B compilation) still
has errors. Needs further investigation of complex nested compilation
scenarios.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem**: is_parameter() was too simple, checking only ValueId which changes
through copies/PHIs. This caused parameters like 'data' to be misclassified as
carriers, leading to incorrect PHI construction.
**Solution**: Track original parameter names at function entry.
**Changes**:
1. **Added function_param_names field** (builder.rs):
- HashSet<String> to track original parameter names
- Populated in lower_static_method_as_function()
- Cleared and repopulated for each new function
2. **Improved is_parameter()** (loop_builder.rs):
- Check name against function_param_names instead of ValueId
- More reliable than checking func.params (ValueIds change)
- __pin$*$@* variables correctly classified as carriers
- Added debug logging with NYASH_LOOPFORM_DEBUG
3. **Enhanced debug output** (loopform_builder.rs):
- Show carrier/pinned classification during prepare_structure()
- Show variable_map state after emit_header_phis()
**Test Results**:
- ✅ 'args' correctly identified as parameter (was working)
- ✅ 'data' now correctly identified as parameter (was broken)
- ✅ __pin variables correctly classified as carriers
- ✅ PHI values allocated and variable_map updated correctly
- ⚠️ ValueId undefined errors persist (separate issue)
**Remaining Issue**:
ValueId(10) undefined error suggests PHI visibility problem or VM verification
issue. Needs further investigation of emit_phi_at_block_start() or VM executor.
**Backward Compatibility**:
- Flag OFF: 100% existing behavior preserved (legacy path unchanged)
- Feature-flagged with NYASH_LOOPFORM_PHI_V2=1
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
**Problem**: Loop body PHIs reference ValueIds that don't exist at header exit.
Example: bb6 uses %14 from bb3, but %14 is only defined in bb6.
**Partial Fix**:
1. Create header_exit_snapshot from PHI values + new pinned variables
2. Use snapshot for loop body PHI creation instead of current variable_map
3. Use snapshot for exit PHI generation
**Progress**: Error moved from BasicBlockId(4) to BasicBlockId(3)
**Remaining**: Circular dependency - PHIs reference other PHIs in same block.
Need to ensure snapshot contains only values defined before header branch.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Unify standard method calls to emit_unified_call; route via RouterPolicy and apply rewrite::{special,known} at a single entry.\n- Stabilize emit-time invariants: LocalSSA finalize + BlockSchedule PHI→Copy→Call ordering; metadata propagation on copies.\n- Known rewrite default ON (userbox only, strict guards) with opt-out flag NYASH_REWRITE_KNOWN_DEFAULT=0.\n- Expand TypeAnnotation whitelist (is_digit_char/is_hex_digit_char/is_alpha_char/Map.has).\n- Docs: unified-method-resolution design note; Quick Reference normalization note; selfhosting/quickstart.\n- Tools: add tools/selfhost_smoke.sh (dev-only).\n- Keep behavior unchanged for Unknown/core/user-instance via BoxCall fallback; all tests green (quick/integration).
- SSOT using profiles (aliases/packages via nyash.toml), AST prelude merge
- Parser/member guards; Builder pin/PHI and instance→function rewrite (dev on)
- VM refactors (handlers split) and JSON roundtrip/nested stabilization
- CURRENT_TASK.md updated with scope and acceptance criteria
Notes: dev-only guards remain togglable via env; no default behavior changes for prod.
Major changes:
- Split runner module: 1358→580 lines (via Gemini)
- Create new modules: dispatch.rs, selfhost.rs, pipeline.rs, pipe_io.rs
- Fix build errors from incomplete method migrations
- Add warning to CLAUDE.md about JIT/Cranelift not working
- Create interpreter.rs mode module
- Refactor loop builder into separate module
Build status:
- ✅ Executable builds successfully
- ✅ Basic execution works (tested with print)
- ⚠️ 106 warnings remain (to be cleaned up next)
- ⚠️ execute_mir_mode still in mod.rs (needs further migration)
Note: ChatGPT correctly fixed runner.execute_mir_mode() calls
that I incorrectly changed to super::modes::mir::
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Parser improvements:
- Added expression statement fallback in parse_statement() for flexible syntax
- Fixed ternary operator to use PeekExpr instead of If AST (better lowering)
- Added peek_token() check to avoid ?/?: operator conflicts
LLVM Python improvements:
- Added optional ESC_JSON_FIX environment flag for string concatenation
- Improved PHI generation with better default handling
- Enhanced substring tracking for esc_json pattern
Documentation updates:
- Updated language guide with peek expression examples
- Added box theory diagrams to Phase 15 planning
- Clarified peek vs when syntax differences
These changes enable cleaner parser implementation for self-hosting,
especially for handling digit conversion with peek expressions instead
of 19-line if-else chains.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Key updates:
- Document MIR 26→15 instruction reduction plan (transitioning status)
- Add Core-15 target instruction set in INSTRUCTION_SET.md
- Save AI conference analyses validating Box Theory and 15-instruction design
- Create MIR annotation system proposal for optimization hints
- Update SKIP_PHASE_10_DECISION.md with LLVM direct migration rationale
Technical insights:
- RefNew/RefGet/RefSet can be eliminated through Box unification
- GC/sync/async all achievable with 15 core instructions
- BoxCall lowering can automatically insert GC barriers
- 2-3x performance improvement expected with LLVM
- Build time reduction 50%, binary size reduction 40%
Status: Design complete, implementation pending
- After inserting Phi at loop header, update variable_map so that
subsequent uses (after the loop) refer to the Phi result instead of
the latch/body value. This fixes dominance issues in verifier.
- Add tests: loop phi normalization and loop+nested-if phi; both pass.
- Eliminate static_mut_refs warnings by using once_cell::sync::Lazy
- Make FileMode enum public to fix private_interfaces warning
- Reduce warnings from 6 to 3
- Prepare for Rust 2024 edition compatibility
Fixed infinite loop issue in VM by addressing phi node caching problem.
The phi node was caching the initial value and returning it for all
subsequent iterations, preventing loop variable updates.
Changes:
- Created vm_phi.rs module to separate loop execution logic (similar to mir/loop_builder.rs)
- Disabled phi node caching to ensure correct value selection each iteration
- Added LoopExecutor to track block transitions and handle phi nodes properly
- Fixed VM to correctly track previous_block for phi input selection
The VM now correctly executes SSA-form loops with proper variable updates:
- Loop counter increments correctly
- Phi nodes select the right input based on control flow
- Test case now completes successfully (i=1,2,3,4)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>