//! 🎯 箱理論: 関数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.comp_ctx.current_static_box.clone(); if let Some(pos) = func_name.find('.') { let box_name = &func_name[..pos]; if !box_name.is_empty() { self.comp_ctx.current_static_box = Some(box_name.to_string()); } } // BoxCompilationContext vs saved_var_map モード判定 let context_active = self.comp_ctx.compilation_context.is_some(); let saved_var_map = if !context_active { Some(std::mem::take(&mut self.variable_ctx.variable_map)) } else { None }; // 関数スコープ SlotRegistry は元の関数側から退避しておくよ。 let saved_slot_registry = self.comp_ctx.current_slot_registry.take(); // BoxCompilationContext mode: clear()で完全独立化 if context_active { self.variable_ctx.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) ctx.saved_function = self.scope_ctx.current_function.take(); ctx.saved_block = self.current_block.take(); let trace = crate::mir::builder::control_flow::joinir::trace::trace(); trace.emit_if( "debug", "create_function_skeleton", &format!("Creating function: {}", func_name), trace.is_enabled(), ); trace.emit_if( "debug", "create_function_skeleton", &format!("Entry block: {:?}", entry), trace.is_enabled(), ); // Phase 136 Step 3/7: Use scope_ctx as SSOT self.scope_ctx.current_function = Some(function); self.current_block = Some(entry); // 新しい関数スコープ用の SlotRegistry を準備するよ(観測専用) self.comp_ctx.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 scope_ctx (SSOT) self.scope_ctx.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.scope_ctx.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_ctx.variable_map.insert(p.clone(), pid); // Phase 136 Step 3/7: Insert into scope_ctx (SSOT) self.scope_ctx.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.comp_ctx.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> { let trace = crate::mir::builder::control_flow::joinir::trace::trace(); // Phase 112: StepTree capability guard (strict-only) let strict = crate::config::env::joinir_dev::strict_enabled(); let dev = crate::config::env::joinir_dev_enabled(); if strict || dev { let tree = crate::mir::control_tree::StepTreeBuilderBox::build_from_block(&body); if dev { trace.dev("control_tree/step_tree", &tree.to_compact_string()); } // Phase 112: Guard check (strict mode only) let func_name = self .scope_ctx .current_function .as_ref() .map(|f| f.signature.name.clone()) .unwrap_or_else(|| "".to_string()); crate::mir::builder::control_flow::joinir::control_tree_capability_guard::check( &tree, &func_name, strict, dev, )?; // Phase 121/122: StepTree→Normalized shadow lowering (dev-only) if dev { use crate::mir::control_tree::normalized_shadow::StepTreeNormalizedShadowLowererBox; use crate::mir::control_tree::normalized_shadow::parity; // Try shadow lowering (if-only scope) let shadow_result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree); match shadow_result { Ok(Some((module, _meta))) => { // Phase 122: Verify Normalized JoinModule structure let expected_env_fields = tree.contract.writes.len(); let verify_result = parity::verify_normalized_structure(&module, expected_env_fields); if !verify_result.ok { let msg = format!( "phase122/emit: structure verification failed for {}: {}", func_name, verify_result.hint.unwrap_or_else(|| "".to_string()) ); if strict { return Err(format!( "Phase122 Normalized structure verification failed (strict mode): {}", msg )); } trace.dev("phase122/emit/error", &msg); } else { // Shadow lowering succeeded + structure verified let status = format!( "module_emitted=true funcs={} env_fields={} step_tree_sig={}", module.functions.len(), expected_env_fields, tree.signature_basis_string() ); trace.dev("phase122/emit", &status); } } Ok(None) => { // Out of scope (e.g., contains loops) let status = StepTreeNormalizedShadowLowererBox::get_status_string(&tree); trace.dev("phase121/shadow", &status); } Err(err) => { // Should be supported but failed (internal error) let msg = format!( "phase121/shadow: internal error for {}: {}", func_name, err ); if strict { return Err(format!( "Phase121 shadow lowering failed (strict mode): {}\nHint: if-only pattern should be supported but conversion failed", err )); } trace.dev("phase121/shadow/error", &msg); } } } } trace.emit_if( "debug", "lower_function_body", &format!("body.len() = {}", body.len()), trace.is_enabled(), ); let program_ast = function_lowering::wrap_in_program(body); trace.emit_if( "debug", "lower_function_body", "About to call build_expression", trace.is_enabled(), ); let _last = self.build_expression(program_ast)?; trace.emit_if( "debug", "lower_function_body", "build_expression completed", trace.is_enabled(), ); 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.scope_ctx.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.scope_ctx.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 scope_ctx (SSOT) let finalized = self.scope_ctx.current_function.take().unwrap(); 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) self.scope_ctx.current_function = ctx.saved_function; self.current_block = ctx.saved_block; // モード別にcontext復元 if ctx.context_active { // BoxCompilationContext mode: clear のみ(次回も完全独立) self.variable_ctx.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_ctx.variable_map = saved; } // Static box context復元 self.comp_ctx.current_static_box = ctx.saved_static_ctx; // 関数スコープ SlotRegistry も元の関数に戻すよ。 self.comp_ctx.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) ctx.saved_function = self.scope_ctx.current_function.take(); ctx.saved_block = self.current_block.take(); // Phase 136 Step 3/7: Use scope_ctx as SSOT self.scope_ctx.current_function = Some(function); self.current_block = Some(entry); // instance method 用の関数スコープ SlotRegistry もここで用意するよ。 self.comp_ctx.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.scope_ctx.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_ctx .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_ctx.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_ctx.variable_map.insert(p.clone(), pid); slot_regs.push((p.clone(), None)); } } } if let Some(reg) = self.comp_ctx.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.comp_ctx.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.scope_ctx.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.comp_ctx.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.comp_ctx.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_ctx.variable_map)), saved_static_ctx: None, saved_function: None, saved_block: None, saved_slot_registry: self.comp_ctx.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.scope_ctx.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.scope_ctx.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.scope_ctx.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) self.scope_ctx.current_function = ctx.saved_function; self.current_block = ctx.saved_block; if let Some(saved) = ctx.saved_var_map { self.variable_ctx.variable_map = saved; } self.comp_ctx.current_slot_registry = ctx.saved_slot_registry; // Phase 200-C: Clear fn_body_ast after function lowering self.comp_ctx.fn_body_ast = None; Ok(()) } }