//! 🎯 箱理論: 関数lowering処理 //! //! 責務: //! - static/instance method を MIR function に lowering //! - BoxCompilationContext による完全独立化 //! - パラメータ・型情報の適切な管理 use super::function_lowering; use crate::ast::ASTNode; use crate::mir::builder::{MirBuilder, MirInstruction, MirType}; use crate::mir::region::function_slot_registry::FunctionSlotRegistry; use crate::mir::{MirValueKind, ValueId}; // Phase 26-A-3: ValueId型安全化 use std::collections::BTreeMap; // Phase 25.1: 決定性確保 /// 🎯 箱理論: Lowering Context(準備と復元) struct LoweringContext { context_active: bool, saved_var_map: Option>, // Phase 25.1: BTreeMap化 saved_static_ctx: Option, saved_function: Option, saved_block: Option, saved_slot_registry: Option, } impl MirBuilder { /// 🎯 箱理論: Step 1 - Lowering Context準備 fn prepare_lowering_context(&mut self, func_name: &str) -> LoweringContext { // Static box context設定 let saved_static_ctx = self.current_static_box.clone(); if let Some(pos) = func_name.find('.') { let box_name = &func_name[..pos]; if !box_name.is_empty() { self.current_static_box = Some(box_name.to_string()); } } // BoxCompilationContext vs saved_var_map モード判定 let context_active = self.compilation_context.is_some(); let saved_var_map = if !context_active { Some(std::mem::take(&mut self.variable_map)) } else { None }; // 関数スコープ SlotRegistry は元の関数側から退避しておくよ。 let saved_slot_registry = self.current_slot_registry.take(); // BoxCompilationContext mode: clear()で完全独立化 if context_active { self.variable_map.clear(); self.type_ctx.value_origin_newbox.clear(); // value_types も static box 単位で独立させる。 // これにより、前の static box で使用された ValueId に紐づく型情報が // 次の box にリークして誤った box_name 推論(例: Stage1UsingResolverBox) // を引き起こすことを防ぐ。 self.type_ctx.value_types.clear(); } LoweringContext { context_active, saved_var_map, saved_static_ctx, saved_function: None, saved_block: None, saved_slot_registry, } } /// 🎯 箱理論: Step 2 - 関数スケルトン作成 fn create_function_skeleton( &mut self, func_name: String, params: &[String], body: &[ASTNode], ctx: &mut LoweringContext, ) -> Result<(), String> { let signature = function_lowering::prepare_static_method_signature(func_name.clone(), params, body); let entry = self.next_block_id(); let function = self.new_function_with_metadata(signature, entry); // Phase 136 Step 3/7: Save from scope_ctx (SSOT), sync to legacy field ctx.saved_function = self.scope_ctx.current_function.take(); self.current_function = None; ctx.saved_block = self.current_block.take(); eprintln!( "[DEBUG/create_function_skeleton] Creating function: {}", func_name ); eprintln!("[DEBUG/create_function_skeleton] Entry block: {:?}", entry); // Phase 136 Step 3/7: Update both scope_ctx (SSOT) and legacy field (backward compat) self.scope_ctx.current_function = Some(function.clone()); self.current_function = Some(function); self.current_block = Some(entry); // 新しい関数スコープ用の SlotRegistry を準備するよ(観測専用) self.current_slot_registry = Some(FunctionSlotRegistry::new()); self.ensure_block_exists(entry)?; // Region 観測レイヤ: static 関数用の FunctionRegion を積むよ。 crate::mir::region::observer::observe_function_region(self); Ok(()) } /// 🎯 箱理論: Step 3 - パラメータ設定 #[allow(deprecated)] fn setup_function_params(&mut self, params: &[String]) { // Phase 136 Step 3/7: Clear both scope_ctx (SSOT) and legacy field (backward compat) self.scope_ctx.function_param_names.clear(); self.function_param_names.clear(); // SlotRegistry 更新は borrow 競合を避けるため、まずローカルに集約してから反映するよ。 let mut slot_regs: Vec<(String, Option)> = Vec::new(); // Phase 26-A-3: パラメータ型情報も後で一括登録(借用競合回避) let mut param_kinds: Vec<(ValueId, u32)> = Vec::new(); if let Some(ref mut f) = self.current_function { // 📦 Hotfix 5: Use pre-populated params from MirFunction::new() // Static methods have implicit receiver at params[0], so actual parameters start at offset let receiver_offset = if f.params.is_empty() { 0 } else { // If params already populated (by Hotfix 4+5), use them if f.params.len() > params.len() { 1 } else { 0 } }; let param_types = f.signature.params.clone(); for (idx, p) in params.iter().enumerate() { let param_idx = receiver_offset + idx; let pid = if param_idx < f.params.len() { // Use pre-allocated ValueId from MirFunction::new() f.params[param_idx] } else { // Allocate new ValueId (fallback for non-static methods) let new_pid = f.next_value_id(); f.params.push(new_pid); new_pid }; self.variable_map.insert(p.clone(), pid); // Phase 136 Step 3/7: Insert into both scope_ctx (SSOT) and legacy field self.scope_ctx.function_param_names.insert(p.clone()); self.function_param_names.insert(p.clone()); // Phase 26-A-3: パラメータ型情報を収集(後で一括登録) // param_idx: receiver offset を考慮した実際のパラメータインデックス param_kinds.push((pid, param_idx as u32)); let ty = param_types.get(param_idx).cloned(); slot_regs.push((p.clone(), ty)); } } // Phase 26-A-3: パラメータ型情報を一括登録(GUARD Bug Prevention) for (pid, param_idx) in param_kinds { self.register_value_kind(pid, MirValueKind::Parameter(param_idx)); } if let Some(reg) = self.current_slot_registry.as_mut() { for (name, ty) in slot_regs { reg.ensure_slot(&name, ty); } } } /// 🎯 箱理論: Step 4 - 本体lowering fn lower_function_body(&mut self, body: Vec) -> Result<(), String> { eprintln!("[DEBUG/lower_function_body] body.len() = {}", body.len()); let program_ast = function_lowering::wrap_in_program(body); eprintln!("[DEBUG/lower_function_body] About to call build_expression"); let _last = self.build_expression(program_ast)?; eprintln!("[DEBUG/lower_function_body] build_expression completed"); Ok(()) } /// 🎯 箱理論: Step 5 - 関数finalize #[allow(deprecated)] fn finalize_function(&mut self, returns_value: bool) -> Result<(), String> { // Void return追加(必要な場合) if !returns_value { if let Some(ref mut f) = self.current_function { if let Some(block) = f.get_block(self.current_block.unwrap()) { if !block.is_terminated() { let void_val = crate::mir::builder::emission::constant::emit_void(self); self.emit_instruction(MirInstruction::Return { value: Some(void_val), })?; } } } } // 型推論 if let Some(ref mut f) = self.current_function { if returns_value && matches!(f.signature.return_type, MirType::Void | MirType::Unknown) { let mut inferred: Option = None; 'search: for (_bid, bb) in f.blocks.iter() { for inst in bb.instructions.iter() { if let MirInstruction::Return { value: Some(v) } = inst { if let Some(mt) = self.type_ctx.value_types.get(v).cloned() { inferred = Some(mt); break 'search; } } } if let Some(MirInstruction::Return { value: Some(v) }) = &bb.terminator { if let Some(mt) = self.type_ctx.value_types.get(v).cloned() { inferred = Some(mt); break; } } } if let Some(mt) = inferred { f.signature.return_type = mt; } } } // Moduleに追加 // Phase 136 Step 3/7: Take from legacy field, sync to scope_ctx let finalized = self.current_function.take().unwrap(); self.scope_ctx.current_function = None; if let Some(ref mut module) = self.current_module { module.add_function(finalized); } Ok(()) } /// 🎯 箱理論: Step 6 - Context復元 fn restore_lowering_context(&mut self, ctx: LoweringContext) { // Phase 136 Step 3/7: Restore to scope_ctx (SSOT), sync to legacy field self.scope_ctx.current_function = ctx.saved_function.clone(); self.current_function = ctx.saved_function; self.current_block = ctx.saved_block; // モード別にcontext復元 if ctx.context_active { // BoxCompilationContext mode: clear のみ(次回も完全独立) self.variable_map.clear(); self.type_ctx.value_origin_newbox.clear(); // static box ごとに型情報も独立させる(前 box の型メタデータを引きずらない) self.type_ctx.value_types.clear(); } else if let Some(saved) = ctx.saved_var_map { // Legacy mode: Main.main 側の variable_map を元に戻す self.variable_map = saved; } // Static box context復元 self.current_static_box = ctx.saved_static_ctx; // 関数スコープ SlotRegistry も元の関数に戻すよ。 self.current_slot_registry = ctx.saved_slot_registry; } /// 🎯 箱理論: Step 2b - 関数スケルトン作成(instance method版) fn create_method_skeleton( &mut self, func_name: String, box_name: &str, params: &[String], body: &[ASTNode], ctx: &mut LoweringContext, ) -> Result<(), String> { let signature = function_lowering::prepare_method_signature(func_name, box_name, params, body); let entry = self.next_block_id(); let function = self.new_function_with_metadata(signature, entry); // Phase 136 Step 3/7: Save from scope_ctx (SSOT), sync to legacy field ctx.saved_function = self.scope_ctx.current_function.take(); self.current_function = None; ctx.saved_block = self.current_block.take(); // Phase 136 Step 3/7: Update both scope_ctx (SSOT) and legacy field (backward compat) self.scope_ctx.current_function = Some(function.clone()); self.current_function = Some(function); self.current_block = Some(entry); // instance method 用の関数スコープ SlotRegistry もここで用意するよ。 self.current_slot_registry = Some(FunctionSlotRegistry::new()); self.ensure_block_exists(entry)?; // Region 観測レイヤ: instance method 用の FunctionRegion も積んでおくよ。 crate::mir::region::observer::observe_function_region(self); Ok(()) } /// 🎯 箱理論: Step 3b - パラメータ設定(instance method版: me + params) fn setup_method_params(&mut self, box_name: &str, params: &[String]) { // SlotRegistry 更新はローカルバッファに集約してから反映するよ。 let mut slot_regs: Vec<(String, Option)> = Vec::new(); if let Some(ref mut f) = self.current_function { // 📦 Hotfix 6 改訂版: // MirFunction::new() が既に 0..N の ValueId を params 用に予約しているので、 // ここではそれを「上書き使用」するだけにして、push で二重定義しないようにするよ。 // // params レイアウト: // index 0: me (box) // index 1..: 通常パラメータ if f.params.is_empty() { // 安全弁: 何らかの理由で pre-populate されていない場合は従来どおり new する let me_id = ValueId(0); f.params.push(me_id); for i in 0..params.len() { f.params.push(ValueId((i + 1) as u32)); } } // me let me_id = f.params[0]; self.variable_map.insert("me".to_string(), me_id); self.type_ctx.value_origin_newbox.insert(me_id, box_name.to_string()); slot_regs.push(("me".to_string(), None)); // 通常パラメータ for (idx, p) in params.iter().enumerate() { let param_idx = idx + 1; if param_idx < f.params.len() { let pid = f.params[param_idx]; self.variable_map.insert(p.clone(), pid); slot_regs.push((p.clone(), None)); } else { // 念のため足りない場合は新規に確保(互換用) let pid = f.next_value_id(); f.params.push(pid); self.variable_map.insert(p.clone(), pid); slot_regs.push((p.clone(), None)); } } } if let Some(reg) = self.current_slot_registry.as_mut() { for (name, ty) in slot_regs { reg.ensure_slot(&name, ty); } } } /// 🎯 箱理論: Step 4b - 本体lowering(instance method版: cf_block) fn lower_method_body(&mut self, body: Vec) -> Result<(), String> { let _last = self.cf_block(body)?; Ok(()) } /// 🎯 箱理論: 統合エントリーポイント - static method lowering pub(in crate::mir::builder) fn lower_static_method_as_function( &mut self, func_name: String, params: Vec, body: Vec, ) -> Result<(), String> { // Phase 200-C: Store fn_body for capture analysis eprintln!( "[lower_static_method_as_function] Storing fn_body with {} nodes for '{}'", body.len(), func_name ); self.fn_body_ast = Some(body.clone()); // Step 1: Context準備 let mut ctx = self.prepare_lowering_context(&func_name); // Step 2: 関数スケルトン作成 self.create_function_skeleton(func_name, ¶ms, &body, &mut ctx)?; // Step 3: パラメータ設定 self.setup_function_params(¶ms); // Step 4: 本体lowering self.lower_function_body(body)?; // Step 5: 関数finalize let returns_value = if let Some(ref f) = self.current_function { !matches!(f.signature.return_type, MirType::Void) } else { false }; self.finalize_function(returns_value)?; // FunctionRegion を 1 段ポップして元の関数コンテキストに戻るよ。 crate::mir::region::observer::pop_function_region(self); // Step 6: Context復元 self.restore_lowering_context(ctx); // Phase 200-C: Clear fn_body_ast after function lowering self.fn_body_ast = None; Ok(()) } /// 🎯 箱理論: 統合エントリーポイント - instance method lowering pub(in crate::mir::builder) fn lower_method_as_function( &mut self, func_name: String, box_name: String, params: Vec, body: Vec, ) -> Result<(), String> { // Phase 200-C: Store fn_body for capture analysis self.fn_body_ast = Some(body.clone()); // Step 1: Context準備(instance methodでは不要だがAPI統一のため) let mut ctx = LoweringContext { context_active: false, saved_var_map: Some(std::mem::take(&mut self.variable_map)), saved_static_ctx: None, saved_function: None, saved_block: None, saved_slot_registry: self.current_slot_registry.take(), }; // Step 2b: 関数スケルトン作成(method版) self.create_method_skeleton(func_name, &box_name, ¶ms, &body, &mut ctx)?; // Step 3b: パラメータ設定(me + params) self.setup_method_params(&box_name, ¶ms); // Step 4b: 本体lowering(cf_block版) self.lower_method_body(body)?; // Step 5: 関数finalize let returns_value = if let Some(ref f) = self.current_function { !matches!(f.signature.return_type, MirType::Void) } else { false }; // Void return追加(必要な場合) if !returns_value && !self.is_current_block_terminated() { let void_val = crate::mir::builder::emission::constant::emit_void(self); self.emit_instruction(MirInstruction::Return { value: Some(void_val), })?; } // 型推論(Step 5の一部として) if let Some(ref mut f) = self.current_function { if returns_value && matches!(f.signature.return_type, MirType::Void | MirType::Unknown) { let mut inferred: Option = None; 'search: for (_bid, bb) in f.blocks.iter() { for inst in bb.instructions.iter() { if let MirInstruction::Return { value: Some(v) } = inst { if let Some(mt) = self.type_ctx.value_types.get(v).cloned() { inferred = Some(mt); break 'search; } } } if let Some(MirInstruction::Return { value: Some(v) }) = &bb.terminator { if let Some(mt) = self.type_ctx.value_types.get(v).cloned() { inferred = Some(mt); break; } } } if let Some(mt) = inferred { f.signature.return_type = mt; } } } // Moduleに追加 let finalized_function = self.current_function.take().unwrap(); if let Some(ref mut module) = self.current_module { module.add_function(finalized_function); } // FunctionRegion を 1 段ポップして元の関数コンテキストに戻るよ。 crate::mir::region::observer::pop_function_region(self); // Phase 136 Step 3/7: Restore to scope_ctx (SSOT), sync to legacy field self.scope_ctx.current_function = ctx.saved_function.clone(); self.current_function = ctx.saved_function; self.current_block = ctx.saved_block; if let Some(saved) = ctx.saved_var_map { self.variable_map = saved; } self.current_slot_registry = ctx.saved_slot_registry; // Phase 200-C: Clear fn_body_ast after function lowering self.fn_body_ast = None; Ok(()) } }