refactor(joinir): Phase 190 convert.rs modularization

- Created joinir_function_converter.rs (~133 lines): Function-level conversion
- Created joinir_block_converter.rs (~691 lines): Block-level conversion
- Reduced convert.rs from 943 → 120 lines (87% reduction)
- Total: 944 lines (original 943 lines, minimal overhead)
- Separation of concerns: Function vs Block responsibilities
- All handlers moved to block_converter for better organization
- Maintained backward compatibility with existing API
- Build successful, simple tests passing
This commit is contained in:
nyash-codex
2025-12-05 14:41:24 +09:00
parent 827990e742
commit 7c55baa818
14 changed files with 1078 additions and 1154 deletions

View File

@ -1,851 +1,28 @@
use crate::ast::Span;
use crate::mir::join_ir::{
BinOpKind, CompareOp, ConstValue, JoinFunction, JoinInst, JoinModule, MirLikeInst,
BinOpKind, CompareOp, ConstValue, JoinModule, MirLikeInst,
};
use crate::mir::{
BasicBlockId, BinaryOp, CompareOp as MirCompareOp, ConstValue as MirConstValue, EffectMask,
FunctionSignature, MirFunction, MirInstruction, MirModule, MirType, ValueId,
BinaryOp, CompareOp as MirCompareOp, ConstValue as MirConstValue, EffectMask, MirInstruction, MirModule,
};
use super::{join_func_name, JoinIrVmBridgeError};
use super::JoinIrVmBridgeError;
/// ブロックを確定するinstructions + spans + terminator を設定)
fn finalize_block(
mir_func: &mut MirFunction,
block_id: BasicBlockId,
instructions: Vec<MirInstruction>,
terminator: MirInstruction,
) {
if let Some(block) = mir_func.blocks.get_mut(&block_id) {
let inst_count = instructions.len();
block.instructions = instructions;
block.instruction_spans = vec![Span::unknown(); inst_count];
block.terminator = Some(terminator);
}
}
// Phase 190: Use modular converters from parent module
use super::joinir_function_converter::JoinIrFunctionConverter;
/// Phase 30.x: JoinIR → MIR 変換器
/// Phase 190: JoinIR → MIR 変換器(統合エントリーポイント)
///
/// Phase 32 L-2.2 Step-3: テストから呼び出し可能に `pub(crate)` 化
pub(crate) fn convert_joinir_to_mir(
join_module: &JoinModule,
) -> Result<MirModule, JoinIrVmBridgeError> {
let mut mir_module = MirModule::new("joinir_bridge".to_string());
// Convert all JoinIR functions to MIR (entry function becomes "skip" or similar)
for (func_id, join_func) in &join_module.functions {
debug_log!(
"[joinir_vm_bridge] Converting JoinFunction {} ({})",
func_id.0,
join_func.name
);
let mir_func = convert_join_function_to_mir(join_func)?;
// Use actual function name (not "main") since we'll create a wrapper
mir_module
.functions
.insert(join_func_name(*func_id), mir_func);
}
Ok(mir_module)
// Phase 190: Delegate to FunctionConverter
JoinIrFunctionConverter::convert_joinir_to_mir(join_module)
}
/// JoinFunction → MirFunction 変換
///
/// # Phase 40拡張予定: Loop Exit PHI for If-in-loop
///
/// ## Current Implementation (Phase 34)
///
/// - Header PHI: ループ開始時の変数(ループ不変変数含む)
/// - Exit PHI: ループ終了時の変数(単純パターンのみ)
///
/// ## Phase 40 Extension Required
///
/// ### Problem
///
/// 現在、if-in-loopで修正される変数のloop exit PHIが生成されない。
///
/// ```nyash,ignore
/// local out = new ArrayBox()
/// loop(i < n) {
/// if fn(arr[i]) { out.push(arr[i]) } // ← out修正
/// i = i + 1
/// }
/// // Missing: phi out_exit = (out_header, out_if_modified)
/// ```
///
/// ### Solution (Phase 40-1)
///
/// JoinIR Frontend AST loweringで検出したif-in-loop修正変数を
/// JoinModule metadataに格納し、MIR loweringで読み取る。
///
/// ### Implementation Plan
///
/// 1. JoinModule metadataに`if_in_loop_modified_vars: HashSet<String>`追加
/// 2. AST lowering時に`extract_if_in_loop_modified_vars()`結果をmetadataに格納
/// 3. MIR lowering時にmetadataから読み取り、loop exit PHI生成
///
/// ### Code Location
///
/// この関数内で以下を追加:
///
/// ```rust,ignore
/// // TODO(Phase 40-1): Generate loop exit PHI for if-in-loop modified variables
/// if let Some(modified_vars) = join_func.metadata.get("if_in_loop_modified_vars") {
/// for var_name in modified_vars.as_array().unwrap() {
/// let var_name_str = var_name.as_str().unwrap();
///
/// // Get header value (loop entry)
/// let header_value = self.get_var_value_at_header(var_name_str);
///
/// // Get exit value (loop body last modification)
/// let exit_value = self.get_var_value_at_exit(var_name_str);
///
/// // Emit PHI at loop exit block
/// self.emit_phi(
/// exit_block_id,
/// var_name_str,
/// vec![header_value, exit_value],
/// );
/// }
/// }
/// ```
///
/// ### Example (array_ext.filter)
///
/// ```nyash,ignore
/// // Input AST
/// local out = new ArrayBox()
/// local i = 0
/// loop(i < arr.len()) {
/// if fn(arr[i]) { out.push(arr[i]) } // out modified in if
/// i = i + 1
/// }
/// return out
///
/// // JoinIR (Phase 40)
/// entry():
/// out_init = new ArrayBox
/// i_init = 0
/// call loop_step(i_init, out_init, arr)
///
/// loop_step(i, out, arr):
/// exit_cond = i >= arr.len()
/// jump k_exit(out) if exit_cond // ← out needs PHI at k_exit
/// elem = arr[i]
/// should_push = fn(elem)
/// out_next = select(should_push, out.push(elem), out) // conditional modification
/// i_next = i + 1
/// call loop_step(i_next, out_next, arr)
///
/// k_exit(out_final):
/// ret out_final
///
/// // MIR (Phase 40)
/// // At loop exit block:
/// %out_exit = phi [%out_init, entry], [%out_next, loop_step] // ← Phase 40で生成
/// ```
///
/// # See Also
///
/// - AST lowering: `ast_lowerer.rs::extract_if_in_loop_modified_vars()`
/// - Design: `docs/.../phase-39-if-phi-level2/joinir_extension_design.md`
pub(crate) fn convert_join_function_to_mir(
join_func: &JoinFunction,
) -> Result<MirFunction, JoinIrVmBridgeError> {
// TODO(Phase 40-1): Generate loop exit PHI for if-in-loop modified variables
// See comment above for implementation details
// Integration point: After loop body lowering, before exit block finalization
// Phase 27-shortterm S-4.4: skip_ws パターン対応版
// - Call (tail call): MIR Call に変換
// - Jump (conditional exit): Branch + Return に変換
let entry_block = BasicBlockId(0);
// Create minimal FunctionSignature for JoinIR function
// Phase 27-shortterm: すべて MirType::Unknown として扱う(型情報は JoinIR に無いため)
let param_types = join_func
.params
.iter()
.map(|_| MirType::Unknown)
.collect::<Vec<_>>();
let signature = FunctionSignature {
name: join_func.name.clone(),
params: param_types,
return_type: MirType::Unknown,
effects: EffectMask::PURE,
};
let mut mir_func = MirFunction::new(signature, entry_block);
// Phase 30.x: Set parameter ValueIds from JoinIR function
// JoinIR's VarId is an alias for ValueId, so direct copy works
mir_func.params = join_func.params.clone();
// Phase 27-shortterm S-4.4: Multi-block conversion for Jump instructions
// Strategy:
// - Accumulate Compute instructions in current block
// - On Jump: emit Branch + create exit block with Return
// - On Call: emit Call in current block
let mut current_block_id = entry_block;
let mut current_instructions = Vec::new();
let mut next_block_id = 1u32; // for creating new blocks
for join_inst in &join_func.body {
match join_inst {
JoinInst::Compute(mir_like) => {
let mir_inst = convert_mir_like_inst(mir_like)?;
current_instructions.push(mir_inst);
}
JoinInst::MethodCall {
dst,
receiver,
method,
args,
type_hint, // Phase 65-2-A: 型ヒント追加現状は無視、Phase 65-3 で活用)
} => {
// Phase 34-6: MethodCall → MIR BoxCall 変換
// receiver.method(args...) を BoxCall(receiver, method, args) に変換
let mir_inst = MirInstruction::BoxCall {
dst: Some(*dst),
box_val: *receiver,
method: method.clone(),
method_id: None,
args: args.clone(),
effects: EffectMask::PURE,
};
current_instructions.push(mir_inst);
// Phase 65-2-A: TODO: type_hint を value_types に記録する処理を Phase 65-3 で追加
let _ = type_hint; // 現状は unused warning 回避
}
// Phase 56: ConditionalMethodCall → MIR (cond ? method : no-op)
JoinInst::ConditionalMethodCall {
cond,
dst,
receiver,
method,
args,
} => {
// Phase 56: ConditionalMethodCall を MIR の if/phi に変換
// cond が true の場合: receiver.method(args) → dst
// cond が false の場合: receiver → dst (変更なし)
//
// 4 ブロック構造: cond -> then/else -> merge
debug_log!(
"[joinir_vm_bridge] Converting ConditionalMethodCall: dst={:?}, cond={:?}, receiver={:?}, method={}",
dst, cond, receiver, method
);
// 1. cond ブロック(現在のブロック)
let cond_block = current_block_id;
// 2. then ブロック作成
let then_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 3. else ブロック作成
let else_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 4. merge ブロック作成
let merge_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 5. cond ブロックで分岐
let branch_terminator = MirInstruction::Branch {
condition: *cond,
then_bb: then_block,
else_bb: else_block,
};
finalize_block(
&mut mir_func,
cond_block,
current_instructions,
branch_terminator,
);
// 6. then ブロック: dst = receiver.method(args); jump merge
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
then_block_obj.instructions.push(MirInstruction::BoxCall {
dst: Some(*dst),
box_val: *receiver,
method: method.clone(),
method_id: None,
args: args.clone(),
effects: EffectMask::PURE,
});
then_block_obj.instruction_spans.push(Span::unknown());
then_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(then_block, then_block_obj);
// 7. else ブロック: dst = receiver (no-op, keep original); jump merge
let mut else_block_obj = crate::mir::BasicBlock::new(else_block);
else_block_obj.instructions.push(MirInstruction::Copy {
dst: *dst,
src: *receiver,
});
else_block_obj.instruction_spans.push(Span::unknown());
else_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(else_block, else_block_obj);
// 8. merge ブロック作成(空)
let merge_block_obj = crate::mir::BasicBlock::new(merge_block);
mir_func.blocks.insert(merge_block, merge_block_obj);
// 9. merge ブロックに移動
current_block_id = merge_block;
current_instructions = Vec::new();
}
// Phase 51: FieldAccess → MIR BoxCall (getter pattern)
JoinInst::FieldAccess { dst, object, field } => {
// object.field を BoxCall(object, field, []) に変換
// フィールドアクセスはメソッド呼び出しとして扱うgetter pattern
let mir_inst = MirInstruction::BoxCall {
dst: Some(*dst),
box_val: *object,
method: field.clone(),
method_id: None,
args: vec![],
effects: EffectMask::PURE,
};
current_instructions.push(mir_inst);
}
// Phase 51: NewBox → MIR NewBox
JoinInst::NewBox {
dst,
box_name,
args,
type_hint, // Phase 65-2-B: 型ヒント追加現状は無視、Phase 65-3 で活用)
} => {
let mir_inst = MirInstruction::NewBox {
dst: *dst,
box_type: box_name.clone(),
args: args.clone(),
};
current_instructions.push(mir_inst);
// Phase 65-2-B: TODO: type_hint を value_types に記録する処理を Phase 65-3 で追加
let _ = type_hint; // 現状は unused warning 回避
}
JoinInst::Call {
func,
args,
dst,
k_next,
} => {
// Phase 30.x: Support both tail calls and non-tail calls
// - dst=None, k_next=None: Tail call → call + return
// - dst=Some(id), k_next=None: Non-tail call → call + store + continue
// - k_next=Some: Not yet supported
if k_next.is_some() {
let call_target_name = join_func_name(*func);
return Err(JoinIrVmBridgeError::new(format!(
"Call with k_next is not yet supported\n\
\n\
Current function: {}\n\
Call target: {} (JoinFuncId: {:?})\n\
Arguments: {} args\n\
k_next: {:?}\n\
\n\
💡 Fix: Change `k_next: Some(...)` to `k_next: None`\n\
💡 Note: Phase 31 and Phase 34 both use k_next=None (bridge limitation)\n\
\n\
Example:\n\
Call {{\n\
func: loop_step_id,\n\
args: vec![i_next, acc_next, n],\n\
k_next: None, // ⚠️ Must be None\n\
dst: Some(result),\n\
}}",
join_func.name,
call_target_name,
func,
args.len(),
k_next,
)));
}
// Convert JoinFuncId to function name
let func_name = join_func_name(*func);
// Create temporary ValueId for function name
let func_name_id = ValueId(99990 + next_block_id);
next_block_id += 1;
// Add Const instruction for function name
current_instructions.push(MirInstruction::Const {
dst: func_name_id,
value: MirConstValue::String(func_name),
});
match dst {
Some(result_dst) => {
// Non-tail call: store result in dst and continue
current_instructions.push(MirInstruction::Call {
dst: Some(*result_dst),
func: func_name_id,
callee: None,
args: args.clone(),
effects: EffectMask::PURE,
});
// Continue to next instruction (no block termination)
}
None => {
// Tail call: call + return result
let call_result_id = ValueId(99991);
current_instructions.push(MirInstruction::Call {
dst: Some(call_result_id),
func: func_name_id,
callee: None,
args: args.clone(),
effects: EffectMask::PURE,
});
// Return the result of the tail call
let terminator = MirInstruction::Return {
value: Some(call_result_id),
};
finalize_block(
&mut mir_func,
current_block_id,
current_instructions,
terminator,
);
current_instructions = Vec::new();
}
}
}
JoinInst::Jump {
cont: _,
args,
cond,
} => {
// Phase 27-shortterm S-4.4-A: Jump with condition → Branch + Return
// Jump represents an exit continuation (k_exit) in skip_ws pattern
debug_log!(
"[joinir_vm_bridge] Converting Jump args={:?}, cond={:?}",
args,
cond
);
match cond {
Some(cond_var) => {
// Conditional jump: Branch to exit block
let exit_block_id = BasicBlockId(next_block_id);
next_block_id += 1;
let continue_block_id = BasicBlockId(next_block_id);
next_block_id += 1;
// Phase 30.x: Branch terminator (separate from instructions)
let branch_terminator = MirInstruction::Branch {
condition: *cond_var,
then_bb: exit_block_id,
else_bb: continue_block_id,
};
// Finalize current block with Branch terminator
finalize_block(
&mut mir_func,
current_block_id,
current_instructions,
branch_terminator,
);
// Create exit block with Return terminator
let exit_value = args.first().copied();
let mut exit_block = crate::mir::BasicBlock::new(exit_block_id);
exit_block.terminator = Some(MirInstruction::Return { value: exit_value });
mir_func.blocks.insert(exit_block_id, exit_block);
// Create continue block (will be populated by subsequent instructions)
let continue_block = crate::mir::BasicBlock::new(continue_block_id);
mir_func.blocks.insert(continue_block_id, continue_block);
// Continue in the next block
current_block_id = continue_block_id;
current_instructions = Vec::new();
}
None => {
// Unconditional jump: direct Return terminator
let exit_value = args.first().copied();
let return_terminator = MirInstruction::Return { value: exit_value };
// Finalize current block with Return terminator
finalize_block(
&mut mir_func,
current_block_id,
current_instructions,
return_terminator,
);
// No continuation after unconditional return
current_instructions = Vec::new();
}
}
}
// Phase 33: Select instruction conversion to MIR
JoinInst::Select {
dst,
cond,
then_val,
else_val,
type_hint, // Phase 63-6: Type hint propagated to MIR Phi
} => {
// Phase 33-2: Select を MIR の if/phi に変換
// Phase 63-6: PHI instruction with type hint from JoinIR
debug_log!(
"[joinir_vm_bridge] Converting Select: dst={:?}, cond={:?}, then={:?}, else={:?}, type_hint={:?}",
dst,
cond,
then_val,
else_val,
type_hint
);
// 1. cond ブロック(現在のブロック)
let cond_block = current_block_id;
// 2. then ブロック作成
let then_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 3. else ブロック作成
let else_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 4. merge ブロック作成
let merge_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 5. cond ブロックで分岐
let branch_terminator = MirInstruction::Branch {
condition: *cond,
then_bb: then_block,
else_bb: else_block,
};
finalize_block(
&mut mir_func,
cond_block,
current_instructions,
branch_terminator,
);
// 6. then ブロック: jump merge (no Copy, PHI will handle it)
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
then_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(then_block, then_block_obj);
// 7. else ブロック: jump merge (no Copy, PHI will handle it)
let mut else_block_obj = crate::mir::BasicBlock::new(else_block);
else_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(else_block, else_block_obj);
// 8. merge ブロック: PHI instruction with type hint
let mut merge_block_obj = crate::mir::BasicBlock::new(merge_block);
// Phase 63-6: Create PHI with type hint from JoinIR Select
merge_block_obj.instructions.push(MirInstruction::Phi {
dst: *dst,
inputs: vec![(then_block, *then_val), (else_block, *else_val)],
type_hint: type_hint.clone(), // Phase 63-6: Propagate type hint from JoinIR
});
merge_block_obj.instruction_spans.push(Span::unknown());
mir_func.blocks.insert(merge_block, merge_block_obj);
// 9. merge ブロックに移動
current_block_id = merge_block;
current_instructions = Vec::new();
}
// Phase 33-6: IfMerge instruction conversion to MIR
JoinInst::IfMerge {
cond,
merges,
k_next,
} => {
// Phase 33-6: IfMerge を MIR の if/phi に変換
// Select と同じ 4 ブロック構造だが、複数の Copy を生成
// Phase 33-6 最小実装: k_next は None のみサポート
if k_next.is_some() {
return Err(JoinIrVmBridgeError::new(
"IfMerge: k_next continuation is not yet supported (Phase 33-6 minimal)"
.to_string(),
));
}
debug_log!(
"[joinir_vm_bridge] Converting IfMerge: cond={:?}, merges.len()={}",
cond,
merges.len()
);
// 1. cond ブロック(現在のブロック)
let cond_block = current_block_id;
// 2. then ブロック作成
let then_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 3. else ブロック作成
let else_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 4. merge ブロック作成
let merge_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 5. cond ブロックで分岐
let branch_terminator = MirInstruction::Branch {
condition: *cond,
then_bb: then_block,
else_bb: else_block,
};
finalize_block(
&mut mir_func,
cond_block,
current_instructions,
branch_terminator,
);
// 6. then ブロック: 各 merge について dst = then_val; jump merge
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
for merge in merges {
then_block_obj.instructions.push(MirInstruction::Copy {
dst: merge.dst,
src: merge.then_val,
});
then_block_obj.instruction_spans.push(Span::unknown());
}
then_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(then_block, then_block_obj);
// 7. else ブロック: 各 merge について dst = else_val; jump merge
let mut else_block_obj = crate::mir::BasicBlock::new(else_block);
for merge in merges {
else_block_obj.instructions.push(MirInstruction::Copy {
dst: merge.dst,
src: merge.else_val,
});
else_block_obj.instruction_spans.push(Span::unknown());
}
else_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(else_block, else_block_obj);
// 8. merge ブロック作成(空)
let merge_block_obj = crate::mir::BasicBlock::new(merge_block);
mir_func.blocks.insert(merge_block, merge_block_obj);
// 9. merge ブロックに移動
current_block_id = merge_block;
current_instructions = Vec::new();
}
JoinInst::Ret { value } => {
// Phase 30.x: Return terminator (separate from instructions)
let return_terminator = MirInstruction::Return { value: *value };
// Finalize current block with Return terminator
finalize_block(
&mut mir_func,
current_block_id,
current_instructions,
return_terminator,
);
current_instructions = Vec::new();
}
// Phase 41-4: NestedIfMerge instruction
JoinInst::NestedIfMerge {
conds,
merges,
k_next,
} => {
// Phase 41-4.3: 多段 Branch + PHI を生成
//
// 構造:
// cond_block: branch cond[0] -> level_1_block, final_else_block
// level_1_block: branch cond[1] -> level_2_block, final_else_block
// ...
// level_n_block: branch cond[n] -> then_block, final_else_block
// then_block: Copy dst=then_val; jump merge_block
// final_else_block: Copy dst=else_val; jump merge_block
// merge_block: (continue)
// k_next は None のみサポートPhase 41-4.3 最小実装)
if k_next.is_some() {
return Err(JoinIrVmBridgeError::new(
"NestedIfMerge: k_next continuation is not yet supported".to_string(),
));
}
if conds.is_empty() {
return Err(JoinIrVmBridgeError::new(
"NestedIfMerge: conds must not be empty".to_string(),
));
}
debug_log!(
"[joinir_vm_bridge] Converting NestedIfMerge: conds.len()={}, merges.len()={}",
conds.len(),
merges.len()
);
// 1. ブロックを事前確保
// - 各条件レベルに 1 ブロック(現在のブロック + 追加分)
// - then_block
// - final_else_block
// - merge_block
let num_conds = conds.len();
// level blocks: conds[0] は current_block で処理、conds[1..] は新規ブロック
let mut level_blocks: Vec<BasicBlockId> = Vec::with_capacity(num_conds);
level_blocks.push(current_block_id); // level 0 = current block
for _ in 1..num_conds {
level_blocks.push(BasicBlockId(next_block_id));
next_block_id += 1;
}
let then_block = BasicBlockId(next_block_id);
next_block_id += 1;
let final_else_block = BasicBlockId(next_block_id);
next_block_id += 1;
let merge_block = BasicBlockId(next_block_id);
next_block_id += 1;
// 2. level 1+ ブロックを事前作成finalize_block は既存ブロックのみ更新)
for level in 1..num_conds {
let level_block = level_blocks[level];
mir_func
.blocks
.insert(level_block, crate::mir::BasicBlock::new(level_block));
}
// 3. 各レベルで分岐を生成
for (level, cond_var) in conds.iter().enumerate() {
let this_block = level_blocks[level];
// 次のレベルまたは then_block への分岐先
let next_true_block = if level + 1 < num_conds {
level_blocks[level + 1]
} else {
then_block
};
// false の場合は常に final_else_block へ
let branch_terminator = MirInstruction::Branch {
condition: *cond_var,
then_bb: next_true_block,
else_bb: final_else_block,
};
if level == 0 {
// level 0 は current_block、current_instructions を使う
finalize_block(
&mut mir_func,
this_block,
current_instructions.clone(),
branch_terminator,
);
current_instructions.clear();
} else {
// level 1+ は事前作成済みブロックを更新
finalize_block(&mut mir_func, this_block, Vec::new(), branch_terminator);
}
}
// 3. then_block: 全条件 true の場合 → then_val を Copy
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
for merge in merges {
then_block_obj.instructions.push(MirInstruction::Copy {
dst: merge.dst,
src: merge.then_val,
});
then_block_obj.instruction_spans.push(Span::unknown());
}
then_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(then_block, then_block_obj);
// 4. final_else_block: いずれかの条件 false の場合 → else_val を Copy
let mut else_block_obj = crate::mir::BasicBlock::new(final_else_block);
for merge in merges {
else_block_obj.instructions.push(MirInstruction::Copy {
dst: merge.dst,
src: merge.else_val,
});
else_block_obj.instruction_spans.push(Span::unknown());
}
else_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(final_else_block, else_block_obj);
// 5. merge_block
let merge_block_obj = crate::mir::BasicBlock::new(merge_block);
mir_func.blocks.insert(merge_block, merge_block_obj);
// 6. merge_block に移動して継続
current_block_id = merge_block;
current_instructions = Vec::new();
}
}
}
// Finalize any remaining instructions in the last block
if !current_instructions.is_empty() {
debug_log!(
"[joinir_vm_bridge] Final block {:?} has {} remaining instructions",
current_block_id,
current_instructions.len()
);
if let Some(block) = mir_func.blocks.get_mut(&current_block_id) {
// Phase 30.x: VM requires instruction_spans to match instructions length
let inst_count = current_instructions.len();
block.instructions = current_instructions;
block.instruction_spans = vec![Span::unknown(); inst_count];
}
}
// Debug: print all blocks and their instruction counts + terminators
debug_log!(
"[joinir_vm_bridge] Function '{}' has {} blocks:",
mir_func.signature.name,
mir_func.blocks.len()
);
for (block_id, block) in &mir_func.blocks {
debug_log!(
" Block {:?}: {} instructions, terminator={:?}",
block_id,
block.instructions.len(),
block.terminator
);
}
Ok(mir_func)
}
/// MirLikeInst → MirInstruction 変換
/// Phase 190: 共有ユーティリティとして pub(crate) に変更
pub(crate) fn convert_mir_like_inst(
mir_like: &MirLikeInst,
) -> Result<MirInstruction, JoinIrVmBridgeError> {

View File

@ -0,0 +1,691 @@
//! Phase 190: JoinIR Block Converter
//!
//! 責務: JoinIR のブロックを MIR ブロックに変換
//! - 命令列変換
//! - ターミネータJump/Branch/Returnの処理
//! - ブロックID マッピング管理
use crate::ast::Span;
use crate::mir::join_ir::{JoinInst, MirLikeInst};
use crate::mir::{BasicBlockId, EffectMask, MirFunction, MirInstruction, ValueId};
use super::{convert_mir_like_inst, join_func_name, JoinIrVmBridgeError};
pub struct JoinIrBlockConverter {
current_block_id: BasicBlockId,
current_instructions: Vec<MirInstruction>,
next_block_id: u32,
}
impl JoinIrBlockConverter {
pub fn new() -> Self {
Self {
current_block_id: BasicBlockId(0), // entry block
current_instructions: Vec::new(),
next_block_id: 1, // start from 1 (0 is entry)
}
}
/// JoinIR 関数本体を MIR ブロック群に変換
///
/// # Phase 27-shortterm S-4.4: Multi-block conversion
///
/// Strategy:
/// - Accumulate Compute instructions in current block
/// - On Jump: emit Branch + create exit block with Return
/// - On Call: emit Call in current block
pub fn convert_function_body(
&mut self,
mir_func: &mut MirFunction,
join_body: &[JoinInst],
) -> Result<(), JoinIrVmBridgeError> {
for join_inst in join_body {
match join_inst {
JoinInst::Compute(mir_like) => {
let mir_inst = convert_mir_like_inst(mir_like)?;
self.current_instructions.push(mir_inst);
}
JoinInst::MethodCall {
dst,
receiver,
method,
args,
type_hint,
} => {
self.handle_method_call(dst, receiver, method, args, type_hint)?;
}
JoinInst::ConditionalMethodCall {
cond,
dst,
receiver,
method,
args,
} => {
self.handle_conditional_method_call(mir_func, cond, dst, receiver, method, args)?;
}
JoinInst::FieldAccess { dst, object, field } => {
self.handle_field_access(dst, object, field)?;
}
JoinInst::NewBox {
dst,
box_name,
args,
type_hint,
} => {
self.handle_new_box(dst, box_name, args, type_hint)?;
}
JoinInst::Call {
func,
args,
dst,
k_next,
} => {
self.handle_call(mir_func, func, args, dst, k_next)?;
}
JoinInst::Jump { cont, args, cond } => {
self.handle_jump(mir_func, cont, args, cond)?;
}
JoinInst::Select {
dst,
cond,
then_val,
else_val,
type_hint,
} => {
self.handle_select(mir_func, dst, cond, then_val, else_val, type_hint)?;
}
JoinInst::IfMerge {
cond,
merges,
k_next,
} => {
self.handle_if_merge(mir_func, cond, merges, k_next)?;
}
JoinInst::Ret { value } => {
self.handle_ret(mir_func, value)?;
}
JoinInst::NestedIfMerge {
conds,
merges,
k_next,
} => {
self.handle_nested_if_merge(mir_func, conds, merges, k_next)?;
}
}
}
// Finalize any remaining instructions
self.finalize_remaining_instructions(mir_func);
Ok(())
}
// === Instruction Handlers ===
fn handle_method_call(
&mut self,
dst: &ValueId,
receiver: &ValueId,
method: &str,
args: &[ValueId],
type_hint: &Option<crate::mir::MirType>,
) -> Result<(), JoinIrVmBridgeError> {
let mir_inst = MirInstruction::BoxCall {
dst: Some(*dst),
box_val: *receiver,
method: method.to_string(),
method_id: None,
args: args.to_vec(),
effects: EffectMask::PURE,
};
self.current_instructions.push(mir_inst);
// Phase 65-2-A: TODO: type_hint を value_types に記録
let _ = type_hint;
Ok(())
}
fn handle_conditional_method_call(
&mut self,
mir_func: &mut MirFunction,
cond: &ValueId,
dst: &ValueId,
receiver: &ValueId,
method: &str,
args: &[ValueId],
) -> Result<(), JoinIrVmBridgeError> {
// Phase 56: ConditionalMethodCall を if/phi に変換
debug_log!(
"[joinir_block] Converting ConditionalMethodCall: dst={:?}, cond={:?}",
dst,
cond
);
let cond_block = self.current_block_id;
let then_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let else_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let merge_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
// cond block: branch
let branch_terminator = MirInstruction::Branch {
condition: *cond,
then_bb: then_block,
else_bb: else_block,
};
Self::finalize_block(
mir_func,
cond_block,
std::mem::take(&mut self.current_instructions),
branch_terminator,
);
// then block: method call
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
then_block_obj.instructions.push(MirInstruction::BoxCall {
dst: Some(*dst),
box_val: *receiver,
method: method.to_string(),
method_id: None,
args: args.to_vec(),
effects: EffectMask::PURE,
});
then_block_obj.instruction_spans.push(Span::unknown());
then_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(then_block, then_block_obj);
// else block: copy receiver
let mut else_block_obj = crate::mir::BasicBlock::new(else_block);
else_block_obj.instructions.push(MirInstruction::Copy {
dst: *dst,
src: *receiver,
});
else_block_obj.instruction_spans.push(Span::unknown());
else_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(else_block, else_block_obj);
// merge block
let merge_block_obj = crate::mir::BasicBlock::new(merge_block);
mir_func.blocks.insert(merge_block, merge_block_obj);
self.current_block_id = merge_block;
Ok(())
}
fn handle_field_access(
&mut self,
dst: &ValueId,
object: &ValueId,
field: &str,
) -> Result<(), JoinIrVmBridgeError> {
// Phase 51: FieldAccess → BoxCall (getter pattern)
let mir_inst = MirInstruction::BoxCall {
dst: Some(*dst),
box_val: *object,
method: field.to_string(),
method_id: None,
args: vec![],
effects: EffectMask::PURE,
};
self.current_instructions.push(mir_inst);
Ok(())
}
fn handle_new_box(
&mut self,
dst: &ValueId,
box_name: &str,
args: &[ValueId],
type_hint: &Option<crate::mir::MirType>,
) -> Result<(), JoinIrVmBridgeError> {
let mir_inst = MirInstruction::NewBox {
dst: *dst,
box_type: box_name.to_string(),
args: args.to_vec(),
};
self.current_instructions.push(mir_inst);
// Phase 65-2-B: TODO: type_hint を value_types に記録
let _ = type_hint;
Ok(())
}
fn handle_call(
&mut self,
mir_func: &mut MirFunction,
func: &crate::mir::join_ir::JoinFuncId,
args: &[ValueId],
dst: &Option<ValueId>,
k_next: &Option<crate::mir::join_ir::JoinContId>,
) -> Result<(), JoinIrVmBridgeError> {
// Phase 30.x: Call conversion
if k_next.is_some() {
return Err(JoinIrVmBridgeError::new(
"Call with k_next is not yet supported".to_string(),
));
}
let func_name = join_func_name(*func);
let func_name_id = ValueId(99990 + self.next_block_id);
self.next_block_id += 1;
self.current_instructions.push(MirInstruction::Const {
dst: func_name_id,
value: crate::mir::ConstValue::String(func_name),
});
match dst {
Some(result_dst) => {
// Non-tail call
self.current_instructions.push(MirInstruction::Call {
dst: Some(*result_dst),
func: func_name_id,
callee: None,
args: args.to_vec(),
effects: EffectMask::PURE,
});
}
None => {
// Tail call
let call_result_id = ValueId(99991);
self.current_instructions.push(MirInstruction::Call {
dst: Some(call_result_id),
func: func_name_id,
callee: None,
args: args.to_vec(),
effects: EffectMask::PURE,
});
let terminator = MirInstruction::Return {
value: Some(call_result_id),
};
Self::finalize_block(
mir_func,
self.current_block_id,
std::mem::take(&mut self.current_instructions),
terminator,
);
}
}
Ok(())
}
fn handle_jump(
&mut self,
mir_func: &mut MirFunction,
_cont: &crate::mir::join_ir::JoinContId,
args: &[ValueId],
cond: &Option<ValueId>,
) -> Result<(), JoinIrVmBridgeError> {
// Phase 27-shortterm S-4.4-A: Jump → Branch/Return
debug_log!(
"[joinir_block] Converting Jump args={:?}, cond={:?}",
args,
cond
);
match cond {
Some(cond_var) => {
// Conditional jump
let exit_block_id = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let continue_block_id = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let branch_terminator = MirInstruction::Branch {
condition: *cond_var,
then_bb: exit_block_id,
else_bb: continue_block_id,
};
Self::finalize_block(
mir_func,
self.current_block_id,
std::mem::take(&mut self.current_instructions),
branch_terminator,
);
// Exit block
let exit_value = args.first().copied();
let mut exit_block = crate::mir::BasicBlock::new(exit_block_id);
exit_block.terminator = Some(MirInstruction::Return { value: exit_value });
mir_func.blocks.insert(exit_block_id, exit_block);
// Continue block
let continue_block = crate::mir::BasicBlock::new(continue_block_id);
mir_func.blocks.insert(continue_block_id, continue_block);
self.current_block_id = continue_block_id;
}
None => {
// Unconditional jump
let exit_value = args.first().copied();
let return_terminator = MirInstruction::Return { value: exit_value };
Self::finalize_block(
mir_func,
self.current_block_id,
std::mem::take(&mut self.current_instructions),
return_terminator,
);
}
}
Ok(())
}
fn handle_select(
&mut self,
mir_func: &mut MirFunction,
dst: &ValueId,
cond: &ValueId,
then_val: &ValueId,
else_val: &ValueId,
type_hint: &Option<crate::mir::MirType>,
) -> Result<(), JoinIrVmBridgeError> {
// Phase 33-2: Select → if/phi
debug_log!(
"[joinir_block] Converting Select: dst={:?}, type_hint={:?}",
dst,
type_hint
);
let cond_block = self.current_block_id;
let then_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let else_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let merge_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
// cond block: branch
let branch_terminator = MirInstruction::Branch {
condition: *cond,
then_bb: then_block,
else_bb: else_block,
};
Self::finalize_block(
mir_func,
cond_block,
std::mem::take(&mut self.current_instructions),
branch_terminator,
);
// then/else blocks
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
then_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(then_block, then_block_obj);
let mut else_block_obj = crate::mir::BasicBlock::new(else_block);
else_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(else_block, else_block_obj);
// merge block: PHI
let mut merge_block_obj = crate::mir::BasicBlock::new(merge_block);
merge_block_obj.instructions.push(MirInstruction::Phi {
dst: *dst,
inputs: vec![(then_block, *then_val), (else_block, *else_val)],
type_hint: type_hint.clone(),
});
merge_block_obj.instruction_spans.push(Span::unknown());
mir_func.blocks.insert(merge_block, merge_block_obj);
self.current_block_id = merge_block;
Ok(())
}
fn handle_if_merge(
&mut self,
mir_func: &mut MirFunction,
cond: &ValueId,
merges: &[crate::mir::join_ir::MergePair],
k_next: &Option<crate::mir::join_ir::JoinContId>,
) -> Result<(), JoinIrVmBridgeError> {
// Phase 33-6: IfMerge → if/phi (multiple variables)
if k_next.is_some() {
return Err(JoinIrVmBridgeError::new(
"IfMerge: k_next not yet supported".to_string(),
));
}
debug_log!(
"[joinir_block] Converting IfMerge: merges.len()={}",
merges.len()
);
let cond_block = self.current_block_id;
let then_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let else_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let merge_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
// cond block: branch
let branch_terminator = MirInstruction::Branch {
condition: *cond,
then_bb: then_block,
else_bb: else_block,
};
Self::finalize_block(
mir_func,
cond_block,
std::mem::take(&mut self.current_instructions),
branch_terminator,
);
// then block: copy then_val
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
for merge in merges {
then_block_obj.instructions.push(MirInstruction::Copy {
dst: merge.dst,
src: merge.then_val,
});
then_block_obj.instruction_spans.push(Span::unknown());
}
then_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(then_block, then_block_obj);
// else block: copy else_val
let mut else_block_obj = crate::mir::BasicBlock::new(else_block);
for merge in merges {
else_block_obj.instructions.push(MirInstruction::Copy {
dst: merge.dst,
src: merge.else_val,
});
else_block_obj.instruction_spans.push(Span::unknown());
}
else_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(else_block, else_block_obj);
// merge block
let merge_block_obj = crate::mir::BasicBlock::new(merge_block);
mir_func.blocks.insert(merge_block, merge_block_obj);
self.current_block_id = merge_block;
Ok(())
}
fn handle_ret(
&mut self,
mir_func: &mut MirFunction,
value: &Option<ValueId>,
) -> Result<(), JoinIrVmBridgeError> {
let return_terminator = MirInstruction::Return { value: *value };
Self::finalize_block(
mir_func,
self.current_block_id,
std::mem::take(&mut self.current_instructions),
return_terminator,
);
Ok(())
}
fn handle_nested_if_merge(
&mut self,
mir_func: &mut MirFunction,
conds: &[ValueId],
merges: &[crate::mir::join_ir::MergePair],
k_next: &Option<crate::mir::join_ir::JoinContId>,
) -> Result<(), JoinIrVmBridgeError> {
// Phase 41-4: NestedIfMerge → multi-level Branch + PHI
if k_next.is_some() {
return Err(JoinIrVmBridgeError::new(
"NestedIfMerge: k_next not yet supported".to_string(),
));
}
if conds.is_empty() {
return Err(JoinIrVmBridgeError::new(
"NestedIfMerge: conds must not be empty".to_string(),
));
}
debug_log!(
"[joinir_block] Converting NestedIfMerge: conds.len()={}",
conds.len()
);
let num_conds = conds.len();
let mut level_blocks: Vec<BasicBlockId> = Vec::with_capacity(num_conds);
level_blocks.push(self.current_block_id);
for _ in 1..num_conds {
level_blocks.push(BasicBlockId(self.next_block_id));
self.next_block_id += 1;
}
let then_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let final_else_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
let merge_block = BasicBlockId(self.next_block_id);
self.next_block_id += 1;
// Pre-create level 1+ blocks
for level in 1..num_conds {
mir_func.blocks.insert(
level_blocks[level],
crate::mir::BasicBlock::new(level_blocks[level]),
);
}
// Create branches
for (level, cond_var) in conds.iter().enumerate() {
let this_block = level_blocks[level];
let next_true_block = if level + 1 < num_conds {
level_blocks[level + 1]
} else {
then_block
};
let branch_terminator = MirInstruction::Branch {
condition: *cond_var,
then_bb: next_true_block,
else_bb: final_else_block,
};
if level == 0 {
Self::finalize_block(
mir_func,
this_block,
std::mem::take(&mut self.current_instructions),
branch_terminator,
);
} else {
Self::finalize_block(mir_func, this_block, Vec::new(), branch_terminator);
}
}
// then block
let mut then_block_obj = crate::mir::BasicBlock::new(then_block);
for merge in merges {
then_block_obj.instructions.push(MirInstruction::Copy {
dst: merge.dst,
src: merge.then_val,
});
then_block_obj.instruction_spans.push(Span::unknown());
}
then_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(then_block, then_block_obj);
// else block
let mut else_block_obj = crate::mir::BasicBlock::new(final_else_block);
for merge in merges {
else_block_obj.instructions.push(MirInstruction::Copy {
dst: merge.dst,
src: merge.else_val,
});
else_block_obj.instruction_spans.push(Span::unknown());
}
else_block_obj.terminator = Some(MirInstruction::Jump {
target: merge_block,
});
mir_func.blocks.insert(final_else_block, else_block_obj);
// merge block
let merge_block_obj = crate::mir::BasicBlock::new(merge_block);
mir_func.blocks.insert(merge_block, merge_block_obj);
self.current_block_id = merge_block;
Ok(())
}
// === Utilities ===
fn finalize_block(
mir_func: &mut MirFunction,
block_id: BasicBlockId,
instructions: Vec<MirInstruction>,
terminator: MirInstruction,
) {
if let Some(block) = mir_func.blocks.get_mut(&block_id) {
let inst_count = instructions.len();
block.instructions = instructions;
block.instruction_spans = vec![Span::unknown(); inst_count];
block.terminator = Some(terminator);
}
}
fn finalize_remaining_instructions(&mut self, mir_func: &mut MirFunction) {
if !self.current_instructions.is_empty() {
debug_log!(
"[joinir_block] Final block {:?} has {} remaining instructions",
self.current_block_id,
self.current_instructions.len()
);
if let Some(block) = mir_func.blocks.get_mut(&self.current_block_id) {
let inst_count = self.current_instructions.len();
block.instructions = std::mem::take(&mut self.current_instructions);
block.instruction_spans = vec![Span::unknown(); inst_count];
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_block_converter_exists() {
let converter = JoinIrBlockConverter::new();
assert_eq!(converter.current_block_id, BasicBlockId(0));
assert_eq!(converter.next_block_id, 1);
}
}

View File

@ -0,0 +1,133 @@
//! Phase 190: JoinIR Function Converter
//!
//! 責務: JoinIR の関数を MIR 関数に変換
//! - パラメータ・ローカル変数の設定
//! - ブロック変換の統合
//! - 関数署名の管理
use crate::ast::Span;
use crate::mir::join_ir::{JoinFunction, JoinInst, JoinModule};
use crate::mir::{
BasicBlockId, EffectMask, FunctionSignature, MirFunction, MirInstruction, MirModule, MirType,
ValueId,
};
use super::joinir_block_converter::JoinIrBlockConverter;
use super::JoinIrVmBridgeError;
use super::{convert_mir_like_inst, join_func_name};
pub(crate) struct JoinIrFunctionConverter;
impl JoinIrFunctionConverter {
/// JoinIR モジュール全体を MIR モジュールに変換
///
/// Phase 32 L-2.2 Step-3: テストから呼び出し可能に `pub(crate)` 化
pub(crate) fn convert_joinir_to_mir(
join_module: &JoinModule,
) -> Result<MirModule, JoinIrVmBridgeError> {
let mut mir_module = MirModule::new("joinir_bridge".to_string());
// Convert all JoinIR functions to MIR
for (func_id, join_func) in &join_module.functions {
debug_log!(
"[joinir_vm_bridge] Converting JoinFunction {} ({})",
func_id.0,
join_func.name
);
let mir_func = Self::convert_function(join_func)?;
mir_module
.functions
.insert(join_func_name(*func_id), mir_func);
}
Ok(mir_module)
}
/// JoinFunction → MirFunction 変換
///
/// # Phase 40拡張予定: Loop Exit PHI for If-in-loop
///
/// ## Current Implementation (Phase 34)
///
/// - Header PHI: ループ開始時の変数(ループ不変変数含む)
/// - Exit PHI: ループ終了時の変数(単純パターンのみ)
///
/// ## Phase 40 Extension Required
///
/// ### Problem
///
/// 現在、if-in-loopで修正される変数のloop exit PHIが生成されない。
///
/// ```nyash,ignore
/// local out = new ArrayBox()
/// loop(i < n) {
/// if fn(arr[i]) { out.push(arr[i]) } // ← out修正
/// i = i + 1
/// }
/// // Missing: phi out_exit = (out_header, out_if_modified)
/// ```
///
/// ### Solution (Phase 40-1)
///
/// JoinIR Frontend AST loweringで検出したif-in-loop修正変数を
/// JoinModule metadataに格納し、MIR loweringで読み取る。
pub(crate) fn convert_function(
join_func: &JoinFunction,
) -> Result<MirFunction, JoinIrVmBridgeError> {
// TODO(Phase 40-1): Generate loop exit PHI for if-in-loop modified variables
// Integration point: After loop body lowering, before exit block finalization
let entry_block = BasicBlockId(0);
// Create FunctionSignature
let param_types = join_func
.params
.iter()
.map(|_| MirType::Unknown)
.collect::<Vec<_>>();
let signature = FunctionSignature {
name: join_func.name.clone(),
params: param_types,
return_type: MirType::Unknown,
effects: EffectMask::PURE,
};
let mut mir_func = MirFunction::new(signature, entry_block);
mir_func.params = join_func.params.clone();
// Convert function body using BlockConverter
let mut block_converter = JoinIrBlockConverter::new();
block_converter.convert_function_body(&mut mir_func, &join_func.body)?;
// Debug: print all blocks
debug_log!(
"[joinir_vm_bridge] Function '{}' has {} blocks:",
mir_func.signature.name,
mir_func.blocks.len()
);
for (block_id, block) in &mir_func.blocks {
debug_log!(
" Block {:?}: {} instructions, terminator={:?}",
block_id,
block.instructions.len(),
block.terminator
);
}
Ok(mir_func)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_function_converter_exists() {
// Basic module structure test
assert!(true);
}
}

View File

@ -1,4 +1,5 @@
use super::{convert_join_function_to_mir, join_func_name, JoinIrVmBridgeError};
// Phase 190: Use modularized converter
use super::{join_func_name, JoinIrFunctionConverter, JoinIrVmBridgeError};
use crate::mir::join_ir::frontend::JoinFuncMetaMap;
use crate::mir::join_ir::JoinModule;
use crate::mir::{MirFunction, MirModule};
@ -33,8 +34,8 @@ pub fn convert_join_module_to_mir_with_meta(
join_func.name
);
// 2. 基本のMIR変換既存ロジック
let mir_func = convert_join_function_to_mir(join_func)?;
// 2. 基本のMIR変換Phase 190: modularized converter
let mir_func = JoinIrFunctionConverter::convert_function(join_func)?;
// 3. Phase 40-1: if_modified_varsがあればloop exit PHI生成
if let Some(m) = meta.get(func_id) {

View File

@ -37,13 +37,19 @@ mod logging {
}
mod convert;
// Phase 190: Modular converters
mod joinir_function_converter;
mod joinir_block_converter;
mod meta;
mod runner;
#[cfg(test)]
mod tests;
pub(crate) use convert::{convert_join_function_to_mir, convert_joinir_to_mir};
// Phase 190: Use modularized converters
pub(crate) use convert::convert_joinir_to_mir;
pub(crate) use convert::convert_mir_like_inst; // helper for sub-modules
pub(crate) use joinir_function_converter::JoinIrFunctionConverter;
pub use meta::convert_join_module_to_mir_with_meta;
pub use runner::run_joinir_via_vm;