完全移行→削除の安全順序(Option C)に従い、ScopeContextの
deprecated フィールドと sync helpers を完全削除。
## Changes
- Migrated all access sites to scope_ctx.*
- Removed 7 deprecated fields:
- current_function
- lexical_scope_stack
- function_param_names
- loop_header_stack
- loop_exit_stack
- if_merge_stack
- debug_scope_stack
- Removed 2 sync helpers (sync_scope_ctx_to_legacy, sync_legacy_to_scope_ctx)
- Updated 20+ files with direct field access
## Tests
- cargo build --release: PASS ✅
- Deprecation warnings: 255 → 166 (-89, -35%)
Phase 2 Progress: 4/7 contexts complete (57%)
139 lines
5.4 KiB
Rust
139 lines
5.4 KiB
Rust
use super::{BasicBlockId, ValueId};
|
||
use crate::ast::{ASTNode, LiteralValue};
|
||
|
||
impl super::MirBuilder {
|
||
// Peek expression lowering
|
||
pub(super) fn build_peek_expression(
|
||
&mut self,
|
||
scrutinee: ASTNode,
|
||
arms: Vec<(LiteralValue, ASTNode)>,
|
||
else_expr: ASTNode,
|
||
) -> Result<ValueId, String> {
|
||
// Evaluate scrutinee in the current block
|
||
let scr_val = self.build_expression_impl(scrutinee)?;
|
||
|
||
// Prepare merge and result
|
||
let merge_block: BasicBlockId = self.next_block_id();
|
||
let result_val = self.next_value_id();
|
||
let mut phi_inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||
|
||
// Create dispatch block where we start comparing arms
|
||
let dispatch_block = self.next_block_id();
|
||
// Jump from current block to dispatch (ensure terminator exists)
|
||
let need_jump = {
|
||
let cur = self.current_block;
|
||
if let (Some(cb), Some(ref func)) = (cur, &self.scope_ctx.current_function) {
|
||
if let Some(bb) = func.blocks.get(&cb) {
|
||
!bb.is_terminated()
|
||
} else {
|
||
true
|
||
}
|
||
} else {
|
||
true
|
||
}
|
||
};
|
||
if need_jump {
|
||
crate::mir::builder::emission::branch::emit_jump(self, dispatch_block)?;
|
||
}
|
||
self.start_new_block(dispatch_block)?;
|
||
|
||
// If there are no arms, fall through to else directly
|
||
if arms.is_empty() {
|
||
let else_block = self.next_block_id();
|
||
crate::mir::builder::emission::branch::emit_jump(self, else_block)?;
|
||
self.start_new_block(else_block)?;
|
||
let else_val = self.build_expression_impl(else_expr)?;
|
||
phi_inputs.push((else_block, else_val));
|
||
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
||
self.start_new_block(merge_block)?;
|
||
// フェーズM: PHI はブロック先頭に配置(cf_common 統一)
|
||
self.insert_phi_with_dst(result_val, phi_inputs)?;
|
||
return Ok(result_val);
|
||
}
|
||
|
||
// Else block to handle default case
|
||
let else_block = self.next_block_id();
|
||
|
||
// Chain dispatch blocks for each arm
|
||
let mut cur_dispatch = dispatch_block;
|
||
for (i, (label, arm_expr)) in arms.iter().cloned().enumerate() {
|
||
let then_block = self.next_block_id();
|
||
// Next dispatch (only for non-last arm)
|
||
let next_dispatch = if i + 1 < arms.len() {
|
||
Some(self.next_block_id())
|
||
} else {
|
||
None
|
||
};
|
||
let else_target = next_dispatch.unwrap_or(else_block);
|
||
|
||
// In current dispatch block, compare and branch
|
||
self.start_new_block(cur_dispatch)?;
|
||
let lit_id = match label {
|
||
LiteralValue::String(s) => {
|
||
crate::mir::builder::emission::constant::emit_string(self, s)
|
||
}
|
||
LiteralValue::Integer(i) => {
|
||
crate::mir::builder::emission::constant::emit_integer(self, i)
|
||
}
|
||
LiteralValue::Bool(b) => {
|
||
crate::mir::builder::emission::constant::emit_bool(self, b)
|
||
}
|
||
LiteralValue::Float(f) => {
|
||
crate::mir::builder::emission::constant::emit_float(self, f)
|
||
}
|
||
LiteralValue::Null => crate::mir::builder::emission::constant::emit_null(self),
|
||
LiteralValue::Void => crate::mir::builder::emission::constant::emit_void(self),
|
||
};
|
||
let cond_id = self.next_value_id();
|
||
crate::mir::builder::emission::compare::emit_to(
|
||
self,
|
||
cond_id,
|
||
super::CompareOp::Eq,
|
||
scr_val,
|
||
lit_id,
|
||
)?;
|
||
crate::mir::builder::emission::branch::emit_conditional(
|
||
self,
|
||
cond_id,
|
||
then_block,
|
||
else_target,
|
||
)?;
|
||
|
||
// then arm
|
||
self.start_new_block(then_block)?;
|
||
let then_val = self.build_expression_impl(arm_expr)?;
|
||
phi_inputs.push((then_block, then_val));
|
||
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
||
|
||
// Move to next dispatch or else block
|
||
cur_dispatch = else_target;
|
||
}
|
||
|
||
// Lower else expression in else_block
|
||
self.start_new_block(else_block)?;
|
||
let else_val = self.build_expression_impl(else_expr)?;
|
||
phi_inputs.push((else_block, else_val));
|
||
crate::mir::builder::emission::branch::emit_jump(self, merge_block)?;
|
||
|
||
// Merge and yield result
|
||
self.start_new_block(merge_block)?;
|
||
// フェーズM: PHI はブロック先頭に配置(cf_common 統一)
|
||
if let (Some(func), Some(cur_bb)) = (self.scope_ctx.current_function.as_mut(), self.current_block) {
|
||
crate::mir::ssot::cf_common::insert_phi_at_head_spanned(
|
||
func,
|
||
cur_bb,
|
||
result_val,
|
||
phi_inputs,
|
||
self.metadata_ctx.current_span(),
|
||
);
|
||
} else {
|
||
self.emit_instruction(super::MirInstruction::Phi {
|
||
dst: result_val,
|
||
inputs: phi_inputs,
|
||
type_hint: None, // Phase 63-6: Legacy path, no type hint
|
||
})?;
|
||
}
|
||
Ok(result_val)
|
||
}
|
||
}
|