2025-11-26 01:18:32 +09:00
|
|
|
|
//! Phase 31: LoopToJoinLowerer - 統一 Loop→JoinIR 変換箱
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! このモジュールは MIR の LoopForm を JoinIR に変換する統一インターフェースを提供する。
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! ## 設計思想
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! - **単一エントリポイント**: `LoopToJoinLowerer::lower()` ですべてのループを処理
|
|
|
|
|
|
//! - **パターン自動判定**: LoopScopeShape を解析して適切な変換を選択
|
|
|
|
|
|
//! - **既存コード再利用**: generic_case_a の `_with_scope` 関数を内部で呼び出し
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! ## 使用例
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! ```ignore
|
|
|
|
|
|
//! let lowerer = LoopToJoinLowerer::new();
|
|
|
|
|
|
//! let join_module = lowerer.lower(func, &loop_form, &query)?;
|
|
|
|
|
|
//! ```
|
|
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
use crate::mir::control_form::{LoopControlShape, LoopId, LoopRegion};
|
2025-11-26 01:18:32 +09:00
|
|
|
|
use crate::mir::join_ir::lowering::generic_case_a;
|
|
|
|
|
|
use crate::mir::join_ir::lowering::loop_form_intake::intake_loop_form;
|
|
|
|
|
|
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
|
|
|
|
|
use crate::mir::join_ir::JoinModule;
|
|
|
|
|
|
use crate::mir::loop_form::LoopForm;
|
|
|
|
|
|
use crate::mir::phi_core::loop_exit_liveness::LoopExitLivenessBox;
|
|
|
|
|
|
use crate::mir::phi_core::loop_var_classifier::LoopVarClassBox;
|
|
|
|
|
|
use crate::mir::query::MirQueryBox;
|
|
|
|
|
|
use crate::mir::MirFunction;
|
|
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
/// Phase 32 L-1.2: 汎用 Case-A lowering が有効かどうか
|
|
|
|
|
|
///
|
|
|
|
|
|
/// `NYASH_JOINIR_LOWER_GENERIC=1` の場合、関数名フィルタを外して
|
|
|
|
|
|
/// 構造ベースで Case-A ループを拾う。
|
|
|
|
|
|
fn generic_case_a_enabled() -> bool {
|
|
|
|
|
|
crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_LOWER_GENERIC")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 01:18:32 +09:00
|
|
|
|
/// Loop→JoinIR 変換の統一箱
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Phase 31 で導入された統一インターフェース。
|
|
|
|
|
|
/// 全ての MIR LoopForm を JoinIR に正規化する。
|
|
|
|
|
|
pub struct LoopToJoinLowerer {
|
|
|
|
|
|
/// デバッグモード(詳細ログ出力)
|
|
|
|
|
|
debug: bool,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Default for LoopToJoinLowerer {
|
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
|
Self::new()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl LoopToJoinLowerer {
|
|
|
|
|
|
/// 新しい LoopToJoinLowerer を作成
|
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
let debug = std::env::var("NYASH_LOOPTOJOIN_DEBUG")
|
|
|
|
|
|
.map(|v| v == "1")
|
|
|
|
|
|
.unwrap_or(false);
|
|
|
|
|
|
Self { debug }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// MIR LoopForm を JoinIR に変換
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # Arguments
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - `func`: MIR 関数
|
|
|
|
|
|
/// - `loop_form`: 変換対象の LoopForm
|
|
|
|
|
|
/// - `func_name`: 関数名(オプション、ルーティング用)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # Returns
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - `Some(JoinModule)`: 変換成功
|
|
|
|
|
|
/// - `None`: 変換失敗(フォールバック経路へ)
|
|
|
|
|
|
pub fn lower(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
func: &MirFunction,
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
func_name: Option<&str>,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopToJoinLowerer] lower() called for {:?}",
|
|
|
|
|
|
func_name.unwrap_or("<unknown>")
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// Phase 32 L-1.2: 早期フィルタは削除。構造チェック後に条件付きで適用する。
|
2025-11-26 06:02:52 +09:00
|
|
|
|
|
2025-11-26 01:18:32 +09:00
|
|
|
|
// Step 1: MirQuery を構築
|
|
|
|
|
|
let query = MirQueryBox::new(func);
|
|
|
|
|
|
|
|
|
|
|
|
// Step 2: 分類箱を構築(Phase 31 では空箱、将来 MIR 解析で埋める)
|
|
|
|
|
|
let var_classes = LoopVarClassBox::new();
|
|
|
|
|
|
let exit_live = LoopExitLivenessBox::new();
|
|
|
|
|
|
|
|
|
|
|
|
// Step 3: LoopFormIntake を構築
|
|
|
|
|
|
let intake = intake_loop_form(loop_form, &var_classes, &query, func)?;
|
|
|
|
|
|
|
|
|
|
|
|
// Step 4: LoopScopeShape を構築
|
|
|
|
|
|
let scope =
|
|
|
|
|
|
LoopScopeShape::from_existing_boxes(loop_form, &intake, &var_classes, &exit_live, &query, func_name)?;
|
|
|
|
|
|
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopToJoinLowerer] LoopScopeShape built: pinned={:?}, carriers={:?}, exit_live={:?}",
|
|
|
|
|
|
scope.pinned, scope.carriers, scope.exit_live
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// Phase 32 Step 3-C: View メソッドで構造情報を取得(常に実行)
|
|
|
|
|
|
let loop_id = LoopId(0); // 単一ループの場合は 0
|
|
|
|
|
|
let region = loop_form.to_region_view(loop_id);
|
|
|
|
|
|
let control = loop_form.to_control_view(loop_id);
|
|
|
|
|
|
let exit_edges = loop_form.to_exit_edges(loop_id);
|
2025-11-26 08:01:32 +09:00
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// Debug: view ベースの情報をログ
|
|
|
|
|
|
if self.debug {
|
2025-11-26 08:01:32 +09:00
|
|
|
|
eprintln!(
|
2025-11-26 10:15:31 +09:00
|
|
|
|
"[LoopToJoinLowerer] Phase 32 views: func={:?} loop_id={:?} header={:?} exits={:?}",
|
|
|
|
|
|
func_name.unwrap_or("<unknown>"),
|
|
|
|
|
|
loop_id,
|
2025-11-26 08:01:32 +09:00
|
|
|
|
region.header,
|
2025-11-26 10:15:31 +09:00
|
|
|
|
exit_edges.iter().map(|e| e.to).collect::<Vec<_>>()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Phase 32 L-1.1: View ベースの Case-A サポートチェック(構造判定強化)
|
|
|
|
|
|
if !self.is_supported_case_a_loop_view(func, ®ion, &control, &scope) {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopToJoinLowerer] rejected by view-based check: {:?}",
|
|
|
|
|
|
func_name.unwrap_or("<unknown>")
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return None;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Phase 32 L-1.2: 環境変数で分岐
|
|
|
|
|
|
// OFF(既定): 従来の minimal 4 本だけ
|
|
|
|
|
|
// ON: 構造だけで通す(関数名フィルタを外す)
|
|
|
|
|
|
if !generic_case_a_enabled() {
|
|
|
|
|
|
if !func_name.map_or(false, super::loop_scope_shape::is_case_a_minimal_target) {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopToJoinLowerer] rejected by name filter (generic disabled): {:?}",
|
|
|
|
|
|
func_name.unwrap_or("<unknown>")
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return None;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopToJoinLowerer] generic Case-A enabled, allowing {:?}",
|
|
|
|
|
|
func_name.unwrap_or("<unknown>")
|
2025-11-26 08:01:32 +09:00
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 01:18:32 +09:00
|
|
|
|
// Step 5: パターンに応じた lowering を実行
|
|
|
|
|
|
self.lower_with_scope(scope, func_name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
/// Case-A ループとしてサポートされているかチェック(View ベース版)
|
2025-11-26 06:02:52 +09:00
|
|
|
|
///
|
2025-11-26 10:15:31 +09:00
|
|
|
|
/// Phase 32 L-1.2: 純粋な構造チェックのみ(関数名フィルタは lower() 側で適用)
|
2025-11-26 06:02:52 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// # Case-A の定義
|
|
|
|
|
|
///
|
2025-11-26 10:15:31 +09:00
|
|
|
|
/// - 単一出口(exits が 1 箇所以下)
|
|
|
|
|
|
/// - ヘッダブロックの succ が 2 つ(cond true/false)
|
2025-11-26 06:02:52 +09:00
|
|
|
|
/// - ループ変数または固定変数が存在
|
|
|
|
|
|
/// - ネストループなし(将来チェック追加予定)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # Arguments
|
|
|
|
|
|
///
|
2025-11-26 10:15:31 +09:00
|
|
|
|
/// - `func`: MIR 関数(ヘッダ succ チェック用)
|
|
|
|
|
|
/// - `region`: LoopRegion(ブロック構造)
|
|
|
|
|
|
/// - `control`: LoopControlShape(制御フロー辺)
|
2025-11-26 06:02:52 +09:00
|
|
|
|
/// - `scope`: LoopScopeShape(変数分類用)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # Returns
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - `true`: Case-A として lowering 可能
|
|
|
|
|
|
/// - `false`: 未サポート(フォールバック経路へ)
|
2025-11-26 10:15:31 +09:00
|
|
|
|
fn is_supported_case_a_loop_view(
|
2025-11-26 01:18:32 +09:00
|
|
|
|
&self,
|
2025-11-26 10:15:31 +09:00
|
|
|
|
func: &MirFunction,
|
|
|
|
|
|
region: &LoopRegion,
|
|
|
|
|
|
control: &LoopControlShape,
|
2025-11-26 06:02:52 +09:00
|
|
|
|
scope: &LoopScopeShape,
|
|
|
|
|
|
) -> bool {
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// Phase 32 L-1.2: 純粋な構造チェックのみ
|
|
|
|
|
|
// 関数名フィルタは lower() 側で generic_case_a_enabled() に応じて適用
|
|
|
|
|
|
|
|
|
|
|
|
// 1) 単一出口 (Case-A 限定: exits が 1 箇所以下)
|
|
|
|
|
|
// Note: break_targets ベースなので、条件 false による自然な出口は含まない
|
|
|
|
|
|
// 将来 Case-B/C で複数出口を許可する場合はここを緩める
|
|
|
|
|
|
if control.exits.len() > 1 {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopToJoinLowerer] rejected: multiple exits ({}) - Case-A requires single exit",
|
|
|
|
|
|
control.exits.len()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2025-11-26 06:02:52 +09:00
|
|
|
|
return false;
|
2025-11-26 01:18:32 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// 2) ヘッダブロックの succ が 2 つ(cond true → body, cond false → exit)
|
|
|
|
|
|
// これにより while(cond) 形式のループのみを対象とする
|
|
|
|
|
|
if let Some(header_block) = func.blocks.get(®ion.header) {
|
|
|
|
|
|
let succ_count = header_block.successors.len();
|
|
|
|
|
|
if succ_count != 2 {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopToJoinLowerer] rejected: header {:?} has {} successors (expected 2)",
|
|
|
|
|
|
region.header,
|
|
|
|
|
|
succ_count
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// ヘッダブロックが見つからない(異常ケース)
|
2025-11-26 01:18:32 +09:00
|
|
|
|
if self.debug {
|
2025-11-26 06:02:52 +09:00
|
|
|
|
eprintln!(
|
2025-11-26 10:15:31 +09:00
|
|
|
|
"[LoopToJoinLowerer] rejected: header block {:?} not found",
|
|
|
|
|
|
region.header
|
2025-11-26 06:02:52 +09:00
|
|
|
|
);
|
2025-11-26 01:18:32 +09:00
|
|
|
|
}
|
2025-11-26 06:02:52 +09:00
|
|
|
|
return false;
|
2025-11-26 01:18:32 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// 3) ループ変数または固定変数がある(空ループは対象外)
|
2025-11-26 06:02:52 +09:00
|
|
|
|
if scope.carriers.is_empty() && scope.pinned.is_empty() {
|
2025-11-26 01:18:32 +09:00
|
|
|
|
if self.debug {
|
2025-11-26 06:02:52 +09:00
|
|
|
|
eprintln!("[LoopToJoinLowerer] rejected: no carriers or pinned vars");
|
2025-11-26 01:18:32 +09:00
|
|
|
|
}
|
2025-11-26 06:02:52 +09:00
|
|
|
|
return false;
|
2025-11-26 01:18:32 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 06:02:52 +09:00
|
|
|
|
true
|
|
|
|
|
|
}
|
2025-11-26 01:18:32 +09:00
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// Note: is_supported_case_a_loop (legacy) は Phase 32 で削除済み
|
|
|
|
|
|
// 代替: is_supported_case_a_loop_view() を使用
|
|
|
|
|
|
|
2025-11-26 06:02:52 +09:00
|
|
|
|
/// LoopScopeShape から JoinModule を生成(内部メソッド)
|
|
|
|
|
|
///
|
2025-11-26 10:15:31 +09:00
|
|
|
|
/// Phase 32 L-1.2: 関数名で 4 パターン + 汎用 Case-A にディスパッチ
|
2025-11-26 06:02:52 +09:00
|
|
|
|
fn lower_with_scope(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
scope: LoopScopeShape,
|
|
|
|
|
|
func_name: Option<&str>,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
let name = func_name.unwrap_or("");
|
|
|
|
|
|
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// Phase 32 L-1.2: minimal 4 本にマッチしたらそれぞれの lowerer を使う
|
|
|
|
|
|
// マッチしない場合は汎用 Case-A(まだ未実装、None を返す)
|
2025-11-26 06:02:52 +09:00
|
|
|
|
let result = match name {
|
|
|
|
|
|
"Main.skip/1" => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopToJoinLowerer] dispatching to skip_ws lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_skip_ws_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
"FuncScannerBox.trim/1" => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopToJoinLowerer] dispatching to trim lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_trim_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
"FuncScannerBox.append_defs/2" => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopToJoinLowerer] dispatching to append_defs lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_append_defs_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
"Stage1UsingResolverBox.resolve_for_source/5" => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopToJoinLowerer] dispatching to stage1 lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_stage1_usingresolver_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => {
|
2025-11-26 10:15:31 +09:00
|
|
|
|
// Phase 32 L-1.2: 汎用 Case-A 候補
|
|
|
|
|
|
// ここに来るのは NYASH_JOINIR_LOWER_GENERIC=1 の時だけ
|
|
|
|
|
|
// TODO: 汎用 Case-A lowerer を実装したらここで呼び出す
|
2025-11-26 06:02:52 +09:00
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
2025-11-26 10:15:31 +09:00
|
|
|
|
"[LoopToJoinLowerer] generic Case-A candidate: {:?} (no lowerer yet)",
|
2025-11-26 06:02:52 +09:00
|
|
|
|
name
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
None
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
2025-11-26 01:18:32 +09:00
|
|
|
|
|
2025-11-26 06:02:52 +09:00
|
|
|
|
result
|
2025-11-26 01:18:32 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ========================================
|
2025-11-26 10:28:03 +09:00
|
|
|
|
// Case-A helpers for specific function patterns
|
2025-11-26 01:18:32 +09:00
|
|
|
|
// ========================================
|
|
|
|
|
|
|
2025-11-26 10:28:03 +09:00
|
|
|
|
/// Case-A 汎用 lowerer の「Main.skip/1 用」薄いラッパー。
|
|
|
|
|
|
/// 実際のロジックは `lower` に集約されている。
|
|
|
|
|
|
pub fn lower_case_a_for_skip_ws(
|
2025-11-26 01:18:32 +09:00
|
|
|
|
&self,
|
|
|
|
|
|
func: &MirFunction,
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
self.lower(func, loop_form, Some("Main.skip/1"))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 10:28:03 +09:00
|
|
|
|
/// Case-A 汎用 lowerer の「FuncScannerBox.trim/1 用」薄いラッパー。
|
|
|
|
|
|
/// 実際のロジックは `lower` に集約されている。
|
|
|
|
|
|
pub fn lower_case_a_for_trim(
|
2025-11-26 01:18:32 +09:00
|
|
|
|
&self,
|
|
|
|
|
|
func: &MirFunction,
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
self.lower(func, loop_form, Some("FuncScannerBox.trim/1"))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 10:28:03 +09:00
|
|
|
|
/// Case-A 汎用 lowerer の「FuncScannerBox.append_defs/2 用」薄いラッパー。
|
|
|
|
|
|
/// 実際のロジックは `lower` に集約されている。
|
|
|
|
|
|
pub fn lower_case_a_for_append_defs(
|
2025-11-26 01:18:32 +09:00
|
|
|
|
&self,
|
|
|
|
|
|
func: &MirFunction,
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
self.lower(func, loop_form, Some("FuncScannerBox.append_defs/2"))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 10:28:03 +09:00
|
|
|
|
/// Case-A 汎用 lowerer の「Stage1UsingResolverBox.resolve_for_source/5 用」薄いラッパー。
|
|
|
|
|
|
/// 実際のロジックは `lower` に集約されている。
|
|
|
|
|
|
pub fn lower_case_a_for_stage1_resolver(
|
2025-11-26 01:18:32 +09:00
|
|
|
|
&self,
|
|
|
|
|
|
func: &MirFunction,
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
self.lower(func, loop_form, Some("Stage1UsingResolverBox.resolve_for_source/5"))
|
|
|
|
|
|
}
|
2025-11-26 10:47:35 +09:00
|
|
|
|
|
|
|
|
|
|
/// Case-A 汎用 lowerer の「StageBBodyExtractorBox.build_body_src/2 用」薄いラッパー。
|
|
|
|
|
|
/// 実際のロジックは `lower` に集約されている。
|
|
|
|
|
|
pub fn lower_case_a_for_stageb_body(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
func: &MirFunction,
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
self.lower(func, loop_form, Some("StageBBodyExtractorBox.build_body_src/2"))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Case-A 汎用 lowerer の「StageBFuncScannerBox.scan_all_boxes/1 用」薄いラッパー。
|
|
|
|
|
|
/// 実際のロジックは `lower` に集約されている。
|
|
|
|
|
|
pub fn lower_case_a_for_stageb_funcscanner(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
func: &MirFunction,
|
|
|
|
|
|
loop_form: &LoopForm,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
self.lower(func, loop_form, Some("StageBFuncScannerBox.scan_all_boxes/1"))
|
|
|
|
|
|
}
|
2025-11-26 01:18:32 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_lowerer_creation() {
|
|
|
|
|
|
let lowerer = LoopToJoinLowerer::new();
|
|
|
|
|
|
assert!(!lowerer.debug || lowerer.debug); // Just check it compiles
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|