Files
hakorune/src/mir/builder/calls/lowering.rs
nyash-codex 73844dbe04 feat(builder): CalleeBoxKind構造ガードで静的/ランタイムBox混線を根絶
🎯 箱理論の実践: 「境界を作る」原則による構造レベル分離

## 問題
- StageBArgsBox.resolve_src内のargs.get(i)が
  Stage1UsingResolverBox.getに化ける(静的Box名混入)
- 未定義ValueIdエラー発生(receiver定義なし)

## 解決策(構造ガード)
 CalleeBoxKind enum追加
  - StaticCompiler: Stage-B/Stage-1コンパイラBox
  - RuntimeData: MapBox/ArrayBox等ランタイムBox
  - UserDefined: ユーザー定義Box

 classify_box_kind(): Box名から種別判定
  - 静的Box群を明示的に列挙(1箇所に集約)
  - ランタイムBox群を明示的に列挙
  - 将来の拡張も容易

 apply_static_runtime_guard(): 混線検出・正規化
  - me-call判定(receiver型==box_name → 静的降下に委ねる)
  - 真の混線検出(receiver型≠box_name → 正規化)
  - トレースログで可視化

## 効果
- 修正前: Invalid value ValueId(150/187)
- 修正後: Unknown method 'is_space' (別issue、StringBox実装不足)
- → 静的Box名混入問題を根絶!

## 箱理論原則
-  境界を作る: Static/Runtime/UserDefinedを構造的に分離
-  Fail-Fast: フォールバックより明示的エラー
-  箱にする: CalleeBoxKindでBox種類を1箇所に集約

## ファイル
- src/mir/definitions/call_unified.rs: CalleeBoxKind enum
- src/mir/builder/calls/call_unified.rs: classify_box_kind()
- src/mir/builder/calls/emit.rs: apply_static_runtime_guard()
- docs/development/roadmap/phases/phase-25.1d/README.md: 箱化メモ更新

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 23:13:57 +09:00

360 lines
13 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.

//! 🎯 箱理論: 関数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 {
for p in params {
let pid = f.next_value_id();
f.params.push(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 - 本体loweringinstance 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, &params, &body, &mut ctx)?;
// Step 3: パラメータ設定
self.setup_function_params(&params);
// 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, &params, &body, &mut ctx)?;
// Step 3b: パラメータ設定me + params
self.setup_method_params(&box_name, &params);
// Step 4b: 本体loweringcf_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(())
}
}