Files
hakorune/docs/guides/testing-guide.md
nyash-codex f9d100ce01 chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果:
-  LoopForm v2 テスト・ドキュメント・コメント完備
  - 4ケース(A/B/C/D)完全テストカバレッジ
  - 最小再現ケース作成(SSAバグ調査用)
  - SSOT文書作成(loopform_ssot.md)
  - 全ソースに [LoopForm] コメントタグ追加

-  Stage-1 CLI デバッグ環境構築
  - stage1_cli.hako 実装
  - stage1_bridge.rs ブリッジ実装
  - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh)
  - アーキテクチャ改善提案文書

-  環境変数削減計画策定
  - 25変数の完全調査・分類
  - 6段階削減ロードマップ(25→5、80%削減)
  - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG)

Phase 26-D からの累積変更:
- PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等)
- MIRビルダーリファクタリング
- 型伝播・最適化パス改善
- その他約300ファイルの累積変更

🎯 技術的成果:
- SSAバグ根本原因特定(条件分岐内loop変数変更)
- Region+next_iパターン適用完了(UsingCollectorBox等)
- LoopFormパターン文書化・テスト化完了
- セルフホスティング基盤強化

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: ChatGPT <noreply@openai.com>
Co-Authored-By: Task Assistant <task@anthropic.com>
2025-11-21 06:25:17 +09:00

9.2 KiB
Raw Blame History

テスト実行ガイド

📁 テストファイル配置ルール(超重要!)

⚠️ ルートディレクトリの汚染防止ルール ⚠️

# ❌ 絶対ダメ:ルートで実行
./target/release/nyash test.hako        # ログがルートに散乱!
cargo test > test_output.txt             # 出力ファイルがルートに!

# ✅ 正しい方法:必ずディレクトリを使う
cd local_tests && ../target/release/nyash test.hako
./target/release/nyash local_tests/test.hako

必須ルール:

  • テストファイル: 必ず local_tests/ に配置
  • ログファイル: 環境変数で logs/ に出力するか、実行後即削除
  • デバッグ出力: local_tests/ または logs/ に保存
  • 一時ファイル: /tmp/ を使用

なぜ毎回ルートが散らかるのか:

  1. テスト実行時にカレントディレクトリにログ出力
  2. エラー時のデバッグファイルが自動削除されない
  3. VM統計やMIRダンプがデフォルトでカレントに出力

🧪 テスト実行

# 基本機能テスト
cargo test

# テストファイル作成・実行例
mkdir -p local_tests
echo 'print("Hello Nyash!")' > local_tests/test_hello.hako
./target/debug/nyash local_tests/test_hello.hako

# 演算子統合テストlocal_testsから実行
./target/debug/nyash local_tests/test_comprehensive_operators.hako

# 実用アプリテスト
./target/debug/nyash app_dice_rpg.hako

# JIT 実行フラグCLI
./target/release/nyash --backend vm \
  --jit-exec --jit-stats --jit-dump --jit-threshold 1 \
  --jit-phi-min --jit-hostcall --jit-handle-debug \
  examples/jit_branch_demo.hako
# 既存の環境変数でも可: 
#   NYASH_JIT_EXEC/NYASH_JIT_STATS(/_JSON)/NYASH_JIT_DUMP/NYASH_JIT_THRESHOLD
#   NYASH_JIT_PHI_MIN/NYASH_JIT_HOSTCALL/NYASH_JIT_HANDLE_DEBUG

# HostCallハンドルPoCの例
./target/release/nyash --backend vm --jit-exec --jit-hostcall examples/jit_array_param_call.hako
./target/release/nyash --backend vm --jit-exec --jit-hostcall examples/jit_map_param_call.hako
./target/release/nyash --backend vm --jit-exec --jit-hostcall examples/jit_map_int_keys_param_call.hako
./target/release/nyash --backend vm --jit-exec --jit-hostcall examples/jit_string_param_length.hako
./target/release/nyash --backend vm --jit-exec --jit-hostcall examples/jit_string_is_empty.hako

PHI ポリシーPhase15と検証トグル

  • Phase15 では PHIonMIR14が既定だよ。MIR ビルダーがブロック先頭へ Phi を配置し、検証も SSA 前提で実施するよ。
  • レガシー検証で edge-copy 互換が必要なら NYASH_MIR_NO_PHI=1 を明示してね(NYASH_VERIFY_ALLOW_NO_PHI=1 も忘れずに)。
  • 詳細は docs/reference/mir/phi_policy.md を参照してね。

テスト時の環境(推奨)

# 既定: 何も設定しない → PHI-on

# レガシー PHI-off の再現が必要なときだけ明示的に切り替え
export NYASH_MIR_NO_PHI=1
export NYASH_VERIFY_ALLOW_NO_PHI=1

# さらに edge-copy 規約を厳格チェックしたい場合(任意)
export NYASH_VERIFY_EDGE_COPY_STRICT=1

PHI-on の補助トレース

  • NYASH_LLVM_TRACE_PHI=1NYASH_LLVM_TRACE_OUT=tmp/phi.jsonl を組み合わせると、PHI がどの predecessor から値を受け取っているかを確認できるよ。

PHI 配線トレースJSONL

  • 目的: LLVM 側の PHI 配線が、PHI-on で生成された SSA と legacy edge-copy (PHI-off) の両方に整合しているかを可視化・検証する。
  • 出力: 1 行 JSONJSONLNYASH_LLVM_TRACE_OUT=<path> に追記出力。
  • イベント: finalize_begin/finalize_dst/add_incoming/wire_choose/snapshot などpred→dst 整合が分かる)

クイック実行v2

# 代表サンプルを LLVM ハーネスで実行し PHI トレースを採取v2 スクリプト)
bash tools/smokes/phi_trace_local.sh

# 結果の検証(要: python3
python3 tools/phi_trace_check.py --file tmp/phi_trace.jsonl --summary

ショートカット

  • tools/smokes/phi_trace_local.sh(ビルド→サンプル実行→チェックを一括)
  • tools/smokes/v2/run.sh --profile quick|integration で代表スモークを実行

MIR デバッグの入口まとめ

1. CLI レベルの MIR ダンプ

  • ソースから直接 MIR を確認:
    • ./target/release/nyash --dump-mir path/to/program.hako
  • VM 実行経路で MIR を一緒に吐く:
    • NYASH_VM_DUMP_MIR=1 ./target/release/nyash path/to/program.hako
  • JSON で詳細解析したい場合:
    • ./target/release/nyash --emit-mir-json mir.json path/to/program.hako
    • 例: jq '.functions[0].blocks' mir.json でブロック構造を確認。

2. Scope / Loop ヒントNYASH_MIR_HINTS

  • 環境変数でヒント出力を制御:
    • NYASH_MIR_HINTS="<target>|<filters>..."
  • 例:
    • NYASH_MIR_HINTS="trace|all"stderr へ全ヒント)
    • NYASH_MIR_HINTS="jsonl=tmp/hints.jsonl|loop"(ループ関連のみ JSONL 出力)
  • 詳細: docs/guides/scopebox.md, src/mir/hints.rs

3. mir ロガー(.hako から仕込む MIR ログ)

  • 目的:

    • .hako 側のループや SSA まわりを「MIR レベル」で観測するための dev 専用フック。
    • 実行意味論には影響しないEffect::DebugLog のみ)。
  • 構文(.hako 内):

    __mir__.log("label", v1, v2, ...)
    __mir__.mark("label")
    
    • 第1引数は String リテラル必須(それ以外は通常の呼び出し扱い)。
    • log は第2引数以降の式を評価し、その ValueId 群を記録。
    • mark はラベルだけのマーカー。
    • 戻り値は Void 定数扱いのため、式コンテキストに書いても型崩れしない。
  • 実行時の有効化:

    • NYASH_MIR_DEBUG_LOG=1 ./target/release/nyash path/to/program.hako

    • VM の MIR interpreter が次のようなログを stderr に出力:

      [MIR-LOG] label: %10=123 %11="foo"
      
  • 実装位置:

    • lowering: src/mir/builder/calls/build.rstry_build_mir_debug_callreceiver が __mir__ のときに MirInstruction::DebugLog を挿入)。
    • 実行: src/backend/mir_interpreter/handlers/mod.rsNYASH_MIR_DEBUG_LOG=1 のときだけログを出す)。
  • 利用例(ループ観測の定番パターン):

    loop(i < n) {
      __mir__.log("loop/head", i, n)
      ...
    }
    __mir__.mark("loop/exit")
    
    • FuncScanner / StageB では、skip_whitespace や scan_all_boxes のループ頭・出口に挿入して、ValueId と値の流れを追跡する用途で使用している。

🔌 プラグインテスターBID-FFI診断ツール

# プラグインテスターのビルド
cd tools/plugin-tester
cargo build --release

# プラグインの診断実行
./target/release/plugin-tester ../../plugins/nyash-filebox-plugin/target/debug/libnyash_filebox_plugin.so

# 出力例:
# Plugin Information:
#   Box Type: FileBox (ID: 6)  ← プラグインが自己宣言!
#   Methods: 6
#   - birth [ID: 0] (constructor)
#   - open, read, write, close
#   - fini [ID: 4294967295] (destructor)

plugin-testerの特徴:

  • Box名を決め打ちしない汎用設計
  • プラグインのFFI関数4つabi/init/invoke/shutdownを検証
  • birth/finiライフサイクル確認
  • 将来の拡張: TLV検証、メモリリーク検出

🐛 デバッグ

パーサー無限ループ対策2025-08-09実装

# 🔥 デバッグ燃料でパーサー制御
./target/release/nyash --debug-fuel 1000 program.hako      # 1000回制限
./target/release/nyash --debug-fuel unlimited program.hako  # 無制限
./target/release/nyash program.hako                        # デフォルト10万回

# パーサー無限ループが検出されると自動停止+詳細情報表示
🚨 PARSER INFINITE LOOP DETECTED at method call argument parsing
🔍 Current token: IDENTIFIER("from") at line 17
🔍 Parser position: 45/128

対応状況: must_advance!マクロでパーサー制御完全実装済み
効果: 予約語"from"など問題のあるトークンも安全にエラー検出

アプリケーション デバッグ

// DebugBox活用
DEBUG = new DebugBox()
DEBUG.startTracking()
DEBUG.trackBox(myObject, "説明")
print(DEBUG.memoryReport())

Macro-based Test Runner (MVP)

Nyash provides a macro-powered lightweight test runner in Phase 16 (MVP).

  • Enable and run tests in a script file:
    • nyash --run-tests apps/tests/my_tests.hako
    • Discovers top-level test_* functions and Box test_* methods (static/instance).
  • Filtering: --test-filter NAME (substring match) or env NYASH_TEST_FILTER.
  • Entry policy when a main exists:
    • --test-entry wrap → run tests then call original main
    • --test-entry override → replace entry with test harness only
    • Force apply: NYASH_TEST_FORCE=1
  • Parameterized tests (MVP): NYASH_TEST_ARGS_DEFAULTS=1 injects integer 0 for each parameter (static/instance tests).
  • Exit code = number of failed tests (0 on success).

Notes

  • The feature is behind the macro gate; CLI --run-tests enables it automatically.
  • Future versions will add JSON-based per-test arguments and richer reporting.