fix(joinir): avoid false rejects in balanced depth-scan policy

This commit is contained in:
nyash-codex
2025-12-17 22:52:29 +09:00
parent d42117ac5f
commit 6036627920

View File

@ -49,7 +49,8 @@ fn classify_balanced_depth_scan(
};
let summary = match extract_depth_scan_shape(body, &loop_counter_name, open, close) {
Ok(v) => v,
Ok(Some(v)) => v,
Ok(None) => return PolicyDecision::None,
Err(reason) => return PolicyDecision::Reject(reason),
};
@ -128,7 +129,7 @@ fn extract_depth_scan_shape(
loop_counter_name: &str,
open: &str,
close: &str,
) -> Result<DepthScanShapeSummary, String> {
) -> Result<Option<DepthScanShapeSummary>, String> {
if body.is_empty() {
return Err(error_tags::freeze(
"[phase107/balanced_depth_scan/contract/empty_body] empty loop body",
@ -146,16 +147,20 @@ fn extract_depth_scan_shape(
}
// Find `local ch = s.substring(i, i+1)` (name may vary, but must be a single local).
let ch_name = find_substring_body_local(body, loop_counter_name).ok_or_else(|| {
error_tags::freeze(
"[phase107/balanced_depth_scan/contract/missing_ch] missing body-local `ch = s.substring(i, i+1)`",
)
})?;
// If missing, this is not a depth-scan candidate.
let Some(ch_name) = find_substring_body_local(body, loop_counter_name) else {
return Ok(None);
};
// Find open/close branches and extract `depth` name.
let (depth_from_open, depth_from_close, has_return_i) =
find_depth_branches(body, &ch_name, loop_counter_name, open, close)?;
let (Some(depth_from_open), Some(depth_from_close)) = (depth_from_open, depth_from_close) else {
// Not a depth-scan candidate: no `if ch == open/close` pair.
return Ok(None);
};
if depth_from_open != depth_from_close {
return Err(error_tags::freeze(&format!(
"[phase107/balanced_depth_scan/contract/depth_mismatch] depth variable differs: open='{}', close='{}'",
@ -189,11 +194,11 @@ fn extract_depth_scan_shape(
)));
}
Ok(DepthScanShapeSummary {
Ok(Some(DepthScanShapeSummary {
ch_name,
depth_name: depth_from_open,
declared_locals,
})
}))
}
fn scan_control_flow(node: &ASTNode, return_count: &mut usize) -> Result<(), String> {
@ -276,7 +281,7 @@ fn find_depth_branches(
loop_counter_name: &str,
open: &str,
close: &str,
) -> Result<(String, String, bool), String> {
) -> Result<(Option<String>, Option<String>, bool), String> {
let mut open_depth: Option<String> = None;
let mut close_depth: Option<String> = None;
let mut has_return_i = false;
@ -314,18 +319,6 @@ fn find_depth_branches(
has_return_i = find_depth_zero_return(then_body, &depth_name, loop_counter_name);
}
}
let open_depth = open_depth.ok_or_else(|| {
error_tags::freeze(
"[phase107/balanced_depth_scan/contract/missing_open_branch] missing `if ch == open { depth = depth + 1 }`",
)
})?;
let close_depth = close_depth.ok_or_else(|| {
error_tags::freeze(
"[phase107/balanced_depth_scan/contract/missing_close_branch] missing `if ch == close { depth = depth - 1 ... }`",
)
})?;
Ok((open_depth, close_depth, has_return_i))
}