Files
hakorune/src/runner/json_v0_bridge/lowering/match_expr.rs

71 lines
2.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Match/expr-block lowering for JSON v0 bridge.
use super::merge::new_block;
use super::BridgeEnv;
use crate::mir::{BasicBlockId, CompareOp, ConstValue, MirFunction, MirInstruction, ValueId};
use super::super::ast::{ExprV0, MatchArmV0};
use super::expr::{lower_expr_with_scope, VarScope};
pub(super) fn lower_match_expr_with_scope<S: VarScope>(
env: &BridgeEnv,
f: &mut MirFunction,
cur_bb: BasicBlockId,
scrutinee: &ExprV0,
arms: &[MatchArmV0],
else_expr: &ExprV0,
vars: &mut S,
) -> Result<(ValueId, BasicBlockId), String> {
// Evaluate scrutinee
let (scr_val, start_bb) = lower_expr_with_scope(env, f, cur_bb, scrutinee, vars)?;
// Set up blocks
let dispatch_bb = new_block(f);
if let Some(bb) = f.get_block_mut(start_bb) {
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, start_bb, dispatch_bb); }
}
let else_bb = new_block(f);
let merge_bb = new_block(f);
// Chain dispatch over arms
let mut cur_dispatch = dispatch_bb;
let mut phi_inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
for (i, arm) in arms.iter().enumerate() {
let then_bb = new_block(f);
let next_dispatch = if i + 1 < arms.len() { Some(new_block(f)) } else { None };
let fall_bb = next_dispatch.unwrap_or(else_bb);
// Pre-allocate ids to avoid double borrow
let ldst = f.next_value_id();
let cond = f.next_value_id();
if let Some(bb) = f.get_block_mut(cur_dispatch) {
// compare scr_val == label
bb.add_instruction(MirInstruction::Const { dst: ldst, value: ConstValue::String(arm.label.clone()) });
}
crate::mir::ssot::cf_common::emit_compare_func(f, cur_dispatch, cond, CompareOp::Eq, scr_val, ldst);
crate::mir::ssot::cf_common::set_branch(f, cur_dispatch, cond, then_bb, fall_bb);
// Then arm body
let (tval, tend) = lower_expr_with_scope(env, f, then_bb, &arm.expr, vars)?;
if let Some(bb) = f.get_block_mut(tend) {
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb); }
}
phi_inputs.push((tend, tval));
cur_dispatch = fall_bb;
}
// Else body
let (eval, eend) = lower_expr_with_scope(env, f, else_bb, else_expr, vars)?;
if let Some(bb) = f.get_block_mut(eend) {
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb); }
}
phi_inputs.push((eend, eval));
// Merge result
let out = f.next_value_id();
// フェーズM.2: PHI統一処理no_phi分岐削除
let inputs = phi_inputs;
crate::mir::ssot::cf_common::insert_phi_at_head(f, merge_bb, out, inputs);
Ok((out, merge_bb))
}