diff --git a/src/mir/join_ir/frontend/ast_lowerer/analysis.rs b/src/mir/join_ir/frontend/ast_lowerer/analysis.rs index d6796f54..bc4cbeb8 100644 --- a/src/mir/join_ir/frontend/ast_lowerer/analysis.rs +++ b/src/mir/join_ir/frontend/ast_lowerer/analysis.rs @@ -345,10 +345,10 @@ impl AstToJoinIrLowerer { vars } - /// Phase 85: Loop body に Break があるかチェック + /// Phase 85: Loop body に Break があるかチェック(再帰的探索) /// /// ループパターン検出(loop_frontend_binding)で使用される。 - /// If文内のBreakステートメントを検出する。 + /// ネストした If/Block 内の Break ステートメントも検出する。 /// /// # Arguments /// * `loop_body` - ループ本体のステートメント配列 @@ -356,33 +356,46 @@ impl AstToJoinIrLowerer { /// # Returns /// ループ内にBreakがあればtrue pub(crate) fn has_break_in_loop_body(loop_body: &[serde_json::Value]) -> bool { - loop_body.iter().any(|stmt| { - if stmt["type"].as_str() == Some("If") { - let then_has = stmt["then"] - .as_array() - .map(|body| { - body.iter() - .any(|s| s["type"].as_str() == Some("Break")) - }) - .unwrap_or(false); - let else_has = stmt["else"] - .as_array() - .map(|body| { - body.iter() - .any(|s| s["type"].as_str() == Some("Break")) - }) - .unwrap_or(false); - then_has || else_has - } else { - false - } - }) + Self::has_break_recursive(loop_body) } - /// Phase 85: Loop body に Continue があるかチェック + /// 再帰的に Break を探索 + fn has_break_recursive(stmts: &[serde_json::Value]) -> bool { + for stmt in stmts { + match stmt["type"].as_str() { + Some("Break") => return true, + Some("If") => { + // then 分岐を再帰探索 + if let Some(then_body) = stmt["then"].as_array() { + if Self::has_break_recursive(then_body) { + return true; + } + } + // else 分岐を再帰探索 + if let Some(else_body) = stmt["else"].as_array() { + if Self::has_break_recursive(else_body) { + return true; + } + } + } + Some("Block") => { + // Block 内を再帰探索 + if let Some(block_body) = stmt["body"].as_array() { + if Self::has_break_recursive(block_body) { + return true; + } + } + } + _ => {} + } + } + false + } + + /// Phase 85: Loop body に Continue があるかチェック(再帰的探索) /// /// ループパターン検出(loop_frontend_binding)で使用される。 - /// If文内のContinueステートメントを検出する。 + /// ネストした If/Block 内の Continue ステートメントも検出する。 /// /// # Arguments /// * `loop_body` - ループ本体のステートメント配列 @@ -390,33 +403,46 @@ impl AstToJoinIrLowerer { /// # Returns /// ループ内にContinueがあればtrue pub(crate) fn has_continue_in_loop_body(loop_body: &[serde_json::Value]) -> bool { - loop_body.iter().any(|stmt| { - if stmt["type"].as_str() == Some("If") { - let then_has = stmt["then"] - .as_array() - .map(|body| { - body.iter() - .any(|s| s["type"].as_str() == Some("Continue")) - }) - .unwrap_or(false); - let else_has = stmt["else"] - .as_array() - .map(|body| { - body.iter() - .any(|s| s["type"].as_str() == Some("Continue")) - }) - .unwrap_or(false); - then_has || else_has - } else { - false - } - }) + Self::has_continue_recursive(loop_body) } - /// Phase 89: Loop body に Return があるかチェック + /// 再帰的に Continue を探索 + fn has_continue_recursive(stmts: &[serde_json::Value]) -> bool { + for stmt in stmts { + match stmt["type"].as_str() { + Some("Continue") => return true, + Some("If") => { + // then 分岐を再帰探索 + if let Some(then_body) = stmt["then"].as_array() { + if Self::has_continue_recursive(then_body) { + return true; + } + } + // else 分岐を再帰探索 + if let Some(else_body) = stmt["else"].as_array() { + if Self::has_continue_recursive(else_body) { + return true; + } + } + } + Some("Block") => { + // Block 内を再帰探索 + if let Some(block_body) = stmt["body"].as_array() { + if Self::has_continue_recursive(block_body) { + return true; + } + } + } + _ => {} + } + } + false + } + + /// Phase 89: Loop body に Return があるかチェック(再帰的探索) /// /// ループパターン検出(loop_frontend_binding)で使用される。 - /// If文内のReturnステートメントを検出する(loop-internal early return)。 + /// ネストした If/Block 内の Return ステートメントも検出する(loop-internal early return)。 /// /// # Arguments /// * `loop_body` - ループ本体のステートメント配列 @@ -424,26 +450,39 @@ impl AstToJoinIrLowerer { /// # Returns /// ループ内にReturnがあればtrue pub(crate) fn has_return_in_loop_body(loop_body: &[serde_json::Value]) -> bool { - loop_body.iter().any(|stmt| { - if stmt["type"].as_str() == Some("If") { - let then_has = stmt["then"] - .as_array() - .map(|body| { - body.iter() - .any(|s| s["type"].as_str() == Some("Return")) - }) - .unwrap_or(false); - let else_has = stmt["else"] - .as_array() - .map(|body| { - body.iter() - .any(|s| s["type"].as_str() == Some("Return")) - }) - .unwrap_or(false); - then_has || else_has - } else { - false + Self::has_return_recursive(loop_body) + } + + /// 再帰的に Return を探索 + fn has_return_recursive(stmts: &[serde_json::Value]) -> bool { + for stmt in stmts { + match stmt["type"].as_str() { + Some("Return") => return true, + Some("If") => { + // then 分岐を再帰探索 + if let Some(then_body) = stmt["then"].as_array() { + if Self::has_return_recursive(then_body) { + return true; + } + } + // else 分岐を再帰探索 + if let Some(else_body) = stmt["else"].as_array() { + if Self::has_return_recursive(else_body) { + return true; + } + } + } + Some("Block") => { + // Block 内を再帰探索 + if let Some(block_body) = stmt["body"].as_array() { + if Self::has_return_recursive(block_body) { + return true; + } + } + } + _ => {} } - }) + } + false } }