📦 箱理論: Parameter ValueId完全予約システム確立 ## 🎯 根本原因 Hotfix 4でnext_value_id counterは予約したが、paramsベクトルが空のまま。 setup_function_params()が新規ValueIdをインクリメント済みcounterから割り当て。 結果: シグネチャは%0だが本体は%2を使用するミスマッチ発生。 ## ✅ 修正内容 ### 1. src/mir/function.rs - MirFunction::new() ```rust // 🔥 Hotfix 5: Pre-populate params vector with reserved ValueIds let mut pre_params = Vec::new(); for i in 0..total_value_ids { pre_params.push(ValueId::new(i)); } // ... params: pre_params, // ✅ Pre-populate instead of empty Vec ``` ### 2. src/mir/builder/calls/lowering.rs - setup_function_params() ```rust // 📦 Hotfix 5: Use pre-populated params from MirFunction::new() let receiver_offset = if f.params.is_empty() { 0 } else { if f.params.len() > params.len() { 1 } else { 0 } }; for (idx, p) in params.iter().enumerate() { let param_idx = receiver_offset + idx; let pid = if param_idx < f.params.len() { f.params[param_idx] // Use pre-allocated ValueId } else { let new_pid = f.next_value_id(); f.params.push(new_pid); new_pid }; // ... } ``` ## 📊 テスト結果 - ✅ mir_parserbox_parse_program2_harness_parses_minimal_source: PASS - ✅ mir_stage1_using_resolver_full_collect_entries_verifies: PASS - ⚠️ mir_stage1_using_resolver_min_fragment_verifies: 別問題(dominator violation) ## 🎉 成果 - **Parameter ValueId問題完全解決**: 0/3 → 2/3 tests passing - **Counter予約とVector実体の完全一致**: シグネチャと本体の整合性確保 - **Static method receiver完全対応**: 暗黙receiverも正しく予約 ## 🔧 次のステップ 残り1テストのdominator violation調査(LoopForm Exit PHI生成問題) Co-Authored-By: task先生 <task@anthropic.com>
375 lines
14 KiB
Rust
375 lines
14 KiB
Rust
//! 🎯 箱理論: 関数lowering処理
|
||
//!
|
||
//! 責務:
|
||
//! - static/instance method を MIR function に lowering
|
||
//! - BoxCompilationContext による完全独立化
|
||
//! - パラメータ・型情報の適切な管理
|
||
|
||
use crate::ast::ASTNode;
|
||
use crate::mir::builder::{MirBuilder, MirType, MirInstruction};
|
||
use super::function_lowering;
|
||
use std::collections::HashMap;
|
||
|
||
/// 🎯 箱理論: Lowering Context(準備と復元)
|
||
struct LoweringContext {
|
||
context_active: bool,
|
||
saved_var_map: Option<HashMap<String, super::super::ValueId>>,
|
||
saved_static_ctx: Option<String>,
|
||
saved_function: Option<super::super::MirFunction>,
|
||
saved_block: Option<super::super::BasicBlockId>,
|
||
}
|
||
|
||
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
|
||
};
|
||
|
||
// BoxCompilationContext mode: clear()で完全独立化
|
||
if context_active {
|
||
self.variable_map.clear();
|
||
self.value_origin_newbox.clear();
|
||
// value_types も static box 単位で独立させる。
|
||
// これにより、前の static box で使用された ValueId に紐づく型情報が
|
||
// 次の box にリークして誤った box_name 推論(例: Stage1UsingResolverBox)
|
||
// を引き起こすことを防ぐ。
|
||
self.value_types.clear();
|
||
}
|
||
|
||
LoweringContext {
|
||
context_active,
|
||
saved_var_map,
|
||
saved_static_ctx,
|
||
saved_function: None,
|
||
saved_block: None,
|
||
}
|
||
}
|
||
|
||
/// 🎯 箱理論: 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,
|
||
params,
|
||
body,
|
||
);
|
||
let entry = self.block_gen.next();
|
||
let function = super::super::MirFunction::new(signature, entry);
|
||
|
||
// 現在の関数・ブロックを保存
|
||
ctx.saved_function = self.current_function.take();
|
||
ctx.saved_block = self.current_block.take();
|
||
|
||
// 新しい関数に切り替え
|
||
self.current_function = Some(function);
|
||
self.current_block = Some(entry);
|
||
self.ensure_block_exists(entry)?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 🎯 箱理論: Step 3 - パラメータ設定
|
||
fn setup_function_params(&mut self, params: &[String]) {
|
||
self.function_param_names.clear();
|
||
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 }
|
||
};
|
||
|
||
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);
|
||
self.function_param_names.insert(p.clone());
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 🎯 箱理論: Step 4 - 本体lowering
|
||
fn lower_function_body(&mut self, body: Vec<ASTNode>) -> Result<(), String> {
|
||
let program_ast = function_lowering::wrap_in_program(body);
|
||
let _last = self.build_expression(program_ast)?;
|
||
Ok(())
|
||
}
|
||
|
||
/// 🎯 箱理論: Step 5 - 関数finalize
|
||
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<MirType> = 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.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.value_types.get(v).cloned() {
|
||
inferred = Some(mt);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if let Some(mt) = inferred {
|
||
f.signature.return_type = mt;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Moduleに追加
|
||
let finalized = self.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) {
|
||
// 関数・ブロック復元
|
||
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.value_origin_newbox.clear();
|
||
// static box ごとに型情報も独立させる(前 box の型メタデータを引きずらない)
|
||
self.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;
|
||
}
|
||
|
||
/// 🎯 箱理論: 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.block_gen.next();
|
||
let function = super::super::MirFunction::new(signature, entry);
|
||
|
||
// 現在の関数・ブロックを保存
|
||
ctx.saved_function = self.current_function.take();
|
||
ctx.saved_block = self.current_block.take();
|
||
|
||
// 新しい関数に切り替え
|
||
self.current_function = Some(function);
|
||
self.current_block = Some(entry);
|
||
self.ensure_block_exists(entry)?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 🎯 箱理論: Step 3b - パラメータ設定(instance method版: me + params)
|
||
fn setup_method_params(&mut self, box_name: &str, params: &[String]) {
|
||
if let Some(ref mut f) = self.current_function {
|
||
// First parameter is always 'me'
|
||
let me_id = f.next_value_id();
|
||
f.params.push(me_id);
|
||
self.variable_map.insert("me".to_string(), me_id);
|
||
self.value_origin_newbox.insert(me_id, box_name.to_string());
|
||
|
||
// Then regular parameters
|
||
for p in params {
|
||
let pid = f.next_value_id();
|
||
f.params.push(pid);
|
||
self.variable_map.insert(p.clone(), pid);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// 🎯 箱理論: Step 4b - 本体lowering(instance method版: cf_block)
|
||
fn lower_method_body(&mut self, body: Vec<ASTNode>) -> 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<String>,
|
||
body: Vec<ASTNode>,
|
||
) -> Result<(), String> {
|
||
// 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)?;
|
||
|
||
// Step 6: Context復元
|
||
self.restore_lowering_context(ctx);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// 🎯 箱理論: 統合エントリーポイント - instance method lowering
|
||
pub(in crate::mir::builder) fn lower_method_as_function(
|
||
&mut self,
|
||
func_name: String,
|
||
box_name: String,
|
||
params: Vec<String>,
|
||
body: Vec<ASTNode>,
|
||
) -> Result<(), String> {
|
||
// 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,
|
||
};
|
||
|
||
// 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<MirType> = 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.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.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);
|
||
}
|
||
|
||
// Step 6: Context復元(simple version)
|
||
self.current_function = ctx.saved_function;
|
||
self.current_block = ctx.saved_block;
|
||
if let Some(saved) = ctx.saved_var_map {
|
||
self.variable_map = saved;
|
||
}
|
||
|
||
Ok(())
|
||
}
|
||
}
|