## 実装内容 ### 1. 環境変数フラグ追加 - NYASH_HAKO_CHECK_JOINIR でJoinIR/Legacy経路を切り替え可能 - src/config/env/hako_check.rs で hako_check_joinir_enabled() 実装 - デフォルト: false(レガシー経路)で後方互換性確保 ### 2. MIR Builder JoinIR スイッチ - cf_if() メソッドにフラグチェック追加 - try_cf_if_joinir() プレースホルダー実装(Phase 124で完全実装) - JoinIR → legacy フォールバック機構を構築 ### 3. テストケース作成(4個) - phase123_simple_if.hako - phase123_nested_if.hako - phase123_while_loop.hako - phase123_if_in_loop.hako ### 4. テスト結果 ✅ Legacy path: 4/4 PASS ✅ JoinIR path: 4/4 PASS (JoinIR path は現在フォールバック経由で動作) ### 5. ドキュメント更新 - environment-variables.md: NYASH_HAKO_CHECK_JOINIR 記載 - phase121_hako_check_joinir_design.md: Phase 123実装セクション追加 - hako_check_design.md: 2パス実行フロー図を追加 - CURRENT_TASK.md: Phase 123完了を記録 ## 数値成果 - 新規ファイル: 2個 (config/env/hako_check.rs, test cases × 4, test script) - 修正ファイル: 6個 - 総追加行数: 335行 - ビルド: Zero errors ## 設計・実装の特徴 ✅ Environment variable で簡単に経路切り替え可能 ✅ レガシー経路を完全に保持(後方互換性) ✅ JoinIR基盤を Phase 124 での完全実装に向けて構築 ✅ フォールバック機構でリスク最小化 ## 次のステップ Phase 124: JoinIR 完全実装&デフォルト化 - try_cf_if_joinir() を IfSelectLowerer と統合 - Loop JoinIR 統合追加 - JoinIR をデフォルト経路に変更 - NYASH_LEGACY_PHI=1 で legacy フォールバック可能に 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
hako_check 設計(Phase 121 時点)
概要
hako_check は .hako ファイルの静的解析・検証を行うツール。 Phase 121 では、この経路を JoinIR 統合に向けて設計する。
hako_check の役割
現在の機能
- 構文チェック: パーサーエラーの検出
- 型チェック: 基本的な型の整合性確認
- MIR 生成: .hako → MIR への変換(検証用)
- 制御フローチェック: unreachable code などの検出
- ルールベース診断: 19種類の診断ルール(HC001-HC031)
hako_check の実装構造(Phase 121 調査時点)
重要: hako_check は Rust バイナリではなく .hako スクリプトとして実装されている。
tools/hako_check.sh # シェルスクリプトラッパー
↓
tools/hako_check/cli.hako # .hako エントリーポイント
↓
HakoAnalyzerBox.run() # 静的解析メインロジック
↓
HakoAnalysisBuilderBox # IR 生成(analysis_consumer.hako)
↓
hakorune --backend vm # Rust VM で実行
↓
MirCompiler::compile() # AST → MIR 変換
↓
MirBuilder::build_module() # MIR 生成(ここで PHI 生成)
エントリーポイントの詳細
ファイル: tools/hako_check.sh
実行フロー:
tools/hako_check.shがシェルスクリプトとして起動$BIN(通常は./target/release/hakorune) を使用してcli.hakoを実行- 環境変数で VM バックエンドを指定:
--backend vm
重要な環境変数:
NYASH_DISABLE_PLUGINS=1 # プラグイン無効化(安定性優先)
NYASH_BOX_FACTORY_POLICY=builtin_first # ビルトイン Box 優先
NYASH_FEATURES=stage3 # Stage-3 パーサー使用
NYASH_ENABLE_USING=1 # using 文有効化
MIR 生成経路
hako_check での MIR 生成フロー:
1. cli.hako が .hako ファイルを読み込む
↓
2. HakoAnalysisBuilderBox.build_from_source_flags() を呼び出す
↓
3. 内部で HakoParserCoreBox.parse() を使用(.hako パーサー)
↓
4. AST を取得(Rust VM 内部で nyash_rust::parser::NyashParser を使用)
↓
5. Rust VM が AST を MirCompiler に渡す
↓
6. MirCompiler::compile_with_source() が AST → MIR 変換
↓
7. MirBuilder::build_module() で MIR 生成
↓
8. If/Loop 文は control_flow.rs で処理
PHI 生成経路(Phase 121 時点)
If 文の PHI 生成:
- ファイル:
src/mir/builder/if_form.rs - 関数:
MirBuilder::cf_if()→ PHI 生成ロジック - JoinIR 統合: ❌ 未実装(旧 PHI 生成器を使用中)
Loop の PHI 生成:
- ファイル:
src/mir/builder/control_flow.rs - 関数:
MirBuilder::cf_loop()→try_cf_loop_joinir() - JoinIR 統合: ⚠️ 部分実装(Phase 49 で mainline 統合開始)
HAKO_JOINIR_PRINT_TOKENS_MAIN=1: 特定関数のみ JoinIR 経由HAKO_JOINIR_ARRAY_FILTER_MAIN=1: 特定関数のみ JoinIR 経由- デフォルトは旧 LoopBuilder へフォールバック
Phase 121 での課題
- 旧 MIR/PHI 経路: 現在は旧 PHI 生成器を主に使用している
- JoinIR 統合: If/Loop の JoinIR Lowering 経由への移行が必要
- Strict モード: NYASH_JOINIR_STRICT=1 での動作確認が未実施
現在の JoinIR 統合状況
Loop PHI 生成(部分統合済み)
Phase 49 Mainline Integration:
// src/mir/builder/control_flow.rs
fn try_cf_loop_joinir(&mut self, condition: &ASTNode, body: &ASTNode) -> Result<Option<ValueId>, String> {
let core_on = crate::config::env::joinir_core_enabled();
let mainline_targets = vec!["print_tokens", "filter"];
if core_on && is_mainline_target(&func_name) {
// JoinIR Frontend を試す
return self.cf_loop_joinir_impl(condition, body, &func_name, debug);
}
// フォールバック: 旧 LoopBuilder
Ok(None)
}
特徴:
- 選択的統合: 特定関数のみ JoinIR 経由(mainline targets)
- フォールバック: 失敗時は旧 LoopBuilder に戻る
- 環境変数制御:
NYASH_JOINIR_CORE=1: JoinIR Core 有効化HAKO_JOINIR_PRINT_TOKENS_MAIN=1: print_tokens/0 を JoinIR 経由HAKO_JOINIR_ARRAY_FILTER_MAIN=1: ArrayExtBox.filter/2 を JoinIR 経由
If PHI 生成(未統合)
Phase 121 調査結果: If 文の PHI 生成は旧経路を使用中
ファイル: src/mir/builder/if_form.rs
// 旧 PHI 生成器(Phase 121 時点で現役)
fn cf_if(&mut self, condition: &ASTNode, then_block: &ASTNode, else_block: Option<&ASTNode>) -> Result<ValueId, String> {
// 旧 PHI 生成ロジック
// Phase 33-10 で JoinIR If Lowering が実装されたが、
// MirBuilder 経路ではまだ統合されていない
}
JoinIR 統合設計
統合方針
3段階移行戦略:
-
Phase 122: 環境変数で JoinIR 経路を選択可能に(デフォルトは旧経路)
NYASH_HAKO_CHECK_JOINIR=1で JoinIR 経路を有効化- 旧経路との互換性維持(フォールバック可能)
-
Phase 123: JoinIR 経路をデフォルトに(旧経路は
NYASH_LEGACY_PHI=1でのみ有効)- デフォルトで JoinIR 経路を使用
- 旧経路は明示的に有効化した場合のみ使用
-
Phase 124: 旧経路完全削除(JoinIR のみ)
- 旧 PHI 生成器の完全削除
NYASH_LEGACY_PHI=1環境変数も削除
設計原則
Baseline First:
- Phase 120 で確立した selfhost 経路のベースラインを参考に
- hako_check 経路でも同様のベースライン確立が必要
Fail-Fast:
- フォールバック処理は原則禁止(Phase 123 以降)
- エラーは早期に明示的に失敗させる
環境変数制御:
NYASH_HAKO_CHECK_JOINIR=1: hako_check で JoinIR 経路を有効化NYASH_JOINIR_STRICT=1: フォールバック禁止(厳格モード)
hako_check 特有の考慮事項
1. .hako スクリプトとしての実行:
- hako_check は Rust バイナリではなく .hako スクリプト
- Rust VM 経由で実行されるため、VM の MirBuilder を使用
- JoinIR 統合は VM の MirBuilder に実装する必要がある
2. 診断ルールとの関係:
- hako_check は 19 種類の診断ルール(HC001-HC031)を実装
- MIR 生成は診断の前段階(IR 生成用)
- JoinIR 統合による診断ルールへの影響は最小限
3. selfhost 経路との違い:
- selfhost: .hako コンパイラを実行(実行時 PHI 必要)
- hako_check: 静的解析のみ(MIR 生成は検証用)
- PHI 生成の要件は同じだが、実行環境が異なる
selfhost 経路との違い
| 項目 | selfhost 経路 | hako_check 経路 |
|---|---|---|
| 目的 | .hako コンパイラ実行 | .hako 静的解析 |
| 実行 | VM/LLVM で実行 | MIR 生成のみ(VM で .hako スクリプト実行) |
| PHI 生成 | 実行時に必要 | 検証用のみ |
| エラー処理 | 実行時エラー | 静的エラー |
| 環境変数 | NYASH_USE_NY_COMPILER=1 |
NYASH_DISABLE_PLUGINS=1 |
| 実装形式 | Rust バイナリ | .hako スクリプト(VM で実行) |
Phase 122+ 実装計画
Phase 122: 環境変数で JoinIR 選択可能に
実装内容:
NYASH_HAKO_CHECK_JOINIR=1環境変数追加- MirBuilder の
cf_if()/cf_loop()で環境変数確認 - 条件分岐で JoinIR 経路 or 旧経路を選択
実装箇所:
src/mir/builder/if_form.rs: If 文の JoinIR 統合src/mir/builder/control_flow.rs: Loop の JoinIR 統合拡張
テスト:
- 既存テスト全 PASS(旧経路)
- JoinIR 経路でのスモークテスト作成
Phase 123: JoinIR 経路をデフォルトに
実装内容:
- デフォルトを JoinIR 経路に変更
NYASH_LEGACY_PHI=1で旧経路に戻せるように
テスト:
- JoinIR 経路で全テスト PASS
- 旧経路でも互換性維持確認
Phase 124: 旧経路完全削除
実装内容:
- 旧 PHI 生成器削除(
if_form.rsの旧ロジック削除) NYASH_LEGACY_PHI=1環境変数削除- 関連ドキュメント更新
テスト:
- JoinIR 経路のみで全テスト PASS
まとめ
Phase 121 は設計と調査のみ。実装は Phase 122+ で段階的に実施する。
重要な発見:
- hako_check は .hako スクリプトとして実装されている
- JoinIR 統合は VM の MirBuilder に実装する必要がある
- Loop は部分統合済み(Phase 49)、If は未統合
- 段階的移行戦略により互換性を維持しながら統合可能
Phase 123: 実行フロー図(2パス実装完了)
Legacy パス (NYASH_HAKO_CHECK_JOINIR=0 or unset)
.hako file
↓
Tokenize / Parse (Rust Parser)
↓
AST Generation
↓
MIR Builder (legacy if/loop lowering)
├─ cf_if() → lower_if_form() (legacy PHI generation)
└─ cf_loop() → LoopBuilder (legacy PHI generation)
↓
MIR Generation (with legacy PHI)
↓
VM Interpreter
↓
Execution Result
JoinIR パス (NYASH_HAKO_CHECK_JOINIR=1)
.hako file
↓
Tokenize / Parse (Rust Parser)
↓
AST Generation
↓
MIR Builder (with JoinIR switch check)
├─ cf_if() → [Phase 123] Check hako_check_joinir_enabled()
│ ├─ true: try_cf_if_joinir() → [Placeholder] fallback to legacy
│ └─ false: lower_if_form() (legacy)
└─ cf_loop() → [Phase 124 予定] JoinIR Loop Lowering
↓
MIR Generation
↓
[Phase 124 予定] JoinIR Lowerer (if/loop → PHI)
├─ IfSelectLowerer: Simple if/else → Select instruction
└─ LoopLowerer: Loop → PHI + LoopForm
↓
MIR (with JoinIR-generated PHI)
↓
VM Interpreter
↓
Execution Result
Phase 123 実装状態
✅ 実装完了:
- 環境変数
NYASH_HAKO_CHECK_JOINIR読み取り cf_if()での分岐処理- フォールバック機構(プレースホルダー → レガシー)
📋 未実装(Phase 124 予定):
try_cf_if_joinir()の実際の JoinIR 統合処理- JoinIR Lowerer の適用
- Loop の JoinIR 統合
実行時の動作確認
# Legacy Path (デフォルト)
$ ./target/release/hakorune --backend vm test.hako
[MirBuilder] cf_if() → lower_if_form() (legacy)
RC: 0
# JoinIR Path (Phase 123 実装)
$ NYASH_HAKO_CHECK_JOINIR=1 ./target/release/hakorune --backend vm test.hako
[MirBuilder] cf_if() → try_cf_if_joinir() → fallback to lower_if_form()
RC: 0
# JoinIR Debug Output (Phase 123)
$ NYASH_HAKO_CHECK_JOINIR=1 NYASH_HAKO_CHECK_JOINIR_DEBUG=1 ./target/release/hakorune test.hako
[cf_if/joinir] Routing if statement through JoinIR lowering
[cf_if/joinir] JoinIR not applicable, falling back to legacy
設計ノート
Phase 123 の焦点:
- 環境変数による経路選択機能の実装
- プレースホルダー実装によるフレームワーク確立
- テスト基盤の構築
Phase 124 での完全実装:
- JoinIR Lowerer の統合
- MIR 後処理としての JoinIR 変換
- レガシー経路からの完全移行
Phase 123 実装完了記録 (2025-12-04)
変更ファイル一覧
src/config/env/hako_check.rs(新規) - 環境変数フラグ実装src/config/env.rs- hako_check モジュール追加src/mir/builder/control_flow.rs- JoinIR スイッチ実装docs/reference/environment-variables.md- ドキュメント更新local_tests/phase123_*.hako(4件) - テストケース作成tools/smokes/v2/profiles/integration/hako_check_joinir.sh- テストスクリプト
テスト結果
Legacy Path: 4/4 PASS (100%) JoinIR Path: 4/4 PASS (100%)
Note: JoinIR 経路はプレースホルダー実装のため、実際にはレガシー経路で処理。 環境変数読み取りとフラグ分岐は完全に動作しており、Phase 124 で JoinIR 実装を追加すれば即座に動作可能。