Files
hakorune/docs/development/guides/loop_testing_guide.md
nyash-codex 52b62c5772 feat(phase21.5): Stage-B parser loop fix + delegate path stabilization
## 修正内容

### 1. Stage-B パーサー修正(偶然の回避)
- **ファイル**:
  - `lang/src/compiler/parser/expr/parser_expr_box.hako`
  - `lang/src/compiler/parser/stmt/parser_control_box.hako`
- **問題**: ネストループで gpos が正しく進まず、loop の cond/body が壊れる
- **回避策**: new 式のメソッドチェーン処理追加で別ループを導入
- **結果**: MIR 生成が変わって VM gpos バグを回避

### 2. delegate パス動作確認
- **テスト**: `/tmp/loop_min.hako` → rc=10 
- **MIR構造**: 正しい PHI/compare/binop を生成
- **チェーン**: hakorune parser → Rust delegate → LLVM EXE 完動

### 3. ドキュメント追加
- `docs/development/analysis/` - delegate 分析
- `docs/development/guides/` - ループテストガイド
- `docs/development/testing/` - Stage-B 検証報告

### 4. カナリーテスト追加
- `tools/smokes/v2/profiles/quick/core/phase2100/` 配下に複数追加
- emit_boxcall_length_canary_vm.sh
- stageb_parser_loop_json_canary_vm.sh
- 他

### 受け入れ基準
-  delegate パス: rc=10 返す
-  FORCE パス: rc=10 返す(既存)
-  MIR 構造: 正しい PHI incoming と compare
-  既定挙動: 不変(dev トグルのみ)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 21:24:51 +09:00

200 lines
5.5 KiB
Markdown

# Loop Testing Guide - Two Paths
## Quick Reference
### ✅ FORCE Path (RECOMMENDED - Works Correctly)
Use this for all loop development and testing:
```bash
# Generate MIR with FORCE path
HAKO_SELFHOST_BUILDER_FIRST=1 \
HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG=1 \
HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE=1 \
bash tools/hakorune_emit_mir.sh input.hako output.json
# Build EXE
NYASH_LLVM_BACKEND=crate \
bash tools/ny_mir_builder.sh --in output.json --emit exe -o output.exe
# Run
./output.exe
echo "Exit code: $?"
```
### ❌ Delegate Path (BROKEN - DO NOT USE)
**Known Issue**: Stage-B parser produces malformed Program JSON for loops.
**Symptoms**:
- Empty loop bodies
- Wrong loop conditions (comparing with 0 instead of variables)
- Incorrect exit codes
**Status**: Under investigation. See [delegate_loop_lowering_analysis.md](../analysis/delegate_loop_lowering_analysis.md)
## Test Matrix
| Test Case | FORCE Path | Delegate Path | Notes |
|-----------|------------|---------------|-------|
| Simple while loop | ✅ Pass | ❌ Fail | Returns 0 instead of expected value |
| Loop with break | ✅ Pass | ❌ Fail | Body not executed |
| Loop with continue | ✅ Pass | ❌ Fail | Increment not applied |
| Nested loops | ✅ Pass | ❌ Fail | Inner loop empty |
## Environment Variables
### FORCE Path Variables
```bash
# Primary control
HAKO_SELFHOST_BUILDER_FIRST=1 # Use selfhost builder first
# Loop-specific
HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG=1 # Force JsonFrag for loops
HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE=1 # Enable normalization
HAKO_MIR_BUILDER_JSONFRAG_PURIFY=1 # Enable purification (optional)
# Backend
NYASH_LLVM_BACKEND=crate # Use crate backend for EXE
NYASH_LLVM_VERIFY=1 # Enable LLVM IR verification
NYASH_LLVM_DUMP_IR=path.ll # Dump LLVM IR for inspection
```
### Delegate Path Variables (For Debugging Only)
```bash
# Basic delegate (DO NOT USE for loops)
NYASH_JSON_ONLY=1 # Generate MIR via delegate
# This will produce broken MIR for loops!
```
## Debugging Loop Issues
### 1. Verify MIR Structure
```bash
# Check FORCE MIR
jq '.functions[0].blocks' output_force.json
# Expected structure:
# - Block 0: preheader with const declarations
# - Block 1: header with PHI nodes, compare, and branch
# - Block 2: body with loop operations (e.g., i+1)
# - Block 3: exit
```
### 2. Check Loop Header PHIs
```bash
# Inspect header block PHIs
jq '.functions[0].blocks[1].instructions[] | select(.op == "phi")' output.json
# Expected:
# - PHI for loop variable: incoming from [preheader, latch]
# - PHI for condition variable: incoming from [preheader, latch]
# - Different value IDs for latch (updated values)
```
### 3. Verify Loop Body
```bash
# Check body block
jq '.functions[0].blocks[2]' output.json
# Expected:
# - At least one operation (e.g., binop for i+1)
# - Jump back to header
# - NOT empty!
```
### 4. Compare LLVM IR
```bash
# Generate IR from both paths
HAKO_SELFHOST_BUILDER_FIRST=1 HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG=1 \
NYASH_LLVM_DUMP_IR=/tmp/force.ll \
bash tools/hakorune_emit_mir.sh test.hako force.json && \
NYASH_LLVM_BACKEND=crate bash tools/ny_mir_builder.sh --in force.json --emit exe -o force.exe
# FORCE IR will show:
# - Proper PHI nodes in loop header
# - Loop body with operations
# - Correct comparison (e.g., %i < %n)
```
## Common Pitfalls
### ❌ Forgetting FORCE Variables
```bash
# This will use delegate path and FAIL for loops:
bash tools/hakorune_emit_mir.sh test.hako output.json
# Always use:
HAKO_SELFHOST_BUILDER_FIRST=1 HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG=1 \
bash tools/hakorune_emit_mir.sh test.hako output.json
```
### ❌ Testing Delegate Path for Loops
```bash
# DO NOT test loops with delegate path:
NYASH_JSON_ONLY=1 bash tools/hakorune_emit_mir.sh loop_test.hako output.json
# This WILL produce broken MIR!
```
### ✅ Correct Workflow
```bash
# 1. Set up environment
export HAKO_SELFHOST_BUILDER_FIRST=1
export HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG=1
export HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE=1
# 2. Generate MIR
bash tools/hakorune_emit_mir.sh test.hako output.json
# 3. Build and test
NYASH_LLVM_BACKEND=crate bash tools/ny_mir_builder.sh --in output.json --emit exe -o test.exe
./test.exe
echo "Exit code: $?"
```
## Canary Tests
Use these existing canaries to verify loop functionality:
```bash
# Stage-B loop canary (uses FORCE path)
bash tools/smokes/v2/profiles/quick/core/phase2100/stageb_loop_jsonfrag_crate_exe_canary_vm.sh
# This test verifies:
# - Loop MIR generation via FORCE path
# - Correct PHI structure
# - Proper loop body execution
# - Expected exit code
```
## When to Use Each Path
| Scenario | Use FORCE | Use Delegate | Notes |
|----------|-----------|--------------|-------|
| Loop development | ✅ Yes | ❌ No | Delegate broken for loops |
| Loop testing | ✅ Yes | ❌ No | FORCE path verified |
| If/else | ✅ Yes | ✅ Yes | Both work |
| Simple expressions | ✅ Yes | ✅ Yes | Both work |
| Production builds | ✅ Yes | ❌ No | FORCE path reliable |
## Related Documentation
- [Delegate Loop Lowering Analysis](../analysis/delegate_loop_lowering_analysis.md) - Root cause analysis
- [Phase 21.5 Optimization Readiness](../../roadmap/phases/phase-21.5/) - Current phase docs
- [MIR Builder Configuration](../reference/mir_builder_config.md) - All configuration options
---
**Last Updated**: 2025-11-11
**Status**: FORCE path stable, delegate path broken for loops
**Recommendation**: Always use FORCE path for loop development until Stage-B parser is fixed