refactor(joinir): Phase 89 リファクタリング - 3) Frontend再帰探索
変更内容: - Break/Continue/Return 検出を再帰的探索に変更 - has_break_in_loop_body(): top-level If のみ → 再帰的探索 - has_continue_in_loop_body(): top-level If のみ → 再帰的探索 - has_return_in_loop_body(): top-level If のみ → 再帰的探索 - ネストした If/Block 内のステートメントも検出可能に - ヘルパー関数追加: - has_break_recursive() - has_continue_recursive() - has_return_recursive() 理由: - Phase 90+ で合成形パターン(ネストした If/Block)に対応する準備 - 現状では top-level のみチェックしているため、深い階層で誤判定の可能性 影響範囲: - loop_frontend_binding.rs のルーティングロジック - Phase 90 の合成形パターンで正確な検出が可能に テスト結果: - lib tests: 993 passed (回帰なし) - normalized_dev tests: 61 passed / 1 failed (ベースライン維持) Generated with Claude Code Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user