Files
hakorune/src/runner/json_v0_bridge/lowering/loop_.rs

122 lines
4.3 KiB
Rust
Raw Normal View History

use super::{lower_stmt_list_with_vars, new_block, BridgeEnv, LoopContext};
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
use std::collections::HashMap;
use super::super::ast::StmtV0;
use super::super::ast::ExprV0;
pub(super) fn lower_loop_stmt(
f: &mut MirFunction,
cur_bb: BasicBlockId,
cond: &ExprV0,
body: &[StmtV0],
vars: &mut HashMap<String, ValueId>,
loop_stack: &mut Vec<LoopContext>,
env: &BridgeEnv,
) -> Result<BasicBlockId, String> {
let cond_bb = new_block(f);
let body_bb = new_block(f);
let exit_bb = new_block(f);
// フェーズM.2: no_phi変数削除 + PHI UseBeforeDef修正
let base_vars = vars.clone();
let orig_names: Vec<String> = base_vars.keys().cloned().collect();
// Step 1: cur_bbでCopy命令を先に生成PHI inputsの定義を確保
let mut copy_map: HashMap<String, ValueId> = HashMap::new();
for name in &orig_names {
if let Some(&bval) = base_vars.get(name) {
let copy_dst = f.next_value_id();
if let Some(bb) = f.get_block_mut(cur_bb) {
bb.add_instruction(MirInstruction::Copy {
dst: copy_dst,
src: bval,
});
}
copy_map.insert(name.clone(), copy_dst);
}
}
// Step 2: cur_bbからcond_bbへのJumpを挿入
if let Some(bb) = f.get_block_mut(cur_bb) {
if !bb.is_terminated() {
bb.add_instruction(MirInstruction::Jump { target: cond_bb });
}
}
// Step 3: cond_bbでPHI命令生成copy_mapの値を使用
let mut phi_map: HashMap<String, ValueId> = HashMap::new();
for name in &orig_names {
if let Some(&copy_val) = copy_map.get(name) {
let dst = f.next_value_id();
if let Some(bb) = f.get_block_mut(cond_bb) {
bb.insert_instruction_after_phis(MirInstruction::Phi {
dst,
inputs: vec![(cur_bb, copy_val)],
});
}
// 開発時検証SSOTと同等の不変条件チェック
#[cfg(debug_assertions)]
{
crate::mir::phi_core::common::debug_verify_phi_inputs(
f,
cond_bb,
&[(cur_bb, copy_val)],
);
}
phi_map.insert(name.clone(), dst);
}
}
for (name, &phi) in &phi_map {
vars.insert(name.clone(), phi);
}
let (cval, _cend) = super::expr::lower_expr_with_vars(env, f, cond_bb, cond, vars)?;
if let Some(bb) = f.get_block_mut(cond_bb) {
bb.set_terminator(MirInstruction::Branch {
condition: cval,
then_bb: body_bb,
else_bb: exit_bb,
});
}
let mut body_vars = vars.clone();
loop_stack.push(LoopContext { cond_bb, exit_bb });
let bend_res = lower_stmt_list_with_vars(f, body_bb, body, &mut body_vars, loop_stack, env);
loop_stack.pop();
let bend = bend_res?;
if let Some(bb) = f.get_block_mut(bend) {
if !bb.is_terminated() {
bb.set_terminator(MirInstruction::Jump { target: cond_bb });
}
}
let backedge_to_cond = matches!(
f.blocks
.get(&bend)
.and_then(|bb| bb.terminator.as_ref()),
Some(MirInstruction::Jump { target, .. }) if *target == cond_bb
);
if backedge_to_cond {
// フェーズM.2: PHI統一処理no_phi分岐削除
if let Some(bb) = f.get_block_mut(cond_bb) {
for (name, &phi_dst) in &phi_map {
if let Some(&latch_val) = body_vars.get(name) {
refactor(mir): Phase 6-2 - Apply helper methods to reduce ~28 lines in JSON v0 Bridge **Phase 6-2完了:ヘルパーメソッド適用で28行削減達成!** ## 📊 削減実績 - **loop_.rs**: 8行→1行(7行削減) - PHI更新ループ統一 - **if_else.rs**: 6行→1行(5行削減) - Branch終端設定統一 - **try_catch.rs**: 8箇所×2-3行(16行削減) - Jump終端設定統一 - **合計**: ~28行削減 ## 🔧 適用内容 ### 1. loop_.rs - PHI更新の統一化 - **Before**: 手動でPHI命令を検索してinputs.push() - **After**: `bb.update_phi_input(phi_dst, (bend, latch_val))?` ### 2. if_else.rs - Branch終端設定の統一化 - **Before**: if-let-Some + bb.set_terminator(Branch {...}) - **After**: `f.set_branch_terminator(cur, cval, then_bb, else_bb)?` ### 3. try_catch.rs - Jump終端設定の統一化(8箇所) - **Before**: if-let-Some + bb.set_terminator(Jump {...}) - **After**: `f.set_jump_terminator(bb_id, target)?` ## ✅ テスト結果 - `loop_min_while.nyash`: ✅ PASS(0,1,2出力) - `loop_phi_one_sided.nyash`: ✅ PASS(ArrayBox警告のみ) - ビルド: ✅ 88 warnings(既存レベル) ## 🎯 Phase 6進捗 - **Phase 6-1**: ✅ ヘルパーメソッド追加(+46行) - **Phase 6-2**: ✅ ヘルパー適用(-28行) - **実質削減**: -28行(基盤整備込み) ## 📋 次のステップ - **Phase 6-3**: BranchMergeBuilder pattern(~100行削減見込み) - **Phase 6-4**: 全体統合・最終テスト Related: Phase 1-5(3,824行削減)に続く段階的リファクタリング 🐱 にゃーん!実用化成功!
2025-11-01 15:23:28 +09:00
bb.update_phi_input(phi_dst, (bend, latch_val))?;
// 2要素目preheader copy + latchの到達検証
#[cfg(debug_assertions)]
{
if let Some(&pre_copy) = copy_map.get(name) {
crate::mir::phi_core::common::debug_verify_phi_inputs(
f,
cond_bb,
&[(cur_bb, pre_copy), (bend, latch_val)],
);
}
}
}
}
}
}
for (name, &phi) in &phi_map {
vars.insert(name.clone(), phi);
}
Ok(exit_bb)
}