2025-12-08 00:09:45 +09:00
|
|
|
|
//! Phase 33-23: LoopViewBuilder - Loop lowering ディスパッチ箱
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! LoopToJoinLowererからlowering選択責務を分離した専用モジュール。
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! ## 責務
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! - **Pattern検出**: Pattern 1 (Simple While)検出
|
|
|
|
|
|
//! - **Shape検出**: CaseALoweringShape検出
|
|
|
|
|
|
//! - **Lowerer選択**: Shape/名前ベースでlowerer選択
|
|
|
|
|
|
//! - **Lowerer呼び出し**: 適切なlowererに委譲
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! ## 設計思想
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! - **単一責任**: Lowering選択ロジックのみを集約
|
|
|
|
|
|
//! - **拡張性**: 新しいパターン追加が容易
|
|
|
|
|
|
//! - **テスト容易性**: 独立したBoxで単体テスト可能
|
|
|
|
|
|
|
|
|
|
|
|
use crate::mir::join_ir::lowering::generic_case_a;
|
|
|
|
|
|
use crate::mir::join_ir::lowering::loop_scope_shape::{CaseALoweringShape, LoopScopeShape};
|
|
|
|
|
|
use crate::mir::join_ir::lowering::loop_update_summary; // Phase 170-C-2b
|
|
|
|
|
|
use crate::mir::join_ir::JoinModule;
|
|
|
|
|
|
|
|
|
|
|
|
/// Loop lowering ディスパッチ箱
|
|
|
|
|
|
///
|
|
|
|
|
|
/// LoopScopeShapeからパターンを検出し、適切なlowererを選択する。
|
|
|
|
|
|
pub struct LoopViewBuilder {
|
|
|
|
|
|
/// デバッグモード(詳細ログ出力)
|
|
|
|
|
|
debug: bool,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Default for LoopViewBuilder {
|
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
|
Self::new()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl LoopViewBuilder {
|
|
|
|
|
|
/// 新しいLoopViewBuilderを作成
|
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
let debug = std::env::var("NYASH_LOOPTOJOIN_DEBUG")
|
|
|
|
|
|
.map(|v| v == "1")
|
|
|
|
|
|
.unwrap_or(false);
|
|
|
|
|
|
Self { debug }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// LoopScopeShapeからJoinModuleを生成
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # 選択戦略(Phase 170-A-2: Structure-based + Name fallback)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// 1. Pattern 1検出(Simple While Loop)
|
|
|
|
|
|
/// 2. Shape検出(CaseALoweringShape)
|
|
|
|
|
|
/// 3. Shape別ディスパッチ
|
|
|
|
|
|
/// 4. 名前ベースフォールバック(Generic/NotCaseAの場合)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # Arguments
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - `scope`: LoopScopeShape(変数分類・構造情報)
|
|
|
|
|
|
/// - `func_name`: 関数名(名前ベースフォールバック用)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # Returns
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - `Some(JoinModule)`: Lowering成功
|
|
|
|
|
|
/// - `None`: 未サポートパターン(フォールバック経路へ)
|
|
|
|
|
|
pub fn build(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
scope: LoopScopeShape,
|
|
|
|
|
|
func_name: Option<&str>,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
let name = func_name.unwrap_or("");
|
|
|
|
|
|
|
|
|
|
|
|
// Phase 188-Impl-1: Pattern 1 (Simple While Loop) detection
|
|
|
|
|
|
// Try Pattern 1 FIRST for main function (loop_min_while.hako target)
|
|
|
|
|
|
if let Some(result) = self.try_pattern1(&scope, name) {
|
|
|
|
|
|
return Some(result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Phase 170-A-2: Structure-based routing with CaseALoweringShape
|
|
|
|
|
|
let carrier_names: Vec<String> = scope.carriers.iter().cloned().collect();
|
|
|
|
|
|
let update_summary = loop_update_summary::analyze_loop_updates(&carrier_names);
|
|
|
|
|
|
|
|
|
|
|
|
let stub_features = crate::mir::loop_pattern_detection::LoopFeatures {
|
|
|
|
|
|
has_break: false,
|
|
|
|
|
|
has_continue: false,
|
|
|
|
|
|
has_if: false,
|
|
|
|
|
|
has_if_else_phi: false,
|
|
|
|
|
|
carrier_count: scope.carriers.len(),
|
|
|
|
|
|
break_count: 0,
|
|
|
|
|
|
continue_count: 0,
|
|
|
|
|
|
update_summary: Some(update_summary),
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
let has_progress_carrier = scope.progress_carrier.is_some();
|
|
|
|
|
|
let carrier_count = scope.carriers.len();
|
|
|
|
|
|
|
|
|
|
|
|
let shape = CaseALoweringShape::detect_with_updates(
|
|
|
|
|
|
&stub_features,
|
|
|
|
|
|
carrier_count,
|
|
|
|
|
|
has_progress_carrier,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopViewBuilder] Phase 170-C-2b: shape={:?}, name={:?}, carriers={:?}",
|
|
|
|
|
|
shape.name(),
|
|
|
|
|
|
name,
|
|
|
|
|
|
carrier_names
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Shape-based dispatch
|
|
|
|
|
|
self.dispatch_by_shape(shape, scope, name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Pattern 1 (Simple While Loop) 検出・lowering試行
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # 検出条件
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - 関数名に "main" が含まれる
|
|
|
|
|
|
/// - Pinned vars がない
|
|
|
|
|
|
/// - Carriers が1つ以上
|
2025-12-09 19:08:42 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// # Phase 202-A: JoinValueSpace Integration
|
2025-12-08 00:09:45 +09:00
|
|
|
|
fn try_pattern1(&self, scope: &LoopScopeShape, name: &str) -> Option<JoinModule> {
|
|
|
|
|
|
if !name.contains("main") {
|
|
|
|
|
|
return None;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if scope.pinned.is_empty() && !scope.carriers.is_empty() {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] Trying Pattern 1 lowering for {:?}", name);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-09 19:08:42 +09:00
|
|
|
|
// Phase 202-A: Create JoinValueSpace for Pattern 1
|
|
|
|
|
|
use super::join_value_space::JoinValueSpace;
|
|
|
|
|
|
let mut join_value_space = JoinValueSpace::new();
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(result) = super::simple_while_minimal::lower_simple_while_minimal(
|
|
|
|
|
|
scope.clone(),
|
|
|
|
|
|
&mut join_value_space,
|
|
|
|
|
|
) {
|
2025-12-08 00:09:45 +09:00
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] Pattern 1 lowering succeeded for {:?}", name);
|
|
|
|
|
|
}
|
|
|
|
|
|
return Some(result);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] Pattern 1 lowering failed, trying other lowerers");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Shape別にlowererをディスパッチ
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # Shape種別
|
|
|
|
|
|
///
|
|
|
|
|
|
/// - **StringExamination**: skip_ws lowerer
|
|
|
|
|
|
/// - **ArrayAccumulation**: append_defs lowerer
|
|
|
|
|
|
/// - **IterationWithAccumulation**: stage1 lowerer
|
|
|
|
|
|
/// - **Generic/NotCaseA**: 名前ベースフォールバック
|
|
|
|
|
|
fn dispatch_by_shape(
|
|
|
|
|
|
&self,
|
|
|
|
|
|
shape: CaseALoweringShape,
|
|
|
|
|
|
scope: LoopScopeShape,
|
|
|
|
|
|
name: &str,
|
|
|
|
|
|
) -> Option<JoinModule> {
|
|
|
|
|
|
match shape {
|
|
|
|
|
|
CaseALoweringShape::StringExamination => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] Shape: StringExamination → skip_ws lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_skip_ws_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
CaseALoweringShape::ArrayAccumulation => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] Shape: ArrayAccumulation → append_defs lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_append_defs_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
CaseALoweringShape::IterationWithAccumulation => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] Shape: IterationWithAccumulation → stage1 lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_stage1_usingresolver_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
CaseALoweringShape::Generic | CaseALoweringShape::NotCaseA => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopViewBuilder] Shape: {:?} → name-based fallback",
|
|
|
|
|
|
shape.name()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
self.dispatch_by_name(scope, name)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 名前ベースフォールバック(Legacy)
|
|
|
|
|
|
///
|
|
|
|
|
|
/// # Phase 170-A-2 設計
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Shape検出で未分類のループを名前で振り分ける。
|
|
|
|
|
|
/// 将来的にはShape検出を強化してこのフォールバックを削減する。
|
|
|
|
|
|
fn dispatch_by_name(&self, scope: LoopScopeShape, name: &str) -> Option<JoinModule> {
|
|
|
|
|
|
match name {
|
|
|
|
|
|
"Main.skip/1" => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] [fallback] dispatching to skip_ws lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_skip_ws_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
"FuncScannerBox.trim/1" => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] [fallback] dispatching to trim lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_trim_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
"FuncScannerBox.append_defs/2" => {
|
|
|
|
|
|
if self.debug {
|
|
|
|
|
|
eprintln!("[LoopViewBuilder] [fallback] 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!("[LoopViewBuilder] [fallback] dispatching to stage1 lowerer");
|
|
|
|
|
|
}
|
|
|
|
|
|
generic_case_a::lower_case_a_stage1_usingresolver_with_scope(scope)
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => {
|
|
|
|
|
|
// No shape match AND no whitelist match
|
|
|
|
|
|
if self.debug && self.generic_case_a_enabled() {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LoopViewBuilder] generic Case-A candidate: {:?} (no lowerer yet)",
|
|
|
|
|
|
name
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
None
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Phase 32 L-1.2: 汎用Case-A loweringが有効かどうか
|
|
|
|
|
|
fn generic_case_a_enabled(&self) -> bool {
|
|
|
|
|
|
crate::mir::join_ir::env_flag_is_1("NYASH_JOINIR_LOWER_GENERIC")
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_builder_creation() {
|
|
|
|
|
|
let builder = LoopViewBuilder::new();
|
|
|
|
|
|
assert!(!builder.debug || builder.debug); // Just check it compiles
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|