2025-11-17 17:02:01 +09:00
|
|
|
|
//! 🎯 箱理論: 関数lowering処理
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! 責務:
|
|
|
|
|
|
//! - static/instance method を MIR function に lowering
|
|
|
|
|
|
//! - BoxCompilationContext による完全独立化
|
|
|
|
|
|
//! - パラメータ・型情報の適切な管理
|
|
|
|
|
|
|
2025-11-21 06:25:17 +09:00
|
|
|
|
use super::function_lowering;
|
2025-11-17 17:02:01 +09:00
|
|
|
|
use crate::ast::ASTNode;
|
2025-11-21 06:25:17 +09:00
|
|
|
|
use crate::mir::builder::{MirBuilder, MirInstruction, MirType};
|
2025-11-19 03:28:58 +09:00
|
|
|
|
use crate::mir::region::function_slot_registry::FunctionSlotRegistry;
|
2025-11-21 06:25:17 +09:00
|
|
|
|
use crate::mir::{MirValueKind, ValueId}; // Phase 26-A-3: ValueId型安全化
|
2025-11-22 05:33:40 +09:00
|
|
|
|
use std::collections::BTreeMap; // Phase 25.1: 決定性確保
|
2025-11-17 17:02:01 +09:00
|
|
|
|
|
|
|
|
|
|
/// 🎯 箱理論: Lowering Context(準備と復元)
|
|
|
|
|
|
struct LoweringContext {
|
|
|
|
|
|
context_active: bool,
|
2025-11-22 05:33:40 +09:00
|
|
|
|
saved_var_map: Option<BTreeMap<String, super::super::ValueId>>, // Phase 25.1: BTreeMap化
|
2025-11-17 17:02:01 +09:00
|
|
|
|
saved_static_ctx: Option<String>,
|
|
|
|
|
|
saved_function: Option<super::super::MirFunction>,
|
|
|
|
|
|
saved_block: Option<super::super::BasicBlockId>,
|
2025-11-19 03:28:58 +09:00
|
|
|
|
saved_slot_registry: Option<FunctionSlotRegistry>,
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl MirBuilder {
|
|
|
|
|
|
/// 🎯 箱理論: Step 1 - Lowering Context準備
|
2025-11-21 06:25:17 +09:00
|
|
|
|
fn prepare_lowering_context(&mut self, func_name: &str) -> LoweringContext {
|
2025-11-17 17:02:01 +09:00
|
|
|
|
// Static box context設定
|
2025-12-16 04:07:17 +09:00
|
|
|
|
let saved_static_ctx = self.comp_ctx.current_static_box.clone();
|
2025-11-17 17:02:01 +09:00
|
|
|
|
if let Some(pos) = func_name.find('.') {
|
|
|
|
|
|
let box_name = &func_name[..pos];
|
|
|
|
|
|
if !box_name.is_empty() {
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.current_static_box = Some(box_name.to_string());
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// BoxCompilationContext vs saved_var_map モード判定
|
2025-12-16 04:07:17 +09:00
|
|
|
|
let context_active = self.comp_ctx.compilation_context.is_some();
|
2025-11-17 17:02:01 +09:00
|
|
|
|
let saved_var_map = if !context_active {
|
2025-12-16 03:48:44 +09:00
|
|
|
|
Some(std::mem::take(&mut self.variable_ctx.variable_map))
|
2025-11-17 17:02:01 +09:00
|
|
|
|
} else {
|
|
|
|
|
|
None
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// 関数スコープ SlotRegistry は元の関数側から退避しておくよ。
|
2025-12-16 04:07:17 +09:00
|
|
|
|
let saved_slot_registry = self.comp_ctx.current_slot_registry.take();
|
2025-11-19 03:28:58 +09:00
|
|
|
|
|
2025-11-17 17:02:01 +09:00
|
|
|
|
// BoxCompilationContext mode: clear()で完全独立化
|
|
|
|
|
|
if context_active {
|
2025-12-16 03:48:44 +09:00
|
|
|
|
self.variable_ctx.variable_map.clear();
|
2025-12-15 23:27:24 +09:00
|
|
|
|
self.type_ctx.value_origin_newbox.clear();
|
2025-11-17 23:13:57 +09:00
|
|
|
|
// value_types も static box 単位で独立させる。
|
|
|
|
|
|
// これにより、前の static box で使用された ValueId に紐づく型情報が
|
|
|
|
|
|
// 次の box にリークして誤った box_name 推論(例: Stage1UsingResolverBox)
|
|
|
|
|
|
// を引き起こすことを防ぐ。
|
2025-12-15 23:27:24 +09:00
|
|
|
|
self.type_ctx.value_types.clear();
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LoweringContext {
|
|
|
|
|
|
context_active,
|
|
|
|
|
|
saved_var_map,
|
|
|
|
|
|
saved_static_ctx,
|
|
|
|
|
|
saved_function: None,
|
|
|
|
|
|
saved_block: None,
|
2025-11-19 03:28:58 +09:00
|
|
|
|
saved_slot_registry,
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 🎯 箱理論: Step 2 - 関数スケルトン作成
|
|
|
|
|
|
fn create_function_skeleton(
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
func_name: String,
|
|
|
|
|
|
params: &[String],
|
|
|
|
|
|
body: &[ASTNode],
|
|
|
|
|
|
ctx: &mut LoweringContext,
|
|
|
|
|
|
) -> Result<(), String> {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
let signature =
|
|
|
|
|
|
function_lowering::prepare_static_method_signature(func_name.clone(), params, body);
|
2025-12-15 20:10:36 +09:00
|
|
|
|
let entry = self.next_block_id();
|
2025-11-24 14:17:02 +09:00
|
|
|
|
let function = self.new_function_with_metadata(signature, entry);
|
2025-11-19 03:28:58 +09:00
|
|
|
|
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Save from scope_ctx (SSOT)
|
2025-12-15 20:28:21 +09:00
|
|
|
|
ctx.saved_function = self.scope_ctx.current_function.take();
|
2025-11-17 17:02:01 +09:00
|
|
|
|
ctx.saved_block = self.current_block.take();
|
2025-11-19 03:28:58 +09:00
|
|
|
|
|
2025-12-18 00:29:57 +09:00
|
|
|
|
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(),
|
2025-11-21 06:25:17 +09:00
|
|
|
|
);
|
2025-11-19 08:04:43 +09:00
|
|
|
|
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Use scope_ctx as SSOT
|
|
|
|
|
|
self.scope_ctx.current_function = Some(function);
|
2025-11-17 17:02:01 +09:00
|
|
|
|
self.current_block = Some(entry);
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// 新しい関数スコープ用の SlotRegistry を準備するよ(観測専用)
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.current_slot_registry = Some(FunctionSlotRegistry::new());
|
2025-11-17 17:02:01 +09:00
|
|
|
|
self.ensure_block_exists(entry)?;
|
2025-11-19 03:28:58 +09:00
|
|
|
|
|
|
|
|
|
|
// Region 観測レイヤ: static 関数用の FunctionRegion を積むよ。
|
|
|
|
|
|
crate::mir::region::observer::observe_function_region(self);
|
2025-11-19 08:04:43 +09:00
|
|
|
|
|
2025-11-17 17:02:01 +09:00
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 🎯 箱理論: Step 3 - パラメータ設定
|
2025-12-15 20:28:21 +09:00
|
|
|
|
#[allow(deprecated)]
|
2025-11-17 17:02:01 +09:00
|
|
|
|
fn setup_function_params(&mut self, params: &[String]) {
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Clear scope_ctx (SSOT)
|
2025-12-15 20:28:21 +09:00
|
|
|
|
self.scope_ctx.function_param_names.clear();
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// SlotRegistry 更新は borrow 競合を避けるため、まずローカルに集約してから反映するよ。
|
|
|
|
|
|
let mut slot_regs: Vec<(String, Option<MirType>)> = Vec::new();
|
2025-11-20 09:40:18 +09:00
|
|
|
|
// Phase 26-A-3: パラメータ型情報も後で一括登録(借用競合回避)
|
|
|
|
|
|
let mut param_kinds: Vec<(ValueId, u32)> = Vec::new();
|
2025-11-19 03:28:58 +09:00
|
|
|
|
|
2025-12-15 23:41:30 +09:00
|
|
|
|
if let Some(ref mut f) = self.scope_ctx.current_function {
|
2025-11-18 07:56:47 +09:00
|
|
|
|
// 📦 Hotfix 5: Use pre-populated params from MirFunction::new()
|
|
|
|
|
|
// Static methods have implicit receiver at params[0], so actual parameters start at offset
|
2025-11-21 06:25:17 +09:00
|
|
|
|
let receiver_offset = if f.params.is_empty() {
|
|
|
|
|
|
0
|
|
|
|
|
|
} else {
|
2025-11-18 07:56:47 +09:00
|
|
|
|
// If params already populated (by Hotfix 4+5), use them
|
2025-11-21 06:25:17 +09:00
|
|
|
|
if f.params.len() > params.len() {
|
|
|
|
|
|
1
|
|
|
|
|
|
} else {
|
|
|
|
|
|
0
|
|
|
|
|
|
}
|
2025-11-18 07:56:47 +09:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-11-19 03:28:58 +09:00
|
|
|
|
let param_types = f.signature.params.clone();
|
|
|
|
|
|
|
2025-11-18 07:56:47 +09:00
|
|
|
|
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
|
|
|
|
|
|
};
|
2025-12-16 03:48:44 +09:00
|
|
|
|
self.variable_ctx.variable_map.insert(p.clone(), pid);
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Insert into scope_ctx (SSOT)
|
2025-12-15 20:28:21 +09:00
|
|
|
|
self.scope_ctx.function_param_names.insert(p.clone());
|
2025-11-20 09:40:18 +09:00
|
|
|
|
|
|
|
|
|
|
// Phase 26-A-3: パラメータ型情報を収集(後で一括登録)
|
|
|
|
|
|
// param_idx: receiver offset を考慮した実際のパラメータインデックス
|
|
|
|
|
|
param_kinds.push((pid, param_idx as u32));
|
|
|
|
|
|
|
2025-11-19 03:28:58 +09:00
|
|
|
|
let ty = param_types.get(param_idx).cloned();
|
|
|
|
|
|
slot_regs.push((p.clone(), ty));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-20 09:40:18 +09:00
|
|
|
|
// Phase 26-A-3: パラメータ型情報を一括登録(GUARD Bug Prevention)
|
|
|
|
|
|
for (pid, param_idx) in param_kinds {
|
|
|
|
|
|
self.register_value_kind(pid, MirValueKind::Parameter(param_idx));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-16 04:07:17 +09:00
|
|
|
|
if let Some(reg) = self.comp_ctx.current_slot_registry.as_mut() {
|
2025-11-19 03:28:58 +09:00
|
|
|
|
for (name, ty) in slot_regs {
|
|
|
|
|
|
reg.ensure_slot(&name, ty);
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 🎯 箱理論: Step 4 - 本体lowering
|
|
|
|
|
|
fn lower_function_body(&mut self, body: Vec<ASTNode>) -> Result<(), String> {
|
2025-12-18 00:29:57 +09:00
|
|
|
|
let trace = crate::mir::builder::control_flow::joinir::trace::trace();
|
|
|
|
|
|
|
feat(joinir): Phase 112 strict guard for StepTree required_caps
- Add control_tree_capability_guard.rs with check(tree, func_name, strict, dev)
- Allowlist: If, NestedIf, Loop, Return, Break, Continue
- Deny (strict): NestedLoop, TryCatch, Throw, Lambda, While, ForRange, Match, Arrow
- Wire into lower_function_body() (strict-only check)
- Error format: [joinir/control_tree/cap_missing/<Cap>] with 1-line Hint
- Unit tests: nested_loop_rejects, if_only_passes, strict_false_passes
- Default behavior unchanged (strict=false always Ok)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 01:38:25 +09:00
|
|
|
|
// 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 {
|
2025-12-18 00:22:21 +09:00
|
|
|
|
let tree = crate::mir::control_tree::StepTreeBuilderBox::build_from_block(&body);
|
feat(joinir): Phase 112 strict guard for StepTree required_caps
- Add control_tree_capability_guard.rs with check(tree, func_name, strict, dev)
- Allowlist: If, NestedIf, Loop, Return, Break, Continue
- Deny (strict): NestedLoop, TryCatch, Throw, Lambda, While, ForRange, Match, Arrow
- Wire into lower_function_body() (strict-only check)
- Error format: [joinir/control_tree/cap_missing/<Cap>] with 1-line Hint
- Unit tests: nested_loop_rejects, if_only_passes, strict_false_passes
- Default behavior unchanged (strict=false always Ok)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 01:38:25 +09:00
|
|
|
|
|
|
|
|
|
|
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(|| "<unknown>".to_string());
|
|
|
|
|
|
|
|
|
|
|
|
crate::mir::builder::control_flow::joinir::control_tree_capability_guard::check(
|
|
|
|
|
|
&tree, &func_name, strict, dev,
|
|
|
|
|
|
)?;
|
2025-12-18 04:34:43 +09:00
|
|
|
|
|
2025-12-18 04:52:09 +09:00
|
|
|
|
// Phase 121/122: StepTree→Normalized shadow lowering (dev-only)
|
2025-12-18 04:34:43 +09:00
|
|
|
|
if dev {
|
|
|
|
|
|
use crate::mir::control_tree::normalized_shadow::StepTreeNormalizedShadowLowererBox;
|
2025-12-18 04:52:09 +09:00
|
|
|
|
use crate::mir::control_tree::normalized_shadow::parity;
|
2025-12-18 04:34:43 +09:00
|
|
|
|
|
|
|
|
|
|
// Try shadow lowering (if-only scope)
|
|
|
|
|
|
let shadow_result = StepTreeNormalizedShadowLowererBox::try_lower_if_only(&tree);
|
|
|
|
|
|
|
|
|
|
|
|
match shadow_result {
|
2025-12-18 04:52:09 +09:00
|
|
|
|
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(|| "<no hint>".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);
|
|
|
|
|
|
}
|
2025-12-18 04:34:43 +09:00
|
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-18 00:22:21 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-18 00:29:57 +09:00
|
|
|
|
trace.emit_if(
|
|
|
|
|
|
"debug",
|
|
|
|
|
|
"lower_function_body",
|
|
|
|
|
|
&format!("body.len() = {}", body.len()),
|
|
|
|
|
|
trace.is_enabled(),
|
|
|
|
|
|
);
|
2025-11-17 17:02:01 +09:00
|
|
|
|
let program_ast = function_lowering::wrap_in_program(body);
|
2025-12-18 00:29:57 +09:00
|
|
|
|
trace.emit_if(
|
|
|
|
|
|
"debug",
|
|
|
|
|
|
"lower_function_body",
|
|
|
|
|
|
"About to call build_expression",
|
|
|
|
|
|
trace.is_enabled(),
|
|
|
|
|
|
);
|
2025-11-17 17:02:01 +09:00
|
|
|
|
let _last = self.build_expression(program_ast)?;
|
2025-12-18 00:29:57 +09:00
|
|
|
|
trace.emit_if(
|
|
|
|
|
|
"debug",
|
|
|
|
|
|
"lower_function_body",
|
|
|
|
|
|
"build_expression completed",
|
|
|
|
|
|
trace.is_enabled(),
|
|
|
|
|
|
);
|
2025-11-17 17:02:01 +09:00
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 🎯 箱理論: Step 5 - 関数finalize
|
2025-12-15 20:28:21 +09:00
|
|
|
|
#[allow(deprecated)]
|
2025-11-17 17:02:01 +09:00
|
|
|
|
fn finalize_function(&mut self, returns_value: bool) -> Result<(), String> {
|
|
|
|
|
|
// Void return追加(必要な場合)
|
|
|
|
|
|
if !returns_value {
|
2025-12-15 23:41:30 +09:00
|
|
|
|
if let Some(ref mut f) = self.scope_ctx.current_function {
|
2025-11-17 17:02:01 +09:00
|
|
|
|
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),
|
|
|
|
|
|
})?;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 型推論
|
2025-12-15 23:41:30 +09:00
|
|
|
|
if let Some(ref mut f) = self.scope_ctx.current_function {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
if returns_value && matches!(f.signature.return_type, MirType::Void | MirType::Unknown)
|
2025-11-17 17:02:01 +09:00
|
|
|
|
{
|
|
|
|
|
|
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 {
|
2025-12-15 23:27:24 +09:00
|
|
|
|
if let Some(mt) = self.type_ctx.value_types.get(v).cloned() {
|
2025-11-17 17:02:01 +09:00
|
|
|
|
inferred = Some(mt);
|
|
|
|
|
|
break 'search;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if let Some(MirInstruction::Return { value: Some(v) }) = &bb.terminator {
|
2025-12-15 23:27:24 +09:00
|
|
|
|
if let Some(mt) = self.type_ctx.value_types.get(v).cloned() {
|
2025-11-17 17:02:01 +09:00
|
|
|
|
inferred = Some(mt);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if let Some(mt) = inferred {
|
|
|
|
|
|
f.signature.return_type = mt;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Moduleに追加
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Take from scope_ctx (SSOT)
|
|
|
|
|
|
let finalized = self.scope_ctx.current_function.take().unwrap();
|
2025-11-17 17:02:01 +09:00
|
|
|
|
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) {
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Restore to scope_ctx (SSOT)
|
|
|
|
|
|
self.scope_ctx.current_function = ctx.saved_function;
|
2025-11-17 17:02:01 +09:00
|
|
|
|
self.current_block = ctx.saved_block;
|
|
|
|
|
|
|
|
|
|
|
|
// モード別にcontext復元
|
|
|
|
|
|
if ctx.context_active {
|
|
|
|
|
|
// BoxCompilationContext mode: clear のみ(次回も完全独立)
|
2025-12-16 03:48:44 +09:00
|
|
|
|
self.variable_ctx.variable_map.clear();
|
2025-12-15 23:27:24 +09:00
|
|
|
|
self.type_ctx.value_origin_newbox.clear();
|
2025-11-17 23:13:57 +09:00
|
|
|
|
// static box ごとに型情報も独立させる(前 box の型メタデータを引きずらない)
|
2025-12-15 23:27:24 +09:00
|
|
|
|
self.type_ctx.value_types.clear();
|
2025-11-17 17:02:01 +09:00
|
|
|
|
} else if let Some(saved) = ctx.saved_var_map {
|
|
|
|
|
|
// Legacy mode: Main.main 側の variable_map を元に戻す
|
2025-12-16 03:48:44 +09:00
|
|
|
|
self.variable_ctx.variable_map = saved;
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Static box context復元
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.current_static_box = ctx.saved_static_ctx;
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// 関数スコープ SlotRegistry も元の関数に戻すよ。
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.current_slot_registry = ctx.saved_slot_registry;
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 🎯 箱理論: 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> {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
let signature =
|
|
|
|
|
|
function_lowering::prepare_method_signature(func_name, box_name, params, body);
|
2025-12-15 20:10:36 +09:00
|
|
|
|
let entry = self.next_block_id();
|
2025-11-24 14:17:02 +09:00
|
|
|
|
let function = self.new_function_with_metadata(signature, entry);
|
2025-11-17 17:02:01 +09:00
|
|
|
|
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Save from scope_ctx (SSOT)
|
2025-12-15 20:28:21 +09:00
|
|
|
|
ctx.saved_function = self.scope_ctx.current_function.take();
|
2025-11-17 17:02:01 +09:00
|
|
|
|
ctx.saved_block = self.current_block.take();
|
|
|
|
|
|
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Use scope_ctx as SSOT
|
|
|
|
|
|
self.scope_ctx.current_function = Some(function);
|
2025-11-17 17:02:01 +09:00
|
|
|
|
self.current_block = Some(entry);
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// instance method 用の関数スコープ SlotRegistry もここで用意するよ。
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.current_slot_registry = Some(FunctionSlotRegistry::new());
|
2025-11-17 17:02:01 +09:00
|
|
|
|
self.ensure_block_exists(entry)?;
|
|
|
|
|
|
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// Region 観測レイヤ: instance method 用の FunctionRegion も積んでおくよ。
|
|
|
|
|
|
crate::mir::region::observer::observe_function_region(self);
|
|
|
|
|
|
|
2025-11-17 17:02:01 +09:00
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 🎯 箱理論: Step 3b - パラメータ設定(instance method版: me + params)
|
|
|
|
|
|
fn setup_method_params(&mut self, box_name: &str, params: &[String]) {
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// SlotRegistry 更新はローカルバッファに集約してから反映するよ。
|
|
|
|
|
|
let mut slot_regs: Vec<(String, Option<MirType>)> = Vec::new();
|
|
|
|
|
|
|
2025-12-15 23:41:30 +09:00
|
|
|
|
if let Some(ref mut f) = self.scope_ctx.current_function {
|
2025-11-19 04:01:02 +09:00
|
|
|
|
// 📦 Hotfix 6 改訂版:
|
|
|
|
|
|
// MirFunction::new() が既に 0..N の ValueId を params 用に予約しているので、
|
|
|
|
|
|
// ここではそれを「上書き使用」するだけにして、push で二重定義しないようにするよ。
|
|
|
|
|
|
//
|
|
|
|
|
|
// params レイアウト:
|
|
|
|
|
|
// index 0: me (box<MyBox>)
|
|
|
|
|
|
// 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];
|
2025-12-16 07:02:14 +09:00
|
|
|
|
self.variable_ctx
|
|
|
|
|
|
.variable_map
|
|
|
|
|
|
.insert("me".to_string(), me_id);
|
|
|
|
|
|
self.type_ctx
|
|
|
|
|
|
.value_origin_newbox
|
|
|
|
|
|
.insert(me_id, box_name.to_string());
|
2025-11-19 03:28:58 +09:00
|
|
|
|
slot_regs.push(("me".to_string(), None));
|
2025-11-17 17:02:01 +09:00
|
|
|
|
|
2025-11-19 04:01:02 +09:00
|
|
|
|
// 通常パラメータ
|
2025-11-19 03:37:16 +09:00
|
|
|
|
for (idx, p) in params.iter().enumerate() {
|
2025-11-19 04:01:02 +09:00
|
|
|
|
let param_idx = idx + 1;
|
|
|
|
|
|
if param_idx < f.params.len() {
|
|
|
|
|
|
let pid = f.params[param_idx];
|
2025-12-16 03:48:44 +09:00
|
|
|
|
self.variable_ctx.variable_map.insert(p.clone(), pid);
|
2025-11-19 04:01:02 +09:00
|
|
|
|
slot_regs.push((p.clone(), None));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 念のため足りない場合は新規に確保(互換用)
|
|
|
|
|
|
let pid = f.next_value_id();
|
|
|
|
|
|
f.params.push(pid);
|
2025-12-16 03:48:44 +09:00
|
|
|
|
self.variable_ctx.variable_map.insert(p.clone(), pid);
|
2025-11-19 04:01:02 +09:00
|
|
|
|
slot_regs.push((p.clone(), None));
|
|
|
|
|
|
}
|
2025-11-19 03:28:58 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-16 04:07:17 +09:00
|
|
|
|
if let Some(reg) = self.comp_ctx.current_slot_registry.as_mut() {
|
2025-11-19 03:28:58 +09:00
|
|
|
|
for (name, ty) in slot_regs {
|
|
|
|
|
|
reg.ensure_slot(&name, ty);
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 🎯 箱理論: 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> {
|
2025-12-09 18:32:03 +09:00
|
|
|
|
// Phase 200-C: Store fn_body for capture analysis
|
2025-12-11 20:54:33 +09:00
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[lower_static_method_as_function] Storing fn_body with {} nodes for '{}'",
|
|
|
|
|
|
body.len(),
|
|
|
|
|
|
func_name
|
|
|
|
|
|
);
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.fn_body_ast = Some(body.clone());
|
2025-12-09 18:32:03 +09:00
|
|
|
|
|
2025-11-17 17:02:01 +09:00
|
|
|
|
// 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
|
2025-12-15 23:41:30 +09:00
|
|
|
|
let returns_value = if let Some(ref f) = self.scope_ctx.current_function {
|
2025-11-17 17:02:01 +09:00
|
|
|
|
!matches!(f.signature.return_type, MirType::Void)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
false
|
|
|
|
|
|
};
|
|
|
|
|
|
self.finalize_function(returns_value)?;
|
|
|
|
|
|
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// FunctionRegion を 1 段ポップして元の関数コンテキストに戻るよ。
|
|
|
|
|
|
crate::mir::region::observer::pop_function_region(self);
|
|
|
|
|
|
|
2025-11-17 17:02:01 +09:00
|
|
|
|
// Step 6: Context復元
|
|
|
|
|
|
self.restore_lowering_context(ctx);
|
|
|
|
|
|
|
2025-12-09 18:32:03 +09:00
|
|
|
|
// Phase 200-C: Clear fn_body_ast after function lowering
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.fn_body_ast = None;
|
2025-12-09 18:32:03 +09:00
|
|
|
|
|
2025-11-17 17:02:01 +09:00
|
|
|
|
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> {
|
2025-12-09 18:32:03 +09:00
|
|
|
|
// Phase 200-C: Store fn_body for capture analysis
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.fn_body_ast = Some(body.clone());
|
2025-12-09 18:32:03 +09:00
|
|
|
|
|
2025-11-17 17:02:01 +09:00
|
|
|
|
// Step 1: Context準備(instance methodでは不要だがAPI統一のため)
|
|
|
|
|
|
let mut ctx = LoweringContext {
|
|
|
|
|
|
context_active: false,
|
2025-12-16 03:48:44 +09:00
|
|
|
|
saved_var_map: Some(std::mem::take(&mut self.variable_ctx.variable_map)),
|
2025-11-17 17:02:01 +09:00
|
|
|
|
saved_static_ctx: None,
|
|
|
|
|
|
saved_function: None,
|
|
|
|
|
|
saved_block: None,
|
2025-12-16 04:07:17 +09:00
|
|
|
|
saved_slot_registry: self.comp_ctx.current_slot_registry.take(),
|
2025-11-17 17:02:01 +09:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 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
|
2025-12-15 23:41:30 +09:00
|
|
|
|
let returns_value = if let Some(ref f) = self.scope_ctx.current_function {
|
2025-11-17 17:02:01 +09:00
|
|
|
|
!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の一部として)
|
2025-12-15 23:41:30 +09:00
|
|
|
|
if let Some(ref mut f) = self.scope_ctx.current_function {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
if returns_value && matches!(f.signature.return_type, MirType::Void | MirType::Unknown)
|
2025-11-17 17:02:01 +09:00
|
|
|
|
{
|
|
|
|
|
|
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 {
|
2025-12-15 23:27:24 +09:00
|
|
|
|
if let Some(mt) = self.type_ctx.value_types.get(v).cloned() {
|
2025-11-17 17:02:01 +09:00
|
|
|
|
inferred = Some(mt);
|
|
|
|
|
|
break 'search;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if let Some(MirInstruction::Return { value: Some(v) }) = &bb.terminator {
|
2025-12-15 23:27:24 +09:00
|
|
|
|
if let Some(mt) = self.type_ctx.value_types.get(v).cloned() {
|
2025-11-17 17:02:01 +09:00
|
|
|
|
inferred = Some(mt);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if let Some(mt) = inferred {
|
|
|
|
|
|
f.signature.return_type = mt;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Moduleに追加
|
2025-12-15 23:41:30 +09:00
|
|
|
|
let finalized_function = self.scope_ctx.current_function.take().unwrap();
|
2025-11-17 17:02:01 +09:00
|
|
|
|
if let Some(ref mut module) = self.current_module {
|
|
|
|
|
|
module.add_function(finalized_function);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-19 03:28:58 +09:00
|
|
|
|
// FunctionRegion を 1 段ポップして元の関数コンテキストに戻るよ。
|
|
|
|
|
|
crate::mir::region::observer::pop_function_region(self);
|
|
|
|
|
|
|
2025-12-15 23:41:30 +09:00
|
|
|
|
// Phase 136 Step 3/7: Restore to scope_ctx (SSOT)
|
|
|
|
|
|
self.scope_ctx.current_function = ctx.saved_function;
|
2025-11-17 17:02:01 +09:00
|
|
|
|
self.current_block = ctx.saved_block;
|
|
|
|
|
|
if let Some(saved) = ctx.saved_var_map {
|
2025-12-16 03:48:44 +09:00
|
|
|
|
self.variable_ctx.variable_map = saved;
|
2025-11-17 17:02:01 +09:00
|
|
|
|
}
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.current_slot_registry = ctx.saved_slot_registry;
|
2025-11-17 17:02:01 +09:00
|
|
|
|
|
2025-12-09 18:32:03 +09:00
|
|
|
|
// Phase 200-C: Clear fn_body_ast after function lowering
|
2025-12-16 04:07:17 +09:00
|
|
|
|
self.comp_ctx.fn_body_ast = None;
|
2025-12-09 18:32:03 +09:00
|
|
|
|
|
2025-11-17 17:02:01 +09:00
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|