feat(joinir): emit balanced depth-scan derived vars
This commit is contained in:
@ -52,6 +52,7 @@ impl EmitJoinIRStepBox {
|
|||||||
skeleton,
|
skeleton,
|
||||||
condition_only_recipe: inputs.condition_only_recipe.as_ref(),
|
condition_only_recipe: inputs.condition_only_recipe.as_ref(),
|
||||||
body_local_derived_recipe: inputs.body_local_derived_recipe.as_ref(),
|
body_local_derived_recipe: inputs.body_local_derived_recipe.as_ref(),
|
||||||
|
balanced_depth_scan_recipe: inputs.balanced_depth_scan_recipe.as_ref(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (join_module, fragment_meta) = match lower_loop_with_break_minimal(lowering_inputs) {
|
let (join_module, fragment_meta) = match lower_loop_with_break_minimal(lowering_inputs) {
|
||||||
|
|||||||
@ -5,6 +5,11 @@
|
|||||||
//! - `depth_delta`: per-iteration delta (-1/0/+1)
|
//! - `depth_delta`: per-iteration delta (-1/0/+1)
|
||||||
//! - `depth_next`: depth + depth_delta (for break checks)
|
//! - `depth_next`: depth + depth_delta (for break checks)
|
||||||
|
|
||||||
|
use crate::mir::join_ir::lowering::condition_env::ConditionEnv;
|
||||||
|
use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv;
|
||||||
|
use crate::mir::join_ir::{BinOpKind, CompareOp, ConstValue, JoinInst, MirLikeInst};
|
||||||
|
use crate::mir::ValueId;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BalancedDepthScanRecipe {
|
pub struct BalancedDepthScanRecipe {
|
||||||
pub depth_var: String,
|
pub depth_var: String,
|
||||||
@ -15,3 +20,105 @@ pub struct BalancedDepthScanRecipe {
|
|||||||
pub depth_next_name: String,
|
pub depth_next_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct BalancedDepthScanEmitter;
|
||||||
|
|
||||||
|
impl BalancedDepthScanEmitter {
|
||||||
|
pub fn emit_derived(
|
||||||
|
recipe: &BalancedDepthScanRecipe,
|
||||||
|
body_local_env: &mut LoopBodyLocalEnv,
|
||||||
|
condition_env: &ConditionEnv,
|
||||||
|
alloc_value: &mut dyn FnMut() -> ValueId,
|
||||||
|
instructions: &mut Vec<JoinInst>,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let ch_id = body_local_env.get(&recipe.ch_var).ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"[phase107/balanced-depth] ch '{}' not found in LoopBodyLocalEnv",
|
||||||
|
recipe.ch_var
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
let depth_id = condition_env.get(&recipe.depth_var).ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"[phase107/balanced-depth] depth '{}' not found in ConditionEnv",
|
||||||
|
recipe.depth_var
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let const_open = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Const {
|
||||||
|
dst: const_open,
|
||||||
|
value: ConstValue::String(recipe.open.clone()),
|
||||||
|
}));
|
||||||
|
let const_close = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Const {
|
||||||
|
dst: const_close,
|
||||||
|
value: ConstValue::String(recipe.close.clone()),
|
||||||
|
}));
|
||||||
|
|
||||||
|
let is_open = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Compare {
|
||||||
|
dst: is_open,
|
||||||
|
op: CompareOp::Eq,
|
||||||
|
lhs: ch_id,
|
||||||
|
rhs: const_open,
|
||||||
|
}));
|
||||||
|
let is_close = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Compare {
|
||||||
|
dst: is_close,
|
||||||
|
op: CompareOp::Eq,
|
||||||
|
lhs: ch_id,
|
||||||
|
rhs: const_close,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let const_1 = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Const {
|
||||||
|
dst: const_1,
|
||||||
|
value: ConstValue::Integer(1),
|
||||||
|
}));
|
||||||
|
let const_0 = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Const {
|
||||||
|
dst: const_0,
|
||||||
|
value: ConstValue::Integer(0),
|
||||||
|
}));
|
||||||
|
let const_m1 = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Const {
|
||||||
|
dst: const_m1,
|
||||||
|
value: ConstValue::Integer(-1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
let delta_open = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Select {
|
||||||
|
dst: delta_open,
|
||||||
|
cond: is_open,
|
||||||
|
then_val: const_1,
|
||||||
|
else_val: const_0,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let delta_close = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::Select {
|
||||||
|
dst: delta_close,
|
||||||
|
cond: is_close,
|
||||||
|
then_val: const_m1,
|
||||||
|
else_val: const_0,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let depth_delta = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::BinOp {
|
||||||
|
dst: depth_delta,
|
||||||
|
op: BinOpKind::Add,
|
||||||
|
lhs: delta_open,
|
||||||
|
rhs: delta_close,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let depth_next = alloc_value();
|
||||||
|
instructions.push(JoinInst::Compute(MirLikeInst::BinOp {
|
||||||
|
dst: depth_next,
|
||||||
|
op: BinOpKind::Add,
|
||||||
|
lhs: depth_id,
|
||||||
|
rhs: depth_delta,
|
||||||
|
}));
|
||||||
|
|
||||||
|
body_local_env.insert(recipe.depth_delta_name.clone(), depth_delta);
|
||||||
|
body_local_env.insert(recipe.depth_next_name.clone(), depth_next);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -68,6 +68,7 @@ use crate::mir::join_ir::lowering::carrier_update_emitter::{
|
|||||||
// Phase 92 P2-1: Import ConditionalStep emitter from dedicated module
|
// Phase 92 P2-1: Import ConditionalStep emitter from dedicated module
|
||||||
use crate::mir::join_ir::lowering::common::conditional_step_emitter::emit_conditional_step_update;
|
use crate::mir::join_ir::lowering::common::conditional_step_emitter::emit_conditional_step_update;
|
||||||
use crate::mir::join_ir::lowering::common::body_local_derived_emitter::BodyLocalDerivedRecipe;
|
use crate::mir::join_ir::lowering::common::body_local_derived_emitter::BodyLocalDerivedRecipe;
|
||||||
|
use crate::mir::join_ir::lowering::common::balanced_depth_scan_emitter::{BalancedDepthScanEmitter, BalancedDepthScanRecipe};
|
||||||
use crate::mir::join_ir::lowering::condition_to_joinir::ConditionEnv;
|
use crate::mir::join_ir::lowering::condition_to_joinir::ConditionEnv;
|
||||||
use crate::mir::loop_canonicalizer::UpdateKind;
|
use crate::mir::loop_canonicalizer::UpdateKind;
|
||||||
use crate::mir::join_ir::lowering::join_value_space::JoinValueSpace;
|
use crate::mir::join_ir::lowering::join_value_space::JoinValueSpace;
|
||||||
@ -111,6 +112,8 @@ pub(crate) struct LoopWithBreakLoweringInputs<'a> {
|
|||||||
pub condition_only_recipe: Option<&'a crate::mir::join_ir::lowering::common::condition_only_emitter::ConditionOnlyRecipe>,
|
pub condition_only_recipe: Option<&'a crate::mir::join_ir::lowering::common::condition_only_emitter::ConditionOnlyRecipe>,
|
||||||
/// Phase 94: BodyLocalDerived recipe (P5b escape `ch` reassignment + conditional counter).
|
/// Phase 94: BodyLocalDerived recipe (P5b escape `ch` reassignment + conditional counter).
|
||||||
pub body_local_derived_recipe: Option<&'a BodyLocalDerivedRecipe>,
|
pub body_local_derived_recipe: Option<&'a BodyLocalDerivedRecipe>,
|
||||||
|
/// Phase 107: Balanced depth-scan recipe (find_balanced_* family).
|
||||||
|
pub balanced_depth_scan_recipe: Option<&'a BalancedDepthScanRecipe>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lower Pattern 2 (Loop with Conditional Break) to JoinIR
|
/// Lower Pattern 2 (Loop with Conditional Break) to JoinIR
|
||||||
@ -189,6 +192,7 @@ pub(crate) fn lower_loop_with_break_minimal(
|
|||||||
skeleton,
|
skeleton,
|
||||||
condition_only_recipe,
|
condition_only_recipe,
|
||||||
body_local_derived_recipe,
|
body_local_derived_recipe,
|
||||||
|
balanced_depth_scan_recipe,
|
||||||
} = inputs;
|
} = inputs;
|
||||||
|
|
||||||
let mut body_local_env = body_local_env;
|
let mut body_local_env = body_local_env;
|
||||||
@ -492,6 +496,17 @@ pub(crate) fn lower_loop_with_break_minimal(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phase 107: Balanced depth-scan derived vars (depth_delta/depth_next)
|
||||||
|
if let Some(recipe) = balanced_depth_scan_recipe {
|
||||||
|
BalancedDepthScanEmitter::emit_derived(
|
||||||
|
recipe,
|
||||||
|
body_env,
|
||||||
|
env,
|
||||||
|
&mut alloc_value,
|
||||||
|
&mut body_init_block,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
|
|||||||
@ -148,6 +148,7 @@ fn test_pattern2_header_condition_via_exprlowerer() {
|
|||||||
skeleton: None, // Phase 92 P0-3: skeleton=None for backward compatibility
|
skeleton: None, // Phase 92 P0-3: skeleton=None for backward compatibility
|
||||||
condition_only_recipe: None, // Phase 93 P0: None for normal loops
|
condition_only_recipe: None, // Phase 93 P0: None for normal loops
|
||||||
body_local_derived_recipe: None, // Phase 94: None for normal loops
|
body_local_derived_recipe: None, // Phase 94: None for normal loops
|
||||||
|
balanced_depth_scan_recipe: None, // Phase 107: None for normal loops
|
||||||
});
|
});
|
||||||
|
|
||||||
assert!(result.is_ok(), "ExprLowerer header path should succeed");
|
assert!(result.is_ok(), "ExprLowerer header path should succeed");
|
||||||
|
|||||||
@ -137,6 +137,7 @@ pub fn build_pattern2_minimal_structured() -> JoinModule {
|
|||||||
skeleton: None, // Phase 92 P0-3: skeleton=None for backward compatibility
|
skeleton: None, // Phase 92 P0-3: skeleton=None for backward compatibility
|
||||||
condition_only_recipe: None, // Phase 93 P0: None for normal loops
|
condition_only_recipe: None, // Phase 93 P0: None for normal loops
|
||||||
body_local_derived_recipe: None, // Phase 94: None for fixture
|
body_local_derived_recipe: None, // Phase 94: None for fixture
|
||||||
|
balanced_depth_scan_recipe: None, // Phase 107: None for fixture
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect("pattern2 minimal lowering should succeed");
|
.expect("pattern2 minimal lowering should succeed");
|
||||||
|
|||||||
Reference in New Issue
Block a user