feat(joinir): Phase 33-9.1 Loop/If lowering responsibility separation
Implement clear separation between Loop and If lowering responsibilities: **Guard Implementation:** - Add is_loop_lowered_function() to identify 6 Loop-dedicated functions - Exclude Loop functions from If lowering path in try_lower_if_to_joinir() - Enforce "1 function → 1 lowering" principle **Documentation:** - Add responsibility comments to loop_to_join.rs - Add responsibility comments to if_select.rs and if_merge.rs - Update if_joinir_design.md with Phase 33-9.1 section **Testing:** - Add unit test test_is_loop_lowered_function() (PASS) - Verify no regression in existing JoinIR tests **Loop-dedicated functions (6):** - Main.skip/1 - FuncScannerBox.trim/1 - FuncScannerBox.append_defs/2 - Stage1UsingResolverBox.resolve_for_source/5 - StageBBodyExtractorBox.build_body_src/2 - StageBFuncScannerBox.scan_all_boxes/1 This prevents future conflicts when both Loop and If lowering expand. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Submodule docs/private updated: 80b08dc5f8...f224c84970
@ -5,6 +5,14 @@
|
|||||||
//! Phase 33-7 制約:
|
//! Phase 33-7 制約:
|
||||||
//! - return パターンのみ(continuation は Phase 33-8)
|
//! - return パターンのみ(continuation は Phase 33-8)
|
||||||
//! - k_next=None のみ
|
//! - k_next=None のみ
|
||||||
|
//!
|
||||||
|
//! ## 責務分離(Phase 33-9.1)
|
||||||
|
//!
|
||||||
|
//! **IfMergeLowerer の責務**:
|
||||||
|
//! - 複数変数を持つ if/else を IfMerge 命令に変換する
|
||||||
|
//!
|
||||||
|
//! **非責務**:
|
||||||
|
//! - Loop の PHI には触らない(Loop lowering の責務)
|
||||||
|
|
||||||
use crate::mir::join_ir::{JoinInst, MergePair};
|
use crate::mir::join_ir::{JoinInst, MergePair};
|
||||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||||
|
|||||||
@ -1,6 +1,14 @@
|
|||||||
//! Phase 33: If/Else の Select 命令への lowering
|
//! Phase 33: If/Else の Select 命令への lowering
|
||||||
//!
|
//!
|
||||||
//! 最小の if/else(副作用なし、単純な値選択)を JoinInst::Select に変換する。
|
//! 最小の if/else(副作用なし、単純な値選択)を JoinInst::Select に変換する。
|
||||||
|
//!
|
||||||
|
//! ## 責務分離(Phase 33-9.1)
|
||||||
|
//!
|
||||||
|
//! **IfSelectLowerer の責務**:
|
||||||
|
//! - 単純 if/else(副作用なし、単一変数)を Select 命令に変換する
|
||||||
|
//!
|
||||||
|
//! **非責務**:
|
||||||
|
//! - Loop の PHI には触らない(Loop lowering の責務)
|
||||||
|
|
||||||
use crate::mir::join_ir::JoinInst;
|
use crate::mir::join_ir::JoinInst;
|
||||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||||
|
|||||||
@ -8,6 +8,16 @@
|
|||||||
//! - **パターン自動判定**: LoopScopeShape を解析して適切な変換を選択
|
//! - **パターン自動判定**: LoopScopeShape を解析して適切な変換を選択
|
||||||
//! - **既存コード再利用**: generic_case_a の `_with_scope` 関数を内部で呼び出し
|
//! - **既存コード再利用**: generic_case_a の `_with_scope` 関数を内部で呼び出し
|
||||||
//!
|
//!
|
||||||
|
//! ## 責務分離(Phase 33-9.1)
|
||||||
|
//!
|
||||||
|
//! **LoopToJoinLowerer の責務**:
|
||||||
|
//! - LoopForm / LoopScopeShape を入力に、「ループだけ」を JoinIR (loop_step/k_exit) に正規化する
|
||||||
|
//! - Loop PHI を関数引数に変換する
|
||||||
|
//!
|
||||||
|
//! **非責務**:
|
||||||
|
//! - if/else の PHI には触らない(If lowering の責務)
|
||||||
|
//! - If の Select/IfMerge などは別ロワー(if_select.rs / if_merge.rs)の責務
|
||||||
|
//!
|
||||||
//! ## 使用例
|
//! ## 使用例
|
||||||
//!
|
//!
|
||||||
//! ```ignore
|
//! ```ignore
|
||||||
|
|||||||
@ -47,6 +47,34 @@ pub use stageb_funcscanner::lower_stageb_funcscanner_to_joinir;
|
|||||||
use crate::mir::join_ir::JoinInst;
|
use crate::mir::join_ir::JoinInst;
|
||||||
use crate::mir::{BasicBlockId, MirFunction};
|
use crate::mir::{BasicBlockId, MirFunction};
|
||||||
|
|
||||||
|
/// Phase 33-9.1: Loop lowering対象関数の判定
|
||||||
|
///
|
||||||
|
/// これらの関数は Phase 32/33 で LoopToJoinLowerer によって処理されます。
|
||||||
|
/// If lowering (Select/IfMerge) の対象から除外することで、Loop/If の責務を明確に分離します。
|
||||||
|
///
|
||||||
|
/// ## 対象関数(6本)
|
||||||
|
/// - Main.skip/1: 空白スキップループ
|
||||||
|
/// - FuncScannerBox.trim/1: 前後空白削除ループ
|
||||||
|
/// - FuncScannerBox.append_defs/2: 配列結合ループ
|
||||||
|
/// - Stage1UsingResolverBox.resolve_for_source/5: using解析ループ
|
||||||
|
/// - StageBBodyExtractorBox.build_body_src/2: Stage-B本体抽出ループ
|
||||||
|
/// - StageBFuncScannerBox.scan_all_boxes/1: Stage-B Box走査ループ
|
||||||
|
///
|
||||||
|
/// ## 将来の拡張
|
||||||
|
/// NYASH_JOINIR_LOWER_GENERIC=1 で汎用 Case-A ループにも拡張可能
|
||||||
|
pub(crate) fn is_loop_lowered_function(name: &str) -> bool {
|
||||||
|
const LOOP_LOWERED_FUNCTIONS: &[&str] = &[
|
||||||
|
"Main.skip/1",
|
||||||
|
"FuncScannerBox.trim/1",
|
||||||
|
"FuncScannerBox.append_defs/2",
|
||||||
|
"Stage1UsingResolverBox.resolve_for_source/5",
|
||||||
|
"StageBBodyExtractorBox.build_body_src/2",
|
||||||
|
"StageBFuncScannerBox.scan_all_boxes/1",
|
||||||
|
];
|
||||||
|
|
||||||
|
LOOP_LOWERED_FUNCTIONS.contains(&name)
|
||||||
|
}
|
||||||
|
|
||||||
/// Phase 33-7: Try to lower if/else to JoinIR Select/IfMerge instruction
|
/// Phase 33-7: Try to lower if/else to JoinIR Select/IfMerge instruction
|
||||||
///
|
///
|
||||||
/// Scope:
|
/// Scope:
|
||||||
@ -73,6 +101,13 @@ pub fn try_lower_if_to_joinir(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase 33-9.1: Loop専任関数の除外(Loop/If責務分離)
|
||||||
|
// Loop lowering対象関数はIf loweringの対象外にすることで、
|
||||||
|
// 1関数につき1 loweringの原則を保証します
|
||||||
|
if is_loop_lowered_function(&func.signature.name) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// Phase 33-8: デバッグログレベル取得(0-3)
|
// Phase 33-8: デバッグログレベル取得(0-3)
|
||||||
let debug_level = crate::config::env::joinir_debug_level();
|
let debug_level = crate::config::env::joinir_debug_level();
|
||||||
let _debug = debug || debug_level >= 1;
|
let _debug = debug || debug_level >= 1;
|
||||||
@ -148,3 +183,40 @@ pub fn try_lower_if_to_joinir(
|
|||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Phase 33-9.1: is_loop_lowered_function() の動作確認
|
||||||
|
#[test]
|
||||||
|
fn test_is_loop_lowered_function() {
|
||||||
|
// Loop 専任関数(6本)は true を返す
|
||||||
|
assert!(is_loop_lowered_function("Main.skip/1"));
|
||||||
|
assert!(is_loop_lowered_function("FuncScannerBox.trim/1"));
|
||||||
|
assert!(is_loop_lowered_function("FuncScannerBox.append_defs/2"));
|
||||||
|
assert!(is_loop_lowered_function(
|
||||||
|
"Stage1UsingResolverBox.resolve_for_source/5"
|
||||||
|
));
|
||||||
|
assert!(is_loop_lowered_function(
|
||||||
|
"StageBBodyExtractorBox.build_body_src/2"
|
||||||
|
));
|
||||||
|
assert!(is_loop_lowered_function(
|
||||||
|
"StageBFuncScannerBox.scan_all_boxes/1"
|
||||||
|
));
|
||||||
|
|
||||||
|
// If lowering 対象関数は false を返す
|
||||||
|
assert!(!is_loop_lowered_function("IfSelectTest.simple_return/0"));
|
||||||
|
assert!(!is_loop_lowered_function("IfMergeTest.multiple_true/0"));
|
||||||
|
assert!(!is_loop_lowered_function(
|
||||||
|
"JsonShapeToMap._read_value_from_pair/1"
|
||||||
|
));
|
||||||
|
assert!(!is_loop_lowered_function(
|
||||||
|
"Stage1JsonScannerBox.value_start_after_key_pos/2"
|
||||||
|
));
|
||||||
|
|
||||||
|
// 一般的な関数も false を返す
|
||||||
|
assert!(!is_loop_lowered_function("SomeBox.some_method/3"));
|
||||||
|
assert!(!is_loop_lowered_function("Main.main/0"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user