chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果: - ✅ LoopForm v2 テスト・ドキュメント・コメント完備 - 4ケース(A/B/C/D)完全テストカバレッジ - 最小再現ケース作成(SSAバグ調査用) - SSOT文書作成(loopform_ssot.md) - 全ソースに [LoopForm] コメントタグ追加 - ✅ Stage-1 CLI デバッグ環境構築 - stage1_cli.hako 実装 - stage1_bridge.rs ブリッジ実装 - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh) - アーキテクチャ改善提案文書 - ✅ 環境変数削減計画策定 - 25変数の完全調査・分類 - 6段階削減ロードマップ(25→5、80%削減) - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG) Phase 26-D からの累積変更: - PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等) - MIRビルダーリファクタリング - 型伝播・最適化パス改善 - その他約300ファイルの累積変更 🎯 技術的成果: - SSAバグ根本原因特定(条件分岐内loop変数変更) - Region+next_iパターン適用完了(UsingCollectorBox等) - LoopFormパターン文書化・テスト化完了 - セルフホスティング基盤強化 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com> Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
@ -1,23 +1,23 @@
|
||||
use super::ast::{ProgramV0, StmtV0, ExprV0};
|
||||
use super::ast::{ExprV0, ProgramV0, StmtV0};
|
||||
use crate::mir::Callee;
|
||||
use crate::mir::{
|
||||
BasicBlockId, ConstValue, EffectMask, FunctionSignature, MirFunction, MirInstruction, MirModule,
|
||||
MirPrinter, MirType, ValueId,
|
||||
BasicBlockId, ConstValue, EffectMask, FunctionSignature, MirFunction, MirInstruction,
|
||||
MirModule, MirPrinter, MirType, ValueId,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
|
||||
// Split out merge/new_block helpers for readability (no behavior change)
|
||||
mod merge;
|
||||
use merge::{merge_var_maps, new_block};
|
||||
// Feature splits (gradual extraction)
|
||||
pub(super) mod expr;
|
||||
pub(super) mod if_else;
|
||||
pub(super) mod loop_;
|
||||
pub(super) mod try_catch;
|
||||
pub(super) mod expr;
|
||||
pub(super) mod ternary; // placeholder (not wired)
|
||||
pub(super) mod match_expr; // placeholder (not wired)
|
||||
pub(super) mod throw_ctx; // thread-local ctx for Result-mode throw routing
|
||||
pub(super) mod ternary; // placeholder (not wired)
|
||||
pub(super) mod throw_ctx;
|
||||
pub(super) mod try_catch; // thread-local ctx for Result-mode throw routing
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct LoopContext {
|
||||
@ -77,8 +77,15 @@ pub(super) fn detect_and_push_increment_hint(body: &[StmtV0]) {
|
||||
if vname == name {
|
||||
if let ExprV0::Int { value } = *rhs {
|
||||
if let Some(v) = value.as_i64() {
|
||||
let s = match op.as_str() { "+" => v, "-" => -v, _ => 0 };
|
||||
if s != 0 { hint = Some((name.clone(), s)); break; }
|
||||
let s = match op.as_str() {
|
||||
"+" => v,
|
||||
"-" => -v,
|
||||
_ => 0,
|
||||
};
|
||||
if s != 0 {
|
||||
hint = Some((name.clone(), s));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -149,16 +156,15 @@ impl FunctionDefBuilder {
|
||||
// Phase 25.1m で確立した規則:
|
||||
// - static box 内のメソッドで、box_name が Main 以外 → インスタンスメソッド
|
||||
// - Main.main は特別扱い(エントリポイント)
|
||||
!self.def.box_name.is_empty()
|
||||
&& self.def.box_name != "Main"
|
||||
!self.def.box_name.is_empty() && self.def.box_name != "Main"
|
||||
}
|
||||
|
||||
/// パラメータ ValueId の生成(インスタンスメソッドなら %0 を me 用に予約)
|
||||
fn build_param_ids(&self) -> Vec<ValueId> {
|
||||
let offset = if self.is_instance_method() {
|
||||
0 // %0 = me, params start from %1
|
||||
0 // %0 = me, params start from %1
|
||||
} else {
|
||||
1 // params start from %1 (no implicit receiver)
|
||||
1 // params start from %1 (no implicit receiver)
|
||||
};
|
||||
|
||||
(0..self.def.params.len())
|
||||
@ -251,7 +257,6 @@ fn lower_continue_stmt(f: &mut MirFunction, cur_bb: BasicBlockId, target_bb: Bas
|
||||
// );
|
||||
}
|
||||
|
||||
|
||||
pub(super) fn lower_stmt_with_vars(
|
||||
f: &mut MirFunction,
|
||||
cur_bb: BasicBlockId,
|
||||
@ -322,16 +327,14 @@ pub(super) fn lower_stmt_with_vars(
|
||||
catches,
|
||||
finally,
|
||||
} => {
|
||||
try_catch::lower_try_stmt(
|
||||
f, cur_bb, try_body, catches, finally, vars, loop_stack, env,
|
||||
)
|
||||
try_catch::lower_try_stmt(f, cur_bb, try_body, catches, finally, vars, loop_stack, env)
|
||||
}
|
||||
StmtV0::If { cond, then, r#else } => {
|
||||
if_else::lower_if_stmt(f, cur_bb, cond, then, r#else, vars, loop_stack, env)
|
||||
}
|
||||
StmtV0::Loop { cond, body } => {
|
||||
loop_::lower_loop_stmt(f, cur_bb, cond, body, vars, loop_stack, env)
|
||||
}
|
||||
StmtV0::If { cond, then, r#else } => if_else::lower_if_stmt(
|
||||
f, cur_bb, cond, then, r#else, vars, loop_stack, env,
|
||||
),
|
||||
StmtV0::Loop { cond, body } => loop_::lower_loop_stmt(
|
||||
f, cur_bb, cond, body, vars, loop_stack, env,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -355,7 +358,10 @@ pub(super) fn lower_stmt_list_with_vars(
|
||||
Ok(cur)
|
||||
}
|
||||
|
||||
pub(super) fn lower_program(prog: ProgramV0, imports: std::collections::HashMap<String, String>) -> Result<MirModule, String> {
|
||||
pub(super) fn lower_program(
|
||||
prog: ProgramV0,
|
||||
imports: std::collections::HashMap<String, String>,
|
||||
) -> Result<MirModule, String> {
|
||||
if prog.body.is_empty() {
|
||||
return Err("empty body".into());
|
||||
}
|
||||
@ -468,7 +474,11 @@ pub(super) fn lower_program(prog: ProgramV0, imports: std::collections::HashMap<
|
||||
// Phase 21.6: Call resolution post-processing
|
||||
// Toggle: HAKO_MIR_BUILDER_CALL_RESOLVE=1
|
||||
// Resolve Call instructions to use qualified function names (e.g., "add" -> "Main.add")
|
||||
if std::env::var("HAKO_MIR_BUILDER_CALL_RESOLVE").ok().as_deref() == Some("1") {
|
||||
if std::env::var("HAKO_MIR_BUILDER_CALL_RESOLVE")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
{
|
||||
if !func_map.is_empty() {
|
||||
for (_func_idx, func) in module.functions.iter_mut() {
|
||||
for (_block_id, block) in func.blocks.iter_mut() {
|
||||
@ -476,7 +486,12 @@ pub(super) fn lower_program(prog: ProgramV0, imports: std::collections::HashMap<
|
||||
|
||||
// Find Call instructions and their associated Const values
|
||||
for inst in &block.instructions {
|
||||
if let MirInstruction::Call { func: func_reg, args, .. } = inst {
|
||||
if let MirInstruction::Call {
|
||||
func: func_reg,
|
||||
args,
|
||||
..
|
||||
} = inst
|
||||
{
|
||||
// Look for the Const instruction that defines func_reg
|
||||
for const_inst in &block.instructions {
|
||||
if let MirInstruction::Const { dst, value } = const_inst {
|
||||
@ -486,12 +501,30 @@ pub(super) fn lower_program(prog: ProgramV0, imports: std::collections::HashMap<
|
||||
if let Some(resolved) = func_map.get(name) {
|
||||
let mut new_name = resolved.clone();
|
||||
// Avoid double suffix if already contains '/N'
|
||||
if !resolved.rsplit('/').next().unwrap_or("").chars().all(|c| c.is_ascii_digit()) || !resolved.contains('/') {
|
||||
new_name = format!("{}{}", resolved.clone(), format!("/{}", args.len()));
|
||||
if !resolved
|
||||
.rsplit('/')
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_digit())
|
||||
|| !resolved.contains('/')
|
||||
{
|
||||
new_name = format!(
|
||||
"{}{}",
|
||||
resolved.clone(),
|
||||
format!("/{}", args.len())
|
||||
);
|
||||
}
|
||||
const_replacements.push((*dst, new_name));
|
||||
if std::env::var("HAKO_MIR_BUILDER_DEBUG").ok().as_deref() == Some("1") {
|
||||
eprintln!("[mirbuilder/call:resolve] {} => {}", name, resolved);
|
||||
if std::env::var("HAKO_MIR_BUILDER_DEBUG")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
{
|
||||
eprintln!(
|
||||
"[mirbuilder/call:resolve] {} => {}",
|
||||
name, resolved
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -512,15 +545,23 @@ pub(super) fn lower_program(prog: ProgramV0, imports: std::collections::HashMap<
|
||||
}
|
||||
}
|
||||
// Build a map reg -> name after replacements
|
||||
let mut reg_name: std::collections::HashMap<ValueId, String> = std::collections::HashMap::new();
|
||||
let mut reg_name: std::collections::HashMap<ValueId, String> =
|
||||
std::collections::HashMap::new();
|
||||
for inst in &block.instructions {
|
||||
if let MirInstruction::Const { dst, value } = inst {
|
||||
if let ConstValue::String(s) = value { reg_name.insert(*dst, s.clone()); }
|
||||
if let ConstValue::String(s) = value {
|
||||
reg_name.insert(*dst, s.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Upgrade legacy calls to Global callee when name is known
|
||||
for inst in &mut block.instructions {
|
||||
if let MirInstruction::Call { func: func_reg, callee, .. } = inst {
|
||||
if let MirInstruction::Call {
|
||||
func: func_reg,
|
||||
callee,
|
||||
..
|
||||
} = inst
|
||||
{
|
||||
if let Some(name) = reg_name.get(func_reg).cloned() {
|
||||
*callee = Some(Callee::Global(name));
|
||||
}
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
use super::merge::new_block;
|
||||
use super::BridgeEnv;
|
||||
use super::ternary;
|
||||
use super::match_expr;
|
||||
use crate::mir::{
|
||||
BasicBlockId, ConstValue, EffectMask, MirFunction, MirInstruction, ValueId,
|
||||
};
|
||||
use super::merge::new_block;
|
||||
use super::ternary;
|
||||
use super::BridgeEnv;
|
||||
use crate::mir::{BasicBlockId, ConstValue, EffectMask, MirFunction, MirInstruction, ValueId};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::super::ast::ExprV0;
|
||||
@ -140,7 +138,10 @@ fn lower_throw(
|
||||
} else {
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_bb) {
|
||||
bb.add_instruction(MirInstruction::Const { dst, value: ConstValue::Integer(0) });
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst,
|
||||
value: ConstValue::Integer(0),
|
||||
});
|
||||
}
|
||||
(dst, cur_bb)
|
||||
}
|
||||
@ -264,8 +265,15 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
|
||||
// );
|
||||
let cdst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(fall_bb) {
|
||||
let cval = if is_and { ConstValue::Bool(false) } else { ConstValue::Bool(true) };
|
||||
bb.add_instruction(MirInstruction::Const { dst: cdst, value: cval });
|
||||
let cval = if is_and {
|
||||
ConstValue::Bool(false)
|
||||
} else {
|
||||
ConstValue::Bool(true)
|
||||
};
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst: cdst,
|
||||
value: cval,
|
||||
});
|
||||
}
|
||||
crate::mir::ssot::cf_common::set_jump(f, fall_bb, merge_bb);
|
||||
let (rval, rhs_end) = lower_expr_with_scope(env, f, rhs_bb, rhs, vars)?;
|
||||
@ -277,7 +285,11 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
|
||||
let out = f.next_value_id();
|
||||
// フェーズM.2: PHI統一処理(no_phi分岐削除)
|
||||
let mut inputs: Vec<(BasicBlockId, ValueId)> = vec![(fall_bb, cdst)];
|
||||
if rhs_end != fall_bb { inputs.push((rhs_end, rval)); } else { inputs.push((fall_bb, rval)); }
|
||||
if rhs_end != fall_bb {
|
||||
inputs.push((rhs_end, rval));
|
||||
} else {
|
||||
inputs.push((fall_bb, rval));
|
||||
}
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, merge_bb, out, inputs);
|
||||
Ok((out, merge_bb))
|
||||
}
|
||||
@ -346,7 +358,10 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
|
||||
let (arg_ids, cur) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
||||
let fun_val = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur) {
|
||||
bb.add_instruction(MirInstruction::Const { dst: fun_val, value: ConstValue::String(name.clone()) });
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst: fun_val,
|
||||
value: ConstValue::String(name.clone()),
|
||||
});
|
||||
}
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur) {
|
||||
@ -361,8 +376,10 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
|
||||
Ok((dst, cur))
|
||||
}
|
||||
ExprV0::Method { recv, method, args } => {
|
||||
let recv_is_console_new = matches!(&**recv, ExprV0::New { class, .. } if class == "ConsoleBox");
|
||||
if recv_is_console_new && (method == "println" || method == "print" || method == "log") {
|
||||
let recv_is_console_new =
|
||||
matches!(&**recv, ExprV0::New { class, .. } if class == "ConsoleBox");
|
||||
if recv_is_console_new && (method == "println" || method == "print" || method == "log")
|
||||
{
|
||||
let (arg_ids, cur2) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur2) {
|
||||
@ -378,11 +395,16 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
|
||||
}
|
||||
// Phase 25.1b: Handle env.box_introspect.kind(value) pattern
|
||||
// Pattern: Method { recv: Method { recv: Var("env"), method: "box_introspect" }, method: "kind", args }
|
||||
if let ExprV0::Method { recv: inner_recv, method: inner_method, args: inner_args } = &**recv {
|
||||
if let ExprV0::Method {
|
||||
recv: inner_recv,
|
||||
method: inner_method,
|
||||
args: inner_args,
|
||||
} = &**recv
|
||||
{
|
||||
if matches!(&**inner_recv, ExprV0::Var { name } if name == "env")
|
||||
&& inner_method == "box_introspect"
|
||||
&& inner_args.is_empty() {
|
||||
|
||||
&& inner_args.is_empty()
|
||||
{
|
||||
// Lower args for the final method call
|
||||
let (arg_ids, cur2) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
||||
let dst = f.next_value_id();
|
||||
@ -418,7 +440,11 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
|
||||
let (arg_ids, cur) = lower_args_with_scope(env, f, cur_bb, args, vars)?;
|
||||
let dst = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur) {
|
||||
bb.add_instruction(MirInstruction::NewBox { dst, box_type: class.clone(), args: arg_ids });
|
||||
bb.add_instruction(MirInstruction::NewBox {
|
||||
dst,
|
||||
box_type: class.clone(),
|
||||
args: arg_ids,
|
||||
});
|
||||
}
|
||||
Ok((dst, cur))
|
||||
}
|
||||
@ -430,10 +456,14 @@ pub(super) fn lower_expr_with_scope<S: VarScope>(
|
||||
let (exc, cur) = lower_expr_with_scope(env, f, cur_bb, expr, vars)?;
|
||||
Ok(lower_throw(env, f, cur, exc))
|
||||
}
|
||||
ExprV0::Ternary { cond, then, r#else } =>
|
||||
ternary::lower_ternary_expr_with_scope(env, f, cur_bb, cond, then, r#else, vars),
|
||||
ExprV0::Match { scrutinee, arms, r#else } =>
|
||||
match_expr::lower_match_expr_with_scope(env, f, cur_bb, scrutinee, arms, r#else, vars),
|
||||
ExprV0::Ternary { cond, then, r#else } => {
|
||||
ternary::lower_ternary_expr_with_scope(env, f, cur_bb, cond, then, r#else, vars)
|
||||
}
|
||||
ExprV0::Match {
|
||||
scrutinee,
|
||||
arms,
|
||||
r#else,
|
||||
} => match_expr::lower_match_expr_with_scope(env, f, cur_bb, scrutinee, arms, r#else, vars),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use super::super::ast::ExprV0;
|
||||
use super::super::ast::StmtV0;
|
||||
use super::{lower_stmt_list_with_vars, merge_var_maps, new_block, BridgeEnv, LoopContext};
|
||||
use crate::mir::{BasicBlockId, MirFunction, ValueId};
|
||||
use std::collections::HashMap;
|
||||
use super::super::ast::StmtV0;
|
||||
use super::super::ast::ExprV0;
|
||||
|
||||
pub(super) fn lower_if_stmt(
|
||||
f: &mut MirFunction,
|
||||
@ -24,16 +24,22 @@ pub(super) fn lower_if_stmt(
|
||||
let tend = lower_stmt_list_with_vars(f, then_bb, then_body, &mut then_vars, loop_stack, env)?;
|
||||
let mut then_terminated = false;
|
||||
if let Some(bb) = f.get_block_mut(tend) {
|
||||
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb); }
|
||||
else { then_terminated = true; }
|
||||
if !bb.is_terminated() {
|
||||
crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb);
|
||||
} else {
|
||||
then_terminated = true;
|
||||
}
|
||||
}
|
||||
let (else_end_pred, else_vars, else_terminated) = if let Some(elses) = else_body {
|
||||
let mut ev = base_vars.clone();
|
||||
let eend = lower_stmt_list_with_vars(f, else_bb, elses, &mut ev, loop_stack, env)?;
|
||||
let mut term = false;
|
||||
if let Some(bb) = f.get_block_mut(eend) {
|
||||
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb); }
|
||||
else { term = true; }
|
||||
if !bb.is_terminated() {
|
||||
crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb);
|
||||
} else {
|
||||
term = true;
|
||||
}
|
||||
}
|
||||
(eend, ev, term)
|
||||
} else {
|
||||
|
||||
@ -20,14 +20,14 @@
|
||||
* だけを行う。
|
||||
*/
|
||||
|
||||
use super::{lower_stmt_list_with_vars, new_block, BridgeEnv, LoopContext};
|
||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||
use crate::mir::phi_core::loopform_builder::{LoopFormBuilder, LoopFormOps};
|
||||
use crate::mir::phi_core::loop_snapshot_merge::LoopSnapshotMergeBox;
|
||||
use crate::mir::phi_core::phi_input_collector::PhiInputCollector;
|
||||
use std::collections::HashMap;
|
||||
use super::super::ast::StmtV0;
|
||||
use super::super::ast::ExprV0;
|
||||
use super::super::ast::StmtV0;
|
||||
use super::{lower_stmt_list_with_vars, new_block, BridgeEnv, LoopContext};
|
||||
use crate::mir::phi_core::loop_snapshot_merge::LoopSnapshotMergeBox;
|
||||
use crate::mir::phi_core::loopform_builder::{LoopFormBuilder, LoopFormOps};
|
||||
use crate::mir::phi_core::phi_input_collector::PhiInputCollector;
|
||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// LoopForm v2 用の JSON bridge 実装。
|
||||
///
|
||||
@ -97,7 +97,9 @@ impl LoopFormOps for LoopFormJsonOps<'_> {
|
||||
fn is_parameter(&self, value_id: ValueId) -> bool {
|
||||
// Phase 26-A-4: ValueId から変数名を逆引き
|
||||
// vars マップを逆引きして変数名を取得
|
||||
let name = self.vars.iter()
|
||||
let name = self
|
||||
.vars
|
||||
.iter()
|
||||
.find(|(_, &v)| v == value_id)
|
||||
.map(|(n, _)| n.as_str());
|
||||
|
||||
@ -153,7 +155,11 @@ impl LoopFormOps for LoopFormJsonOps<'_> {
|
||||
) -> Result<(), String> {
|
||||
if let Some(bb) = self.f.get_block_mut(block) {
|
||||
for inst in &mut bb.instructions {
|
||||
if let MirInstruction::Phi { dst, inputs: phi_inputs } = inst {
|
||||
if let MirInstruction::Phi {
|
||||
dst,
|
||||
inputs: phi_inputs,
|
||||
} = inst
|
||||
{
|
||||
if *dst == phi_id {
|
||||
*phi_inputs = inputs;
|
||||
return Ok(());
|
||||
@ -231,7 +237,10 @@ pub(super) fn lower_loop_stmt(
|
||||
|
||||
// DEBUG: Log preheader snapshot
|
||||
if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() {
|
||||
eprintln!("[loop_/lower] === PREHEADER SNAPSHOT (bb={:?}) ===", preheader_bb);
|
||||
eprintln!(
|
||||
"[loop_/lower] === PREHEADER SNAPSHOT (bb={:?}) ===",
|
||||
preheader_bb
|
||||
);
|
||||
eprintln!("[loop_/lower] Function: {}", f.signature.name);
|
||||
eprintln!("[loop_/lower] base_vars.len() = {}", base_vars.len());
|
||||
let mut sorted: Vec<_> = base_vars.iter().collect();
|
||||
@ -253,8 +262,7 @@ pub(super) fn lower_loop_stmt(
|
||||
loopform.emit_header_phis(&mut ops)?;
|
||||
|
||||
// 3) ループ条件を header ブロックで評価し、body/exit へ分岐
|
||||
let (cval, cend) =
|
||||
super::expr::lower_expr_with_vars(env, ops.f, header_bb, cond, ops.vars)?;
|
||||
let (cval, cend) = super::expr::lower_expr_with_vars(env, ops.f, header_bb, cond, ops.vars)?;
|
||||
crate::mir::ssot::cf_common::set_branch(ops.f, cend, cval, body_bb, exit_bb);
|
||||
|
||||
// 4) ループ本体を lowering(break/continue スナップショットは lowering.rs 側が管理)
|
||||
@ -266,8 +274,7 @@ pub(super) fn lower_loop_stmt(
|
||||
continue_merge_bb: Some(continue_merge_bb),
|
||||
});
|
||||
super::detect_and_push_increment_hint(body);
|
||||
let bend_res =
|
||||
lower_stmt_list_with_vars(ops.f, body_bb, body, &mut body_vars, loop_stack, env);
|
||||
let bend_res = lower_stmt_list_with_vars(ops.f, body_bb, body, &mut body_vars, loop_stack, env);
|
||||
loop_stack.pop();
|
||||
let _ = super::pop_increment_hint();
|
||||
let bend = bend_res?;
|
||||
@ -293,10 +300,13 @@ pub(super) fn lower_loop_stmt(
|
||||
|
||||
// DEBUG: Log writes collection
|
||||
if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() {
|
||||
let func_name = ops.f.signature.name.clone(); // Clone before borrowing
|
||||
let func_name = ops.f.signature.name.clone(); // Clone before borrowing
|
||||
eprintln!("[loop_/lower] === WRITES COLLECTION (Step 5-1) ===");
|
||||
eprintln!("[loop_/lower] Function: {}", func_name);
|
||||
eprintln!("[loop_/lower] {} variables modified in loop body", writes.len());
|
||||
eprintln!(
|
||||
"[loop_/lower] {} variables modified in loop body",
|
||||
writes.len()
|
||||
);
|
||||
let mut sorted_writes: Vec<_> = writes.iter().collect();
|
||||
sorted_writes.sort();
|
||||
for name in &sorted_writes {
|
||||
@ -330,10 +340,7 @@ pub(super) fn lower_loop_stmt(
|
||||
let mut all_inputs: HashMap<String, Vec<(BasicBlockId, ValueId)>> = HashMap::new();
|
||||
for (bb, snap) in &continue_snaps {
|
||||
for (name, &val) in snap {
|
||||
all_inputs
|
||||
.entry(name.clone())
|
||||
.or_default()
|
||||
.push((*bb, val));
|
||||
all_inputs.entry(name.clone()).or_default().push((*bb, val));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
//! Match/expr-block lowering for JSON v0 bridge.
|
||||
|
||||
use super::super::ast::{ExprV0, MatchArmV0};
|
||||
use super::expr::{lower_expr_with_scope, VarScope};
|
||||
use super::merge::new_block;
|
||||
use super::BridgeEnv;
|
||||
use crate::mir::{BasicBlockId, CompareOp, ConstValue, MirFunction, MirInstruction, ValueId};
|
||||
use super::super::ast::{ExprV0, MatchArmV0};
|
||||
use super::expr::{lower_expr_with_scope, VarScope};
|
||||
|
||||
pub(super) fn lower_match_expr_with_scope<S: VarScope>(
|
||||
env: &BridgeEnv,
|
||||
@ -21,7 +21,9 @@ pub(super) fn lower_match_expr_with_scope<S: VarScope>(
|
||||
// Set up blocks
|
||||
let dispatch_bb = new_block(f);
|
||||
if let Some(bb) = f.get_block_mut(start_bb) {
|
||||
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, start_bb, dispatch_bb); }
|
||||
if !bb.is_terminated() {
|
||||
crate::mir::ssot::cf_common::set_jump(f, start_bb, dispatch_bb);
|
||||
}
|
||||
}
|
||||
let else_bb = new_block(f);
|
||||
let merge_bb = new_block(f);
|
||||
@ -31,7 +33,11 @@ pub(super) fn lower_match_expr_with_scope<S: VarScope>(
|
||||
let mut phi_inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||
for (i, arm) in arms.iter().enumerate() {
|
||||
let then_bb = new_block(f);
|
||||
let next_dispatch = if i + 1 < arms.len() { Some(new_block(f)) } else { None };
|
||||
let next_dispatch = if i + 1 < arms.len() {
|
||||
Some(new_block(f))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let fall_bb = next_dispatch.unwrap_or(else_bb);
|
||||
|
||||
// Pre-allocate ids to avoid double borrow
|
||||
@ -39,15 +45,27 @@ pub(super) fn lower_match_expr_with_scope<S: VarScope>(
|
||||
let cond = f.next_value_id();
|
||||
if let Some(bb) = f.get_block_mut(cur_dispatch) {
|
||||
// compare scr_val == label
|
||||
bb.add_instruction(MirInstruction::Const { dst: ldst, value: ConstValue::String(arm.label.clone()) });
|
||||
bb.add_instruction(MirInstruction::Const {
|
||||
dst: ldst,
|
||||
value: ConstValue::String(arm.label.clone()),
|
||||
});
|
||||
}
|
||||
crate::mir::ssot::cf_common::emit_compare_func(f, cur_dispatch, cond, CompareOp::Eq, scr_val, ldst);
|
||||
crate::mir::ssot::cf_common::emit_compare_func(
|
||||
f,
|
||||
cur_dispatch,
|
||||
cond,
|
||||
CompareOp::Eq,
|
||||
scr_val,
|
||||
ldst,
|
||||
);
|
||||
crate::mir::ssot::cf_common::set_branch(f, cur_dispatch, cond, then_bb, fall_bb);
|
||||
|
||||
// Then arm body
|
||||
let (tval, tend) = lower_expr_with_scope(env, f, then_bb, &arm.expr, vars)?;
|
||||
if let Some(bb) = f.get_block_mut(tend) {
|
||||
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb); }
|
||||
if !bb.is_terminated() {
|
||||
crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb);
|
||||
}
|
||||
}
|
||||
phi_inputs.push((tend, tval));
|
||||
|
||||
@ -57,7 +75,9 @@ pub(super) fn lower_match_expr_with_scope<S: VarScope>(
|
||||
// Else body
|
||||
let (eval, eend) = lower_expr_with_scope(env, f, else_bb, else_expr, vars)?;
|
||||
if let Some(bb) = f.get_block_mut(eend) {
|
||||
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb); }
|
||||
if !bb.is_terminated() {
|
||||
crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb);
|
||||
}
|
||||
}
|
||||
phi_inputs.push((eend, eval));
|
||||
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
use crate::mir::{
|
||||
BasicBlock, BasicBlockId, MirFunction, MirInstruction, ValueId,
|
||||
};
|
||||
use crate::mir::{BasicBlock, BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||
|
||||
fn next_block_id(f: &MirFunction) -> BasicBlockId {
|
||||
let mut mx = 0u32;
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
//! NOTE: This module is introduced as part of the helper split.
|
||||
//! It is not wired yet and should not alter behavior.
|
||||
|
||||
use super::super::ast::ExprV0;
|
||||
use super::merge::new_block;
|
||||
use super::BridgeEnv;
|
||||
use crate::mir::{BasicBlockId, MirFunction, ValueId};
|
||||
use super::super::ast::ExprV0;
|
||||
|
||||
use super::expr::{lower_expr_with_scope, VarScope};
|
||||
|
||||
@ -27,11 +27,15 @@ pub(super) fn lower_ternary_expr_with_scope<S: VarScope>(
|
||||
crate::mir::ssot::cf_common::set_branch(f, cur, cval, then_bb, else_bb);
|
||||
let (tval, tend) = lower_expr_with_scope(env, f, then_bb, then_e, vars)?;
|
||||
if let Some(bb) = f.get_block_mut(tend) {
|
||||
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb); }
|
||||
if !bb.is_terminated() {
|
||||
crate::mir::ssot::cf_common::set_jump(f, tend, merge_bb);
|
||||
}
|
||||
}
|
||||
let (eval, eend) = lower_expr_with_scope(env, f, else_bb, else_e, vars)?;
|
||||
if let Some(bb) = f.get_block_mut(eend) {
|
||||
if !bb.is_terminated() { crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb); }
|
||||
if !bb.is_terminated() {
|
||||
crate::mir::ssot::cf_common::set_jump(f, eend, merge_bb);
|
||||
}
|
||||
}
|
||||
let out = f.next_value_id();
|
||||
// フェーズM.2: PHI統一処理(no_phi分岐削除)
|
||||
|
||||
@ -13,7 +13,10 @@ pub(super) struct ThrowCtx {
|
||||
|
||||
impl ThrowCtx {
|
||||
fn new(catch_bb: BasicBlockId) -> Self {
|
||||
Self { catch_bb, incoming: Vec::new() }
|
||||
Self {
|
||||
catch_bb,
|
||||
incoming: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +36,11 @@ pub(super) fn is_active() -> bool {
|
||||
|
||||
/// Record a throw from `from_bb` with value `exc_val`. Sets terminator Jump to catch and
|
||||
/// appends predecessor+value to the incoming list. Returns the catch block id if active.
|
||||
pub(super) fn record_throw(f: &mut MirFunction, from_bb: BasicBlockId, exc_val: ValueId) -> Option<BasicBlockId> {
|
||||
pub(super) fn record_throw(
|
||||
f: &mut MirFunction,
|
||||
from_bb: BasicBlockId,
|
||||
exc_val: ValueId,
|
||||
) -> Option<BasicBlockId> {
|
||||
THROW_CTX.with(|slot| {
|
||||
if let Some(ctx) = slot.borrow_mut().as_mut() {
|
||||
let target = ctx.catch_bb;
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
use super::{
|
||||
lower_stmt_list_with_vars, new_block, BridgeEnv, LoopContext,
|
||||
};
|
||||
use super::super::ast::{CatchV0, StmtV0};
|
||||
use super::{lower_stmt_list_with_vars, new_block, BridgeEnv, LoopContext};
|
||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||
use std::collections::HashMap;
|
||||
use super::super::ast::{StmtV0, CatchV0};
|
||||
|
||||
pub(super) fn lower_try_stmt(
|
||||
f: &mut MirFunction,
|
||||
@ -23,9 +21,23 @@ pub(super) fn lower_try_stmt(
|
||||
if catches.len() > 1 {
|
||||
// Fallback to safe lowering (ignore catches) for multi-catch
|
||||
let mut tmp_vars = vars.clone();
|
||||
let mut next_bb = super::lower_stmt_list_with_vars(f, cur_bb, try_body, &mut tmp_vars, loop_stack, env)?;
|
||||
let mut next_bb = super::lower_stmt_list_with_vars(
|
||||
f,
|
||||
cur_bb,
|
||||
try_body,
|
||||
&mut tmp_vars,
|
||||
loop_stack,
|
||||
env,
|
||||
)?;
|
||||
if !finally.is_empty() {
|
||||
next_bb = super::lower_stmt_list_with_vars(f, next_bb, finally, &mut tmp_vars, loop_stack, env)?;
|
||||
next_bb = super::lower_stmt_list_with_vars(
|
||||
f,
|
||||
next_bb,
|
||||
finally,
|
||||
&mut tmp_vars,
|
||||
loop_stack,
|
||||
env,
|
||||
)?;
|
||||
}
|
||||
*vars = tmp_vars;
|
||||
return Ok(next_bb);
|
||||
@ -34,29 +46,47 @@ pub(super) fn lower_try_stmt(
|
||||
let base_vars = vars.clone();
|
||||
let try_bb = new_block(f);
|
||||
let catch_bb_opt = if has_catch { Some(new_block(f)) } else { None };
|
||||
let finally_bb = if !finally.is_empty() { Some(new_block(f)) } else { None };
|
||||
let finally_bb = if !finally.is_empty() {
|
||||
Some(new_block(f))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let exit_bb = new_block(f);
|
||||
|
||||
f.set_jump_terminator(cur_bb, try_bb)?;
|
||||
if let Some(succ) = f.get_block_mut(try_bb) { succ.add_predecessor(cur_bb); }
|
||||
if let Some(succ) = f.get_block_mut(try_bb) {
|
||||
succ.add_predecessor(cur_bb);
|
||||
}
|
||||
|
||||
// Install thread-local throw context so nested throw expressions jump to catch_bb
|
||||
if has_catch {
|
||||
let catch_bb = catch_bb_opt.expect("catch_bb must exist when has_catch");
|
||||
if crate::config::env::cli_verbose() {
|
||||
eprintln!("[Bridge] try_result_mode: set ThrowCtx (catch_bb={:?})", catch_bb);
|
||||
eprintln!(
|
||||
"[Bridge] try_result_mode: set ThrowCtx (catch_bb={:?})",
|
||||
catch_bb
|
||||
);
|
||||
}
|
||||
super::throw_ctx::set(catch_bb);
|
||||
} else if crate::config::env::cli_verbose() {
|
||||
eprintln!("[Bridge] try_result_mode: no catch present; ThrowCtx not set");
|
||||
}
|
||||
let mut try_vars = base_vars.clone();
|
||||
let try_end = super::lower_stmt_list_with_vars(f, try_bb, try_body, &mut try_vars, loop_stack, env)?;
|
||||
let try_end =
|
||||
super::lower_stmt_list_with_vars(f, try_bb, try_body, &mut try_vars, loop_stack, env)?;
|
||||
// Take recorded incoming exceptions
|
||||
let incoming_exc = if has_catch { super::throw_ctx::take().map(|c| c.incoming).unwrap_or_default() } else { Vec::new() };
|
||||
let incoming_exc = if has_catch {
|
||||
super::throw_ctx::take()
|
||||
.map(|c| c.incoming)
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let target = finally_bb.unwrap_or(exit_bb);
|
||||
f.set_jump_terminator(try_end, target)?;
|
||||
if let Some(succ) = f.get_block_mut(target) { succ.add_predecessor(try_end); }
|
||||
if let Some(succ) = f.get_block_mut(target) {
|
||||
succ.add_predecessor(try_end);
|
||||
}
|
||||
let try_branch_vars = try_vars.clone();
|
||||
|
||||
// Lower catch block if present and reachable
|
||||
@ -72,7 +102,9 @@ pub(super) fn lower_try_stmt(
|
||||
if let Some(_bb) = f.get_block_mut(catch_bb) {
|
||||
let mut inputs = incoming_exc.clone();
|
||||
inputs.sort_by_key(|(bbid, _)| bbid.0);
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, catch_bb, phi_dst, inputs);
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(
|
||||
f, catch_bb, phi_dst, inputs,
|
||||
);
|
||||
}
|
||||
catch_vars.insert(param.clone(), phi_dst);
|
||||
}
|
||||
@ -87,7 +119,9 @@ pub(super) fn lower_try_stmt(
|
||||
)?;
|
||||
let target = finally_bb.unwrap_or(exit_bb);
|
||||
f.set_jump_terminator(end, target)?;
|
||||
if let Some(succ) = f.get_block_mut(target) { succ.add_predecessor(end); }
|
||||
if let Some(succ) = f.get_block_mut(target) {
|
||||
succ.add_predecessor(end);
|
||||
}
|
||||
(end, catch_vars)
|
||||
} else {
|
||||
(try_end, base_vars.clone())
|
||||
@ -98,21 +132,30 @@ pub(super) fn lower_try_stmt(
|
||||
if let Some(finally_block) = finally_bb {
|
||||
// Compute merged var map from try_end + catch_end (if has_catch)
|
||||
let branch_vars: Vec<(BasicBlockId, HashMap<String, ValueId>)> = if has_catch {
|
||||
vec![(try_end, try_branch_vars.clone()), (catch_end, catch_branch_vars.clone())]
|
||||
vec![
|
||||
(try_end, try_branch_vars.clone()),
|
||||
(catch_end, catch_branch_vars.clone()),
|
||||
]
|
||||
} else {
|
||||
vec![(try_end, try_branch_vars.clone())]
|
||||
};
|
||||
let mut names: HashSet<String> = base_vars.keys().cloned().collect();
|
||||
for (_, map) in &branch_vars { names.extend(map.keys().cloned()); }
|
||||
for (_, map) in &branch_vars {
|
||||
names.extend(map.keys().cloned());
|
||||
}
|
||||
let mut merged_vars = base_vars.clone();
|
||||
let mut phi_entries: Vec<(ValueId, Vec<(BasicBlockId, ValueId)>)> = Vec::new();
|
||||
for name in names {
|
||||
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||
for (bbid, map) in &branch_vars {
|
||||
if let Some(&v) = map.get(&name) { inputs.push((*bbid, v)); }
|
||||
if let Some(&v) = map.get(&name) {
|
||||
inputs.push((*bbid, v));
|
||||
}
|
||||
}
|
||||
if inputs.is_empty() {
|
||||
if let Some(&b) = base_vars.get(&name) { merged_vars.insert(name.clone(), b); }
|
||||
if let Some(&b) = base_vars.get(&name) {
|
||||
merged_vars.insert(name.clone(), b);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let uniq: HashSet<ValueId> = inputs.iter().map(|(_, v)| *v).collect();
|
||||
@ -126,12 +169,23 @@ pub(super) fn lower_try_stmt(
|
||||
merged_vars.insert(name.clone(), dst);
|
||||
}
|
||||
if let Some(_bb) = f.get_block_mut(finally_block) {
|
||||
for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs); }
|
||||
for (dst, inputs) in phi_entries {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs);
|
||||
}
|
||||
}
|
||||
let mut finally_vars = merged_vars.clone();
|
||||
let final_end = super::lower_stmt_list_with_vars(f, finally_block, finally, &mut finally_vars, loop_stack, env)?;
|
||||
let final_end = super::lower_stmt_list_with_vars(
|
||||
f,
|
||||
finally_block,
|
||||
finally,
|
||||
&mut finally_vars,
|
||||
loop_stack,
|
||||
env,
|
||||
)?;
|
||||
f.set_jump_terminator(final_end, exit_bb)?;
|
||||
if let Some(succ) = f.get_block_mut(exit_bb) { succ.add_predecessor(final_end); }
|
||||
if let Some(succ) = f.get_block_mut(exit_bb) {
|
||||
succ.add_predecessor(final_end);
|
||||
}
|
||||
*vars = finally_vars;
|
||||
return Ok(exit_bb);
|
||||
} else {
|
||||
@ -142,38 +196,49 @@ pub(super) fn lower_try_stmt(
|
||||
vec![(try_end, try_branch_vars)]
|
||||
};
|
||||
let mut names: HashSet<String> = base_vars.keys().cloned().collect();
|
||||
for (_, map) in &branch_vars { names.extend(map.keys().cloned()); }
|
||||
for (_, map) in &branch_vars {
|
||||
names.extend(map.keys().cloned());
|
||||
}
|
||||
let mut merged_vars = base_vars.clone();
|
||||
let mut phi_entries: Vec<(ValueId, Vec<(BasicBlockId, ValueId)>)> = Vec::new();
|
||||
for name in names {
|
||||
let mut inputs: Vec<(BasicBlockId, ValueId)> = Vec::new();
|
||||
for (bbid, map) in &branch_vars { if let Some(&v) = map.get(&name) { inputs.push((*bbid, v)); } }
|
||||
if inputs.is_empty() { if let Some(&b) = base_vars.get(&name) { merged_vars.insert(name.clone(), b); } continue; }
|
||||
for (bbid, map) in &branch_vars {
|
||||
if let Some(&v) = map.get(&name) {
|
||||
inputs.push((*bbid, v));
|
||||
}
|
||||
}
|
||||
if inputs.is_empty() {
|
||||
if let Some(&b) = base_vars.get(&name) {
|
||||
merged_vars.insert(name.clone(), b);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let uniq: HashSet<ValueId> = inputs.iter().map(|(_, v)| *v).collect();
|
||||
if uniq.len() == 1 { merged_vars.insert(name.clone(), inputs[0].1); continue; }
|
||||
if uniq.len() == 1 {
|
||||
merged_vars.insert(name.clone(), inputs[0].1);
|
||||
continue;
|
||||
}
|
||||
let dst = f.next_value_id();
|
||||
inputs.sort_by_key(|(bbid, _)| bbid.0);
|
||||
phi_entries.push((dst, inputs));
|
||||
merged_vars.insert(name.clone(), dst);
|
||||
}
|
||||
if let Some(_bb) = f.get_block_mut(exit_bb) {
|
||||
for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs); }
|
||||
for (dst, inputs) in phi_entries {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs);
|
||||
}
|
||||
}
|
||||
*vars = merged_vars;
|
||||
return Ok(exit_bb);
|
||||
}
|
||||
} else if !try_enabled || catches.is_empty() || catches.len() > 1 {
|
||||
let mut tmp_vars = vars.clone();
|
||||
let mut next_bb = lower_stmt_list_with_vars(f, cur_bb, try_body, &mut tmp_vars, loop_stack, env)?;
|
||||
let mut next_bb =
|
||||
lower_stmt_list_with_vars(f, cur_bb, try_body, &mut tmp_vars, loop_stack, env)?;
|
||||
if !finally.is_empty() {
|
||||
next_bb = lower_stmt_list_with_vars(
|
||||
f,
|
||||
next_bb,
|
||||
finally,
|
||||
&mut tmp_vars,
|
||||
loop_stack,
|
||||
env,
|
||||
)?;
|
||||
next_bb =
|
||||
lower_stmt_list_with_vars(f, next_bb, finally, &mut tmp_vars, loop_stack, env)?;
|
||||
}
|
||||
*vars = tmp_vars;
|
||||
return Ok(next_bb);
|
||||
@ -260,7 +325,9 @@ pub(super) fn lower_try_stmt(
|
||||
}
|
||||
// フェーズM.2: PHI統一処理(no_phi分岐削除)
|
||||
if let Some(_bb) = f.get_block_mut(finally_block) {
|
||||
for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs); }
|
||||
for (dst, inputs) in phi_entries {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, finally_block, dst, inputs);
|
||||
}
|
||||
}
|
||||
let mut finally_vars = merged_vars.clone();
|
||||
let final_end = lower_stmt_list_with_vars(
|
||||
@ -309,7 +376,9 @@ pub(super) fn lower_try_stmt(
|
||||
}
|
||||
// フェーズM.2: PHI統一処理(no_phi分岐削除)
|
||||
if let Some(_bb) = f.get_block_mut(exit_bb) {
|
||||
for (dst, inputs) in phi_entries { crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs); }
|
||||
for (dst, inputs) in phi_entries {
|
||||
crate::mir::ssot::cf_common::insert_phi_at_head(f, exit_bb, dst, inputs);
|
||||
}
|
||||
}
|
||||
*vars = merged_vars;
|
||||
Ok(exit_bb)
|
||||
|
||||
@ -10,16 +10,26 @@ pub fn parse_json_v0_to_module(json: &str) -> Result<crate::mir::MirModule, Stri
|
||||
parse_json_v0_to_module_with_imports(json, HashMap::new())
|
||||
}
|
||||
|
||||
pub fn parse_json_v0_to_module_with_imports(json: &str, imports: HashMap<String, String>) -> Result<crate::mir::MirModule, String> {
|
||||
pub fn parse_json_v0_to_module_with_imports(
|
||||
json: &str,
|
||||
imports: HashMap<String, String>,
|
||||
) -> Result<crate::mir::MirModule, String> {
|
||||
let prog: ProgramV0 =
|
||||
serde_json::from_str(json).map_err(|e| format!("invalid JSON v0: {}", e))?;
|
||||
if crate::config::env::cli_verbose() {
|
||||
let first = prog
|
||||
.body
|
||||
.get(1)
|
||||
.map(|s| match s { StmtV0::Try { .. } => "Try", _ => "Other" })
|
||||
.map(|s| match s {
|
||||
StmtV0::Try { .. } => "Try",
|
||||
_ => "Other",
|
||||
})
|
||||
.unwrap_or("<none>");
|
||||
eprintln!("[Bridge] JSON v0: body_len={} first_type={}", prog.body.len(), first);
|
||||
eprintln!(
|
||||
"[Bridge] JSON v0: body_len={} first_type={}",
|
||||
prog.body.len(),
|
||||
first
|
||||
);
|
||||
}
|
||||
if prog.version != 0 || prog.kind != "Program" {
|
||||
return Err("unsupported IR: expected {version:0, kind:\"Program\"}".into());
|
||||
|
||||
Reference in New Issue
Block a user