refactor(pattern2): move promotion decision into pattern2/api SSOT
Phase 263 P0.2: pattern2/api/ フォルダ化 - 入口SSOTの物理固定
目的: PromoteDecision/try_promote の参照点を1箇所に閉じ込めて、迷子防止
Changes:
1. 新規フォルダ構造:
- pattern2/api/mod.rs - 入口SSOT(try_promote と PromoteDecision を再export)
- pattern2/api/promote_decision.rs - PromoteDecision/PromoteStepResult 型定義
- pattern2/api/promote_runner.rs - try_promote(...) 実装(SSOT entry point)
- pattern2/mod.rs - api モジュールを公開
2. 移動/抽出:
- PromoteDecision enum を promote_step_box.rs → pattern2/api/promote_decision.rs へ
- promote_and_prepare_carriers を try_promote として pattern2/api/promote_runner.rs へ抽出
3. promote_step_box.rs を薄いラッパに縮退(35行, -177行):
- pattern2::api::try_promote を呼び出すだけの互換用ラッパ
- 将来的に削除予定(deprecated)
4. orchestrator を新API に書き換え:
- use super::pattern2::api::{try_promote, PromoteDecision};
- try_promote(...) を直接呼び出し
5. 参照確認:
- rg で確認: すべての参照が pattern2::api 経由に収束 ✅
検証:
- cargo test --lib: 1368/1368 PASS ✅
- quick smoke: 45/46 PASS ✅(悪化なし)
- 参照点が pattern2/api に一本化され、迷子防止を物理的に保証
This commit is contained in:
@ -60,6 +60,7 @@ pub(in crate::mir::builder) mod escape_pattern_recognizer; // Phase 91 P5b
|
||||
pub(in crate::mir::builder) mod common_init;
|
||||
pub(in crate::mir::builder) mod loop_true_counter_extractor; // Phase 104: loop(true) counter extraction for Pattern2
|
||||
pub(in crate::mir::builder) mod read_digits_break_condition_box; // Phase 104: break cond normalization for read_digits(loop(true))
|
||||
pub(in crate::mir::builder) mod pattern2; // Phase 263 P0.2: Pattern2 module (api/ SSOT entry point)
|
||||
pub(in crate::mir::builder) mod pattern2_break_condition_policy_router; // Phase 105: policy router box for Pattern2 break condition
|
||||
pub(in crate::mir::builder) mod pattern2_policy_router; // Phase 108: unified Pattern2 policy router (balanced/read_digits/default)
|
||||
pub(in crate::mir::builder) mod pattern2_inputs_facts_box; // Phase 105: Pattern2 input facts (analysis only)
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
//! Phase 263 P0.2: Pattern2 promotion API (entry point SSOT)
|
||||
//!
|
||||
//! This module is the single entry point for Pattern2 promotion logic.
|
||||
//! All callers should use this module's exports instead of accessing internals.
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use super::pattern2::api::{try_promote, PromoteDecision};
|
||||
//!
|
||||
//! match try_promote(builder, condition, body, inputs, debug, verbose)? {
|
||||
//! PromoteDecision::Promoted(result) => { /* ... */ }
|
||||
//! PromoteDecision::NotApplicable => { /* fallback to next path */ }
|
||||
//! PromoteDecision::Freeze(reason) => { /* fail-fast */ }
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
mod promote_decision;
|
||||
mod promote_runner;
|
||||
|
||||
// Re-export the SSOT types and functions
|
||||
pub(in crate::mir::builder) use promote_decision::{PromoteDecision, PromoteStepResult};
|
||||
pub(in crate::mir::builder) use promote_runner::try_promote;
|
||||
@ -0,0 +1,26 @@
|
||||
//! Phase 263 P0.2: Promotion decision types (SSOT)
|
||||
//!
|
||||
//! PromoteDecision enum eliminates Option<_> wrapping ambiguity by making
|
||||
//! the decision explicit. All Pattern2 promotion logic flows through this type.
|
||||
|
||||
use super::super::super::pattern2_inputs_facts_box::Pattern2Inputs;
|
||||
|
||||
pub(crate) struct PromoteStepResult {
|
||||
pub inputs: Pattern2Inputs,
|
||||
}
|
||||
|
||||
/// Phase 263 P0.1: Promotion decision for Pattern2 LoopBodyLocal handling
|
||||
///
|
||||
/// Eliminates Option<_> wrapping ambiguity by making decision explicit.
|
||||
pub(crate) enum PromoteDecision {
|
||||
/// Promotion succeeded - Pattern2 can proceed
|
||||
Promoted(PromoteStepResult),
|
||||
|
||||
/// Pattern2 not applicable (e.g., reassigned LoopBodyLocal, no promotable pattern)
|
||||
/// → Router should try next path (legacy binding, etc.)
|
||||
NotApplicable,
|
||||
|
||||
/// Pattern2 should handle this but implementation is missing
|
||||
/// → Fail-Fast with error message
|
||||
Freeze(String),
|
||||
}
|
||||
@ -0,0 +1,180 @@
|
||||
//! Phase 263 P0.2: Pattern2 promotion runner (SSOT entry point)
|
||||
//!
|
||||
//! Single entry point for all Pattern2 promotion logic.
|
||||
//! All callers should use `try_promote()` instead of accessing internals directly.
|
||||
|
||||
use crate::ast::ASTNode;
|
||||
use crate::mir::builder::MirBuilder;
|
||||
|
||||
use super::super::super::body_local_policy::{classify_for_pattern2, BodyLocalRoute};
|
||||
use super::super::super::pattern2_inputs_facts_box::Pattern2Inputs;
|
||||
use super::super::super::policies::PolicyDecision;
|
||||
|
||||
use super::promote_decision::{PromoteDecision, PromoteStepResult};
|
||||
|
||||
/// Phase 263 P0.2: Try to promote LoopBodyLocal variables for Pattern2
|
||||
///
|
||||
/// This is the single entry point for Pattern2 promotion logic.
|
||||
/// Returns PromoteDecision to indicate success, applicability, or freeze.
|
||||
pub(in crate::mir::builder) fn try_promote(
|
||||
builder: &mut MirBuilder,
|
||||
condition: &ASTNode,
|
||||
body: &[ASTNode],
|
||||
inputs: Pattern2Inputs,
|
||||
debug: bool,
|
||||
verbose: bool,
|
||||
) -> Result<PromoteDecision, String> {
|
||||
let mut inputs = inputs;
|
||||
use crate::mir::join_ir::lowering::digitpos_condition_normalizer::DigitPosConditionNormalizer;
|
||||
use crate::mir::loop_pattern_detection::loop_condition_scope::LoopConditionScopeBox;
|
||||
|
||||
let cond_scope = LoopConditionScopeBox::analyze(
|
||||
&inputs.loop_var_name,
|
||||
&vec![condition, &inputs.break_condition_node],
|
||||
Some(&inputs.scope),
|
||||
);
|
||||
|
||||
let mut promoted_pairs: Vec<(String, String)> = Vec::new();
|
||||
let cond_body_local_vars: Vec<String> = cond_scope
|
||||
.vars
|
||||
.iter()
|
||||
.filter(|v| matches!(v.scope, crate::mir::loop_pattern_detection::loop_condition_scope::CondVarScope::LoopBodyLocal))
|
||||
.map(|v| v.name.clone())
|
||||
.collect();
|
||||
|
||||
if cond_scope.has_loop_body_local() {
|
||||
// Policy-controlled: some families must not run promotion/slot heuristics here.
|
||||
// Example: balanced depth-scan uses derived vars and doesn't have a break-guard node.
|
||||
if matches!(
|
||||
inputs.body_local_handling,
|
||||
crate::mir::builder::control_flow::joinir::patterns::pattern2_inputs_facts_box::BodyLocalHandlingPolicy::SkipPromotion
|
||||
) {
|
||||
// no-op: lowerers will populate LoopBodyLocalEnv via init/derived emission.
|
||||
} else if !inputs.is_loop_true_read_digits {
|
||||
match classify_for_pattern2(
|
||||
builder,
|
||||
&inputs.loop_var_name,
|
||||
&inputs.scope,
|
||||
&inputs.break_condition_node,
|
||||
&cond_scope,
|
||||
body,
|
||||
) {
|
||||
PolicyDecision::Use(BodyLocalRoute::Promotion {
|
||||
promoted_carrier,
|
||||
promoted_var,
|
||||
carrier_name,
|
||||
}) => {
|
||||
let is_trim_promotion = promoted_carrier.trim_helper().is_some();
|
||||
if !is_trim_promotion {
|
||||
promoted_pairs.push((promoted_var.clone(), carrier_name.clone()));
|
||||
}
|
||||
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
{
|
||||
use crate::mir::join_ir::lowering::carrier_binding_assigner::CarrierBindingAssigner;
|
||||
let mut promoted_carrier = promoted_carrier;
|
||||
CarrierBindingAssigner::assign_promoted_binding(
|
||||
builder,
|
||||
&mut promoted_carrier,
|
||||
&promoted_var,
|
||||
&carrier_name,
|
||||
)
|
||||
.map_err(|e| format!("[phase78/binding_assign] {:?}", e))?;
|
||||
inputs.carrier_info.merge_from(&promoted_carrier);
|
||||
}
|
||||
#[cfg(not(feature = "normalized_dev"))]
|
||||
{
|
||||
inputs.carrier_info.merge_from(&promoted_carrier);
|
||||
}
|
||||
|
||||
inputs
|
||||
.carrier_info
|
||||
.promoted_loopbodylocals
|
||||
.push(promoted_var.clone());
|
||||
|
||||
if !is_trim_promotion {
|
||||
inputs.break_condition_node = DigitPosConditionNormalizer::normalize(
|
||||
&inputs.break_condition_node,
|
||||
&promoted_var,
|
||||
&carrier_name,
|
||||
);
|
||||
}
|
||||
}
|
||||
PolicyDecision::Use(BodyLocalRoute::ReadOnlySlot(slot)) => {
|
||||
inputs.allowed_body_locals_for_conditions = vec![slot.name.clone()];
|
||||
inputs.read_only_body_local_slot = Some(slot);
|
||||
}
|
||||
PolicyDecision::Reject(reason) => {
|
||||
// Phase 263 P0.1: Reject を PromoteDecision で二分化(型安全)
|
||||
if reason.contains("not_readonly")
|
||||
|| reason.contains("No promotable pattern detected")
|
||||
{
|
||||
// 対象外: Pattern2 で処理できない形 → NotApplicable で後続経路へ
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
eprintln!(
|
||||
"[pattern2/api/promote] Pattern2 対象外(LoopBodyLocal {:?}): {}. 後続経路へfallback.",
|
||||
cond_body_local_vars, reason
|
||||
);
|
||||
}
|
||||
return Ok(PromoteDecision::NotApplicable);
|
||||
} else {
|
||||
// 対象だが未対応(freeze級): 実装バグ or 将来実装予定 → Freeze で Fail-Fast
|
||||
return Ok(PromoteDecision::Freeze(format!(
|
||||
"[pattern2/api/promote] Pattern2 未対応エラー(LoopBodyLocal {:?}): {}",
|
||||
cond_body_local_vars, reason
|
||||
)));
|
||||
}
|
||||
}
|
||||
PolicyDecision::None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate join_ids for carriers and register bindings.
|
||||
for carrier in &mut inputs.carrier_info.carriers {
|
||||
let carrier_join_id = inputs.join_value_space.alloc_param();
|
||||
carrier.join_id = Some(carrier_join_id);
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
if let Some(binding_id) = carrier.binding_id {
|
||||
use crate::mir::join_ir::lowering::carrier_info::CarrierRole;
|
||||
match carrier.role {
|
||||
CarrierRole::ConditionOnly => inputs.env.register_condition_binding(binding_id, carrier_join_id),
|
||||
CarrierRole::LoopState => inputs.env.register_carrier_binding(binding_id, carrier_join_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (promoted_var, promoted_carrier_name) in promoted_pairs {
|
||||
let join_id = inputs
|
||||
.carrier_info
|
||||
.find_carrier(&promoted_carrier_name)
|
||||
.and_then(|c| c.join_id)
|
||||
.ok_or_else(|| format!("[phase229] promoted carrier '{}' has no join_id", promoted_carrier_name))?;
|
||||
inputs.env.insert(promoted_var, join_id);
|
||||
}
|
||||
|
||||
// ExprLowerer validation (best-effort; unchanged behavior)
|
||||
{
|
||||
use crate::mir::join_ir::lowering::expr_lowerer::{ExprContext, ExprLowerer, ExprLoweringError};
|
||||
use crate::mir::join_ir::lowering::scope_manager::Pattern2ScopeManager;
|
||||
|
||||
let scope_manager = Pattern2ScopeManager {
|
||||
condition_env: &inputs.env,
|
||||
loop_body_local_env: Some(&inputs.body_local_env),
|
||||
captured_env: Some(&inputs.captured_env),
|
||||
carrier_info: &inputs.carrier_info,
|
||||
};
|
||||
|
||||
match ExprLowerer::new(&scope_manager, ExprContext::Condition, builder)
|
||||
.with_debug(debug)
|
||||
.lower(&inputs.break_condition_node)
|
||||
{
|
||||
Ok(_) => {}
|
||||
Err(ExprLoweringError::UnsupportedNode(_)) => {}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(PromoteDecision::Promoted(PromoteStepResult { inputs }))
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
//! Phase 263 P0.2: Pattern2 module structure
|
||||
//!
|
||||
//! This module organizes Pattern2 logic with a clear SSOT structure:
|
||||
//! - `api/` - Public entry point for promotion logic (SSOT)
|
||||
|
||||
pub(in crate::mir::builder) mod api;
|
||||
@ -62,9 +62,9 @@ impl Pattern2LoweringOrchestrator {
|
||||
let facts = GatherFactsStepBox::gather(builder, condition, body, fn_body, &ctx, verbose)?;
|
||||
let inputs = ApplyPolicyStepBox::apply(condition, body, facts)?;
|
||||
|
||||
// Phase 263 P0.1: PromoteDecision で分岐を1箇所に固定(型安全)
|
||||
use super::pattern2_steps::promote_step_box::PromoteDecision;
|
||||
let mut inputs = match PromoteStepBox::run(builder, condition, body, inputs, debug, verbose)? {
|
||||
// Phase 263 P0.2: pattern2::api 経由で try_promote を呼び出し(入口SSOT)
|
||||
use super::pattern2::api::{try_promote, PromoteDecision};
|
||||
let mut inputs = match try_promote(builder, condition, body, inputs, debug, verbose)? {
|
||||
PromoteDecision::Promoted(result) => {
|
||||
result.inputs
|
||||
}
|
||||
|
||||
@ -1,40 +1,24 @@
|
||||
//! PromoteStepBox (Phase 106)
|
||||
//!
|
||||
//! Phase 263 P0.2: This is now a thin wrapper over pattern2::api::try_promote.
|
||||
//! All promotion logic has been moved to pattern2::api for SSOT.
|
||||
//!
|
||||
//! Responsibility:
|
||||
//! - promotion / read-only slot routing for body-local vars in conditions
|
||||
//! - carrier preparation for JoinIR emission
|
||||
//! - Backward compatibility wrapper for existing callers
|
||||
//! - Delegates to pattern2::api::try_promote for actual implementation
|
||||
|
||||
use crate::ast::ASTNode;
|
||||
use crate::mir::builder::MirBuilder;
|
||||
use crate::mir::loop_pattern_detection::error_messages;
|
||||
|
||||
use super::super::body_local_policy::{classify_for_pattern2, BodyLocalRoute};
|
||||
use super::super::pattern2::api::{try_promote, PromoteDecision, PromoteStepResult};
|
||||
use super::super::pattern2_inputs_facts_box::Pattern2Inputs;
|
||||
use super::super::policies::PolicyDecision;
|
||||
|
||||
pub(crate) struct PromoteStepResult {
|
||||
pub inputs: Pattern2Inputs,
|
||||
}
|
||||
|
||||
/// Phase 263 P0.1: Promotion decision for Pattern2 LoopBodyLocal handling
|
||||
///
|
||||
/// Eliminates Option<_> wrapping ambiguity by making decision explicit.
|
||||
pub(crate) enum PromoteDecision {
|
||||
/// Promotion succeeded - Pattern2 can proceed
|
||||
Promoted(PromoteStepResult),
|
||||
|
||||
/// Pattern2 not applicable (e.g., reassigned LoopBodyLocal, no promotable pattern)
|
||||
/// → Router should try next path (legacy binding, etc.)
|
||||
NotApplicable,
|
||||
|
||||
/// Pattern2 should handle this but implementation is missing
|
||||
/// → Fail-Fast with error message
|
||||
Freeze(String),
|
||||
}
|
||||
|
||||
pub(crate) struct PromoteStepBox;
|
||||
|
||||
impl PromoteStepBox {
|
||||
/// Phase 263 P0.2: Thin wrapper over pattern2::api::try_promote
|
||||
///
|
||||
/// This method is deprecated. Use pattern2::api::try_promote directly.
|
||||
pub(crate) fn run(
|
||||
builder: &mut MirBuilder,
|
||||
condition: &ASTNode,
|
||||
@ -43,170 +27,6 @@ impl PromoteStepBox {
|
||||
debug: bool,
|
||||
verbose: bool,
|
||||
) -> Result<PromoteDecision, String> {
|
||||
Self::promote_and_prepare_carriers(builder, condition, body, inputs, debug, verbose)
|
||||
try_promote(builder, condition, body, inputs, debug, verbose)
|
||||
}
|
||||
|
||||
pub(in crate::mir::builder) fn promote_and_prepare_carriers(
|
||||
builder: &mut MirBuilder,
|
||||
condition: &ASTNode,
|
||||
body: &[ASTNode],
|
||||
inputs: Pattern2Inputs,
|
||||
debug: bool,
|
||||
verbose: bool,
|
||||
) -> Result<PromoteDecision, String> {
|
||||
let mut inputs = inputs;
|
||||
use crate::mir::join_ir::lowering::digitpos_condition_normalizer::DigitPosConditionNormalizer;
|
||||
use crate::mir::loop_pattern_detection::loop_condition_scope::LoopConditionScopeBox;
|
||||
|
||||
let cond_scope = LoopConditionScopeBox::analyze(
|
||||
&inputs.loop_var_name,
|
||||
&vec![condition, &inputs.break_condition_node],
|
||||
Some(&inputs.scope),
|
||||
);
|
||||
|
||||
let mut promoted_pairs: Vec<(String, String)> = Vec::new();
|
||||
let cond_body_local_vars: Vec<String> = cond_scope
|
||||
.vars
|
||||
.iter()
|
||||
.filter(|v| matches!(v.scope, crate::mir::loop_pattern_detection::loop_condition_scope::CondVarScope::LoopBodyLocal))
|
||||
.map(|v| v.name.clone())
|
||||
.collect();
|
||||
|
||||
if cond_scope.has_loop_body_local() {
|
||||
// Policy-controlled: some families must not run promotion/slot heuristics here.
|
||||
// Example: balanced depth-scan uses derived vars and doesn't have a break-guard node.
|
||||
if matches!(
|
||||
inputs.body_local_handling,
|
||||
crate::mir::builder::control_flow::joinir::patterns::pattern2_inputs_facts_box::BodyLocalHandlingPolicy::SkipPromotion
|
||||
) {
|
||||
// no-op: lowerers will populate LoopBodyLocalEnv via init/derived emission.
|
||||
} else if !inputs.is_loop_true_read_digits {
|
||||
match classify_for_pattern2(
|
||||
builder,
|
||||
&inputs.loop_var_name,
|
||||
&inputs.scope,
|
||||
&inputs.break_condition_node,
|
||||
&cond_scope,
|
||||
body,
|
||||
) {
|
||||
PolicyDecision::Use(BodyLocalRoute::Promotion {
|
||||
promoted_carrier,
|
||||
promoted_var,
|
||||
carrier_name,
|
||||
}) => {
|
||||
let is_trim_promotion = promoted_carrier.trim_helper().is_some();
|
||||
if !is_trim_promotion {
|
||||
promoted_pairs.push((promoted_var.clone(), carrier_name.clone()));
|
||||
}
|
||||
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
{
|
||||
use crate::mir::join_ir::lowering::carrier_binding_assigner::CarrierBindingAssigner;
|
||||
let mut promoted_carrier = promoted_carrier;
|
||||
CarrierBindingAssigner::assign_promoted_binding(
|
||||
builder,
|
||||
&mut promoted_carrier,
|
||||
&promoted_var,
|
||||
&carrier_name,
|
||||
)
|
||||
.map_err(|e| format!("[phase78/binding_assign] {:?}", e))?;
|
||||
inputs.carrier_info.merge_from(&promoted_carrier);
|
||||
}
|
||||
#[cfg(not(feature = "normalized_dev"))]
|
||||
{
|
||||
inputs.carrier_info.merge_from(&promoted_carrier);
|
||||
}
|
||||
|
||||
inputs
|
||||
.carrier_info
|
||||
.promoted_loopbodylocals
|
||||
.push(promoted_var.clone());
|
||||
|
||||
if !is_trim_promotion {
|
||||
inputs.break_condition_node = DigitPosConditionNormalizer::normalize(
|
||||
&inputs.break_condition_node,
|
||||
&promoted_var,
|
||||
&carrier_name,
|
||||
);
|
||||
}
|
||||
}
|
||||
PolicyDecision::Use(BodyLocalRoute::ReadOnlySlot(slot)) => {
|
||||
inputs.allowed_body_locals_for_conditions = vec![slot.name.clone()];
|
||||
inputs.read_only_body_local_slot = Some(slot);
|
||||
}
|
||||
PolicyDecision::Reject(reason) => {
|
||||
// Phase 263 P0.1: Reject を PromoteDecision で二分化(型安全)
|
||||
if reason.contains("not_readonly")
|
||||
|| reason.contains("No promotable pattern detected")
|
||||
{
|
||||
// 対象外: Pattern2 で処理できない形 → NotApplicable で後続経路へ
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
eprintln!(
|
||||
"[pattern2/promote_step] Pattern2 対象外(LoopBodyLocal {:?}): {}. 後続経路へfallback.",
|
||||
cond_body_local_vars, reason
|
||||
);
|
||||
}
|
||||
return Ok(PromoteDecision::NotApplicable);
|
||||
} else {
|
||||
// 対象だが未対応(freeze級): 実装バグ or 将来実装予定 → Freeze で Fail-Fast
|
||||
return Ok(PromoteDecision::Freeze(format!(
|
||||
"[pattern2/promote_step] Pattern2 未対応エラー(LoopBodyLocal {:?}): {}",
|
||||
cond_body_local_vars, reason
|
||||
)));
|
||||
}
|
||||
}
|
||||
PolicyDecision::None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate join_ids for carriers and register bindings.
|
||||
for carrier in &mut inputs.carrier_info.carriers {
|
||||
let carrier_join_id = inputs.join_value_space.alloc_param();
|
||||
carrier.join_id = Some(carrier_join_id);
|
||||
#[cfg(feature = "normalized_dev")]
|
||||
if let Some(binding_id) = carrier.binding_id {
|
||||
use crate::mir::join_ir::lowering::carrier_info::CarrierRole;
|
||||
match carrier.role {
|
||||
CarrierRole::ConditionOnly => inputs.env.register_condition_binding(binding_id, carrier_join_id),
|
||||
CarrierRole::LoopState => inputs.env.register_carrier_binding(binding_id, carrier_join_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (promoted_var, promoted_carrier_name) in promoted_pairs {
|
||||
let join_id = inputs
|
||||
.carrier_info
|
||||
.find_carrier(&promoted_carrier_name)
|
||||
.and_then(|c| c.join_id)
|
||||
.ok_or_else(|| format!("[phase229] promoted carrier '{}' has no join_id", promoted_carrier_name))?;
|
||||
inputs.env.insert(promoted_var, join_id);
|
||||
}
|
||||
|
||||
// ExprLowerer validation (best-effort; unchanged behavior)
|
||||
{
|
||||
use crate::mir::join_ir::lowering::expr_lowerer::{ExprContext, ExprLowerer, ExprLoweringError};
|
||||
use crate::mir::join_ir::lowering::scope_manager::Pattern2ScopeManager;
|
||||
|
||||
let scope_manager = Pattern2ScopeManager {
|
||||
condition_env: &inputs.env,
|
||||
loop_body_local_env: Some(&inputs.body_local_env),
|
||||
captured_env: Some(&inputs.captured_env),
|
||||
carrier_info: &inputs.carrier_info,
|
||||
};
|
||||
|
||||
match ExprLowerer::new(&scope_manager, ExprContext::Condition, builder)
|
||||
.with_debug(debug)
|
||||
.lower(&inputs.break_condition_node)
|
||||
{
|
||||
Ok(_) => {}
|
||||
Err(ExprLoweringError::UnsupportedNode(_)) => {}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(PromoteDecision::Promoted(PromoteStepResult { inputs }))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user