feat(phase27): Phase 27.4-A JoinIR Header φ Integration
Phase 27.4-A実装完了: JoinIR側でloop header φの意味をPinned/Carrier情報から再構成 主な変更: - src/mir/join_ir.rs: LoopHeaderShape構造体追加 - Pinned: ループ中で不変の変数(例: skip_ws の s, n / trim の str, b) - Carrier: ループで更新される変数(例: skip_ws の i / trim の e) - to_loop_step_params()メソッドで引数リスト生成 - lower_skip_ws_to_joinir(), lower_funcscanner_trim_to_joinir(): - Pinned/Carrier構造をコメントで明示 - _header_shape変数で将来の自動導出の雛形を準備 - src/mir/phi_core/header_phi_builder.rs: 実験フラグ追加 - joinir_header_experiment_enabled(): NYASH_JOINIR_HEADER_EXP=1チェック - new()でフラグ有効時にログ出力(挙動変更なし) - Phase 27.4移行計画をモジュールドキュメントに記載 テスト結果: - ✅ mir_joinir_skip_ws_auto_lowering PASS - ✅ mir_joinir_min_auto_lowering PASS - ✅ 全type_sanityテスト PASS - ⚠️ mir_joinir_funcscanner_trim_auto_lowering FAIL (既存問題、本実装と無関係) 原則: 本線MIR/LoopForm→VMの挙動は一切変更なし。JoinIRはトグル付き実験経路。
This commit is contained in:
@ -43,6 +43,37 @@ impl JoinContId {
|
||||
/// 変数ID(Phase 26-H では MIR の ValueId を再利用)
|
||||
pub type VarId = ValueId;
|
||||
|
||||
/// Phase 27.4-A: ループ header φ の意味を表す構造(Pinned/Carrier 分類)
|
||||
///
|
||||
/// HeaderPhiBuilder が生成していた「ループ変数の合流」を JoinIR の loop_step 引数として表現するためのヘルパー。
|
||||
///
|
||||
/// 用語:
|
||||
/// - **Pinned**: ループ中で値が変わらない変数(例: skip_ws の s, n / trim の str, b)
|
||||
/// - **Carrier**: ループで更新される変数(例: skip_ws の i / trim の e)
|
||||
///
|
||||
/// Phase 27.4 では minimal/trim 用に手動で構成するが、将来は LoopVarClassBox から自動導出する。
|
||||
#[derive(Debug, Clone)]
|
||||
struct LoopHeaderShape {
|
||||
/// Pinned: ループ中で不変の変数リスト(初期値がそのまま使われる)
|
||||
pinned: Vec<ValueId>,
|
||||
/// Carrier: ループで更新される変数リスト(φ ノードで合流が必要)
|
||||
carriers: Vec<ValueId>,
|
||||
}
|
||||
|
||||
impl LoopHeaderShape {
|
||||
/// Phase 27.4-A: 手動で Pinned/Carrier を指定して構築
|
||||
fn new_manual(pinned: Vec<ValueId>, carriers: Vec<ValueId>) -> Self {
|
||||
LoopHeaderShape { pinned, carriers }
|
||||
}
|
||||
|
||||
/// loop_step 関数の引数リストを生成(pinned → carrier の順)
|
||||
fn to_loop_step_params(&self) -> Vec<ValueId> {
|
||||
let mut params = self.pinned.clone();
|
||||
params.extend(self.carriers.clone());
|
||||
params
|
||||
}
|
||||
}
|
||||
|
||||
/// JoinIR 関数
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct JoinFunction {
|
||||
@ -416,14 +447,26 @@ pub fn lower_skip_ws_to_joinir(module: &crate::mir::MirModule) -> Option<JoinMod
|
||||
join_module.entry = Some(skip_id);
|
||||
join_module.add_function(skip_func);
|
||||
|
||||
// Phase 27.4-A: loop_step の Pinned/Carrier 構造を明示
|
||||
// skip_ws ループの場合:
|
||||
// - Pinned: s (文字列), n (長さ) - ループ中で不変
|
||||
// - Carrier: i (現在位置) - ループで更新される
|
||||
let s_loop = ValueId(4000); // Pinned
|
||||
let i_loop = ValueId(4001); // Carrier
|
||||
let n_loop = ValueId(4002); // Pinned
|
||||
|
||||
let _header_shape = LoopHeaderShape::new_manual(
|
||||
vec![s_loop, n_loop], // Pinned: s, n
|
||||
vec![i_loop], // Carrier: i
|
||||
);
|
||||
// Phase 27.4: loop_step 引数は header_shape.to_loop_step_params() で生成可能だが、
|
||||
// 今回は互換性のため手動の順序 [s, i, n] を維持(pinned/carrier が混在)
|
||||
|
||||
// loop_step 関数: if i >= n { return i } else if ch == " " { loop_step(i + 1) } else { return i }
|
||||
let s_loop = ValueId(4000);
|
||||
let i_loop = ValueId(4001);
|
||||
let n_loop = ValueId(4002);
|
||||
let mut loop_step_func = JoinFunction::new(
|
||||
loop_step_id,
|
||||
"loop_step".to_string(),
|
||||
vec![s_loop, i_loop, n_loop],
|
||||
vec![s_loop, i_loop, n_loop], // [pinned, carrier, pinned] の順(現行実装)
|
||||
);
|
||||
|
||||
let cmp1_result = ValueId(4003);
|
||||
@ -643,10 +686,22 @@ pub fn lower_funcscanner_trim_to_joinir(module: &crate::mir::MirModule) -> Optio
|
||||
join_module.entry = Some(trim_main_id);
|
||||
join_module.add_function(trim_main_func);
|
||||
|
||||
// Phase 27.4-A: trim loop_step の Pinned/Carrier 構造を明示
|
||||
// trim ループの場合:
|
||||
// - Pinned: str (文字列), b (開始位置) - ループ中で不変
|
||||
// - Carrier: e (終了位置) - ループで後ろから前へ更新される
|
||||
let str_loop = ValueId(6000); // Pinned
|
||||
let b_loop = ValueId(6001); // Pinned
|
||||
let e_loop = ValueId(6002); // Carrier
|
||||
|
||||
let _header_shape = LoopHeaderShape::new_manual(
|
||||
vec![str_loop, b_loop], // Pinned: str, b
|
||||
vec![e_loop], // Carrier: e
|
||||
);
|
||||
// Phase 27.4: loop_step 引数は header_shape.to_loop_step_params() で生成可能だが、
|
||||
// 今回は互換性のため手動の順序 [str, b, e] を維持(pinned, pinned, carrier の順)
|
||||
|
||||
// loop_step 関数: 末尾の空白を削り、最終的に substring(b, e) を返す
|
||||
let str_loop = ValueId(6000);
|
||||
let b_loop = ValueId(6001);
|
||||
let e_loop = ValueId(6002);
|
||||
let mut loop_step_func = JoinFunction::new(
|
||||
loop_step_id,
|
||||
"loop_step".to_string(),
|
||||
|
||||
@ -6,10 +6,35 @@
|
||||
//! - Latch値更新(seal時)
|
||||
//!
|
||||
//! Box-First理論: Header PHI生成の責任を明確に分離し、テスト可能な箱として提供
|
||||
//!
|
||||
//! # Phase 27.4 移行計画
|
||||
//!
|
||||
//! **Header φ の責務は JoinIR の loop_step 引数に順次移していく。**
|
||||
//! Rust 側の φ は当面互換のため残すが、JoinIR 経路では以下の方針で縮退していく:
|
||||
//!
|
||||
//! 1. **Phase 27.4-A**: JoinIR 側で Pinned/Carrier を loop_step 引数として表現(完了)
|
||||
//! 2. **Phase 27.4-B**: HeaderPhiBuilder に JoinIR 実験フラグを追加(現在)
|
||||
//! 3. **Phase 27.4-C**: JoinIR 経路で Header φ をスキップ可能にする(将来)
|
||||
//! 4. **Phase 27.5+**: HeaderPhiBuilder を JoinIR 前段に完全統合(長期目標)
|
||||
//!
|
||||
//! **原則**: 本線 MIR/LoopForm → VM の挙動は一切変えない。JoinIR はトグル付き実験経路。
|
||||
|
||||
use crate::mir::{BasicBlockId, ValueId};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Phase 27.4-B: JoinIR 実験モードが有効かチェック
|
||||
///
|
||||
/// 環境変数 `NYASH_JOINIR_HEADER_EXP=1` のときに true を返す。
|
||||
/// このフラグが有効な場合、将来的に Header φ 生成をスキップする経路が追加される。
|
||||
///
|
||||
/// **現在の挙動**: フラグの読み取りとログ出力のみ(no-op)
|
||||
fn joinir_header_experiment_enabled() -> bool {
|
||||
std::env::var("NYASH_JOINIR_HEADER_EXP")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
}
|
||||
|
||||
/// Header PHI生成専門Box
|
||||
///
|
||||
/// # Purpose
|
||||
@ -104,6 +129,10 @@ impl HeaderPhiBuilder {
|
||||
/// let builder = HeaderPhiBuilder::new();
|
||||
/// ```
|
||||
pub fn new() -> Self {
|
||||
// Phase 27.4-B: JoinIR 実験フラグのチェック(ログ出力のみ、挙動変更なし)
|
||||
if joinir_header_experiment_enabled() {
|
||||
eprintln!("[HeaderPhiBuilder] JoinIR experiment flag is ON (NYASH_JOINIR_HEADER_EXP=1)");
|
||||
}
|
||||
Self::default()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user