fix(parser): Stage-1 CLI infinite loop - MirBuilder-friendly refactoring (Part 1/3)

**Problem**: Stage-1 CLI hits VM step budget (infinite loops) in multiple functions
- ParserBox.parse_program2: bb2853→bb2854 loop
- StringHelpers.skip_ws: bb488→bb491 loop

**Root Cause**: MirBuilder bug with `loop(cont==1)` + nested `if-else` pattern
- PHI instructions with self-references
- Loop exit blocks jumping back to header instead of continuation

**Solution**: Refactor to MirBuilder-friendly pattern
```hako
// Before (causes infinite loop):
loop(cont == 1) {
  if guard > max { return j } else { guard++ }
  if condition { action } else { cont = 0 }
}

// After (MirBuilder-friendly):
loop(j < n) {
  if condition { j++; continue }
  break
}
```

**Changes**:
1. parser_box.hako: parse_program2 main loop refactored
   - 7 sections: ws→EOF/guard→parse_stmt2→progress guard→trace→semicolons→emit
   - Unconditional parse_stmt2 execution (no nested if-else)
   - Explicit `break` for loop exits

2. string_helpers.hako: StringHelpers.skip_ws simplified
   - Removed `cont` flag and guard counter
   - Direct `loop(j < n)` with `continue/break`

3. vm.rs, vm_fallback.rs: RUST_MIR_DUMP_PATH support
   - Enables offline MIR analysis for debugging

**Progress**:
-  parse_program2: infinite loop fixed
-  StringHelpers.skip_ws: infinite loop fixed
-  ParserIdentScanBox.scan_ident: next target (bb985 loop)

**Testing**:
- MIR dumps generated successfully (116K+ lines)
- ws_init loop completes
- parse_program2 progresses further
- Still hits infinite loop in scan_ident (Part 2 needed)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-24 18:19:31 +09:00
parent 6885235145
commit c6c5653ae0
4 changed files with 97 additions and 116 deletions

View File

@ -172,14 +172,13 @@ static box StringHelpers {
local s = "" + src
local n = s.length()
local j = i
local cont = 1
local guard = 0
local max = 100000
loop(cont == 1) {
if guard > max { return j } else { guard = guard + 1 }
if j < n {
if me.is_space(s.substring(j, j+1)) { j = j + 1 } else { cont = 0 }
} else { cont = 0 }
// Simplified loop structure for MirBuilder compatibility
loop(j < n) {
if me.is_space(s.substring(j, j+1)) {
j = j + 1
continue
}
break
}
return j
}