feat(joinir): Phase 63-4 infer_type_from_phi degradation design
Phase 63-4: infer_type_from_phi を『JoinIR 型ヒント優先+従来ロジックフォールバック』に縮退する仕様を設計(実装は Phase 63-5+)
## Changes
### Documentation Updates
- **README.md**: Added complete Phase 63-4 design (63-4.1 through 63-4.5)
- 63-4.1: Current state analysis (definition location, callsites, role, JoinIR preparation)
- 63-4.2: Degradation spec (type_hint priority + fallback pattern)
- 63-4.3: Representative cases and A/B testing strategy (P1/P2/P3)
- 63-4.4: Deletion conditions (5 conditions, current: 2/5 = 40%)
- 63-4.5: Phase 63-5 handoff (infer_type_from_phi_with_hint() implementation tasks)
- **PHI_BOX_INVENTORY.md**: Updated if_phi.rs entry with Phase 63-4 deletion plan
- Added: "Phase 63-4完了: infer_type_from_phi の JoinIR type_hint 優先への縮退案を設計(実装は Phase 63-5+)"
- **CURRENT_TASK.md**: Added Phase 63-4 section with summary of design work
## Design Highlights
### Degradation Pattern
```rust
pub fn infer_type_from_phi_with_hint(
function: &MirFunction,
ret_val: ValueId,
types: &BTreeMap<ValueId, MirType>,
type_hint: Option<MirType>,
) -> Option<MirType> {
if let Some(hint) = type_hint {
return Some(hint); // Route B: JoinIR priority (SSOT)
}
infer_type_from_phi(function, ret_val, types) // Route A: Fallback
}
```
### Representative Cases
- **P1**: IfSelectTest.simple/local (Phase 63-5 target)
- **P2**: read_quoted_from (Phase 63-6+ target)
- **P3**: MethodCall/Box constructors (Phase 64+ expansion)
### Deletion Conditions (2/5 achieved)
1. ✅ JoinIR has type_hint field (Phase 63-3)
2. ✅ Type hints populated for representative cases (Phase 63-2)
3. ⏳ Degraded to type_hint priority (Phase 63-5)
4. ⏳ P1 cases determined by type_hint only (Phase 63-5)
5. ⏳ All functions use type hints (Phase 64+)
## Files Changed
- docs/private/roadmap2/phases/phase-63-joinir-type-info/README.md
- docs/private/roadmap2/phases/phase-30-final-joinir-world/PHI_BOX_INVENTORY.md
- CURRENT_TASK.md
## Next Steps
Phase 63-5: Implement degradation for P1 cases (IfSelectTest.simple/local)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -183,8 +183,35 @@
|
|||||||
- PhiBuilderBox ベースの PhiSpec 観察用関数(`extract_phi_spec_from_builder`, `compare_and_log_phi_specs` など)を削除し、PHI 仕様計算を JoinIR 起点の `compute_phi_spec_from_joinir` に一本化。
|
- PhiBuilderBox ベースの PhiSpec 観察用関数(`extract_phi_spec_from_builder`, `compare_and_log_phi_specs` など)を削除し、PHI 仕様計算を JoinIR 起点の `compute_phi_spec_from_joinir` に一本化。
|
||||||
- 合計約 97 行削減(予想 76 行を超過)。If 側 PHI の「観察・比較」は JoinIR 情報から復元する経路のみとなり、if_phi/PhiBuilderBox は本番ロジックに専念する構造に整理された。
|
- 合計約 97 行削減(予想 76 行を超過)。If 側 PHI の「観察・比較」は JoinIR 情報から復元する経路のみとなり、if_phi/PhiBuilderBox は本番ロジックに専念する構造に整理された。
|
||||||
|
|
||||||
|
### 1-00h. Phase 62 — PHI Core Cleanup(phi_core 小箱クリーンアップ)
|
||||||
|
|
||||||
|
- 目的: PHI 箱のうち、既に機能が JoinIR/loopform/phi_merge 側に移っていて「殻だけ残っていた」小箱を片付け、phi_core 直下の実コードをさらに減らす。
|
||||||
|
- 実績:
|
||||||
|
- `phi_core/phi_input_collector.rs` を削除。Phase 59/59b で loopform_builder.rs / loop_builder.rs へのインライン化が完了しており、外部依存 0 であることを PHI_BOX_INVENTORY ベースで確認済み。
|
||||||
|
- `phi_core/conservative.rs` を 57 行すべてコメントのみの「歴史メモ」ファイルに縮退(実コードは Phase 58 で `phi_merge.rs::merge_all_vars` 側にインライン済み)。将来的に docs/ への移設候補として扱う。
|
||||||
|
- PHI_BOX_INVENTORY.md / phi-reduction-series/INDEX.md / CURRENT_TASK.md を更新し、「PhiInputCollector 削除済み」「ConservativeMerge 本体は inline 済みで conservative.rs は docs 専用」という現状を明示。
|
||||||
|
|
||||||
- JoinIR/phi_core 関連テストは全て PASS。既知の `local` キーワード問題を除き、新たな退行はなし。
|
- JoinIR/phi_core 関連テストは全て PASS。既知の `local` キーワード問題を除き、新たな退行はなし。
|
||||||
|
|
||||||
|
### 1-00i. Phase 63-3 — JoinIR 型ヒントの最小配線
|
||||||
|
|
||||||
|
- 目的: infer_type_from_phi を削る前に、「JoinIR 側で MirType をどこに持てばよいか」を決め、そのための schema 変更と最小限のコード更新を行う。
|
||||||
|
- 実績:
|
||||||
|
- `JoinInst::Select` と `MergePair` に `type_hint: Option<MirType>` を追加し、If PHI に関わる値まわりに型ヒントをぶら下げる足場を用意した。
|
||||||
|
- Select / MergePair を生成する全サイト(if_select.rs / if_merge.rs / nested_if.rs / read_quoted.rs など 13 ファイル)を更新し、新フィールドを一旦 `type_hint: None` で埋めてビルドが通る状態に統一。
|
||||||
|
- JoinIR 関連テスト(IfSelect/IfMerge/Frontend 系)はすべて PASS。挙動は従来どおりだが、今後 AST/Frontend/Bridge から型ヒントを流し込む準備が整った。
|
||||||
|
|
||||||
|
### 1-00j. Phase 63-4 — infer_type_from_phi 縮退設計(設計のみ)
|
||||||
|
|
||||||
|
- 目的: infer_type_from_phi を『JoinIR 型ヒント優先+従来ロジックフォールバック』に縮退する仕様を docs に固定(実装は Phase 63-5+)。
|
||||||
|
- 実績:
|
||||||
|
- 63-4.1: infer_type_from_phi の現状整理(定義場所 / 呼び出し元 / 役割 / JoinIR 準備状況)を文書化。
|
||||||
|
- 63-4.2: 縮退後の仕様設計(type_hint がある場合は優先、ない場合は従来ロジックへフォールバック)。
|
||||||
|
- 63-4.3: 代表ケースと A/B テスト方針(P1: IfSelectTest.simple/local, P2: read_quoted_from, P3: MethodCall/Box コンストラクタ)を整理。
|
||||||
|
- 63-4.4: 削除条件の明確化(5条件、現時点達成率 2/5 = 40%)。
|
||||||
|
- 63-4.5: Phase 63-5 への引き継ぎ(infer_type_from_phi_with_hint() 実装タスク定義)。
|
||||||
|
- docs: `docs/private/roadmap2/phases/phase-63-joinir-type-info/README.md`, `PHI_BOX_INVENTORY.md` 更新済み
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. 中期 TODO(ざっくり)
|
## 2. 中期 TODO(ざっくり)
|
||||||
|
|||||||
@ -42,6 +42,7 @@ pub fn lower(
|
|||||||
cond: cond_id,
|
cond: cond_id,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.register_param(var_name.to_string(), result_id);
|
ctx.register_param(var_name.to_string(), result_id);
|
||||||
|
|||||||
@ -40,6 +40,7 @@ pub fn lower(
|
|||||||
cond: cond_id,
|
cond: cond_id,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.register_param(var_name.to_string(), result_id);
|
ctx.register_param(var_name.to_string(), result_id);
|
||||||
|
|||||||
@ -128,6 +128,7 @@ impl AstToJoinIrLowerer {
|
|||||||
cond: cond_var,
|
cond: cond_var,
|
||||||
then_val: then_var,
|
then_val: then_var,
|
||||||
else_val: else_var,
|
else_val: else_var,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ret result
|
// Ret result
|
||||||
|
|||||||
@ -212,6 +212,7 @@ fn create_loop_step_function_continue(
|
|||||||
cond: continue_cond_var,
|
cond: continue_cond_var,
|
||||||
then_val: step_acc, // Continue: 更新しない
|
then_val: step_acc, // Continue: 更新しない
|
||||||
else_val: acc_increment, // 通常: 更新
|
else_val: acc_increment, // 通常: 更新
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
// 6. 末尾再帰
|
// 6. 末尾再帰
|
||||||
|
|||||||
@ -843,6 +843,7 @@ impl AstToJoinIrLowerer {
|
|||||||
cond: continue_cond_var,
|
cond: continue_cond_var,
|
||||||
then_val: step_acc, // Continue: 更新しない
|
then_val: step_acc, // Continue: 更新しない
|
||||||
else_val: acc_increment, // 通常: 更新
|
else_val: acc_increment, // 通常: 更新
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
// 6. 末尾再帰
|
// 6. 末尾再帰
|
||||||
|
|||||||
@ -145,6 +145,7 @@ impl AstToJoinIrLowerer {
|
|||||||
dst,
|
dst,
|
||||||
then_val: then_var,
|
then_val: then_var,
|
||||||
else_val: else_var,
|
else_val: else_var,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -403,11 +403,13 @@ impl AstToJoinIrLowerer {
|
|||||||
dst: i_after_esc,
|
dst: i_after_esc,
|
||||||
then_val: i_esc,
|
then_val: i_esc,
|
||||||
else_val: step_i,
|
else_val: step_i,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
MergePair {
|
MergePair {
|
||||||
dst: ch_merged,
|
dst: ch_merged,
|
||||||
then_val: ch_esc,
|
then_val: ch_esc,
|
||||||
else_val: step_ch,
|
else_val: step_ch,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
k_next: None,
|
k_next: None,
|
||||||
|
|||||||
@ -142,12 +142,17 @@ fn write_inst<W: Write>(inst: &JoinInst, out: &mut W) -> std::io::Result<()> {
|
|||||||
cond,
|
cond,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
type_hint,
|
||||||
} => {
|
} => {
|
||||||
write!(out, "{{\"type\":\"select\"")?;
|
write!(out, "{{\"type\":\"select\"")?;
|
||||||
write!(out, ",\"dst\":{}", dst.0)?;
|
write!(out, ",\"dst\":{}", dst.0)?;
|
||||||
write!(out, ",\"cond\":{}", cond.0)?;
|
write!(out, ",\"cond\":{}", cond.0)?;
|
||||||
write!(out, ",\"then_val\":{}", then_val.0)?;
|
write!(out, ",\"then_val\":{}", then_val.0)?;
|
||||||
write!(out, ",\"else_val\":{}", else_val.0)?;
|
write!(out, ",\"else_val\":{}", else_val.0)?;
|
||||||
|
// Phase 63-3: type_hint を JSON 出力(存在する場合のみ)
|
||||||
|
if let Some(ref th) = type_hint {
|
||||||
|
write!(out, ",\"type_hint\":\"{}\"", format!("{:?}", th))?;
|
||||||
|
}
|
||||||
write!(out, "}}")?;
|
write!(out, "}}")?;
|
||||||
}
|
}
|
||||||
// Phase 33-6: IfMerge instruction JSON serialization
|
// Phase 33-6: IfMerge instruction JSON serialization
|
||||||
@ -577,11 +582,13 @@ mod tests {
|
|||||||
dst: ValueId(10),
|
dst: ValueId(10),
|
||||||
then_val: ValueId(20),
|
then_val: ValueId(20),
|
||||||
else_val: ValueId(30),
|
else_val: ValueId(30),
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
MergePair {
|
MergePair {
|
||||||
dst: ValueId(11),
|
dst: ValueId(11),
|
||||||
then_val: ValueId(21),
|
then_val: ValueId(21),
|
||||||
else_val: ValueId(31),
|
else_val: ValueId(31),
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
k_next: None,
|
k_next: None,
|
||||||
|
|||||||
@ -202,6 +202,7 @@ impl IfMergeLowerer {
|
|||||||
dst,
|
dst,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
type_hint: None, // Phase 63-3: 現時点では型ヒントなし
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
use crate::mir::join_ir::JoinInst;
|
use crate::mir::join_ir::JoinInst;
|
||||||
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
use crate::mir::{BasicBlockId, MirFunction, MirInstruction, ValueId};
|
||||||
|
// Phase 63-2: Type hint inference from MIR
|
||||||
|
use crate::mir::{ConstValue, MirType};
|
||||||
|
|
||||||
// Phase 61-1: If-in-loop context support
|
// Phase 61-1: If-in-loop context support
|
||||||
use super::if_phi_context::IfPhiContext;
|
use super::if_phi_context::IfPhiContext;
|
||||||
@ -118,11 +120,16 @@ impl IfSelectLowerer {
|
|||||||
// Select 命令を生成
|
// Select 命令を生成
|
||||||
let dst = pattern.dst.unwrap_or(pattern.then_val);
|
let dst = pattern.dst.unwrap_or(pattern.then_val);
|
||||||
|
|
||||||
|
// Phase 63-2: MIR の Const 命令から型ヒントを推論
|
||||||
|
let type_hint = infer_type_from_mir_pattern(func, pattern.then_val)
|
||||||
|
.or_else(|| infer_type_from_mir_pattern(func, pattern.else_val));
|
||||||
|
|
||||||
Some(JoinInst::Select {
|
Some(JoinInst::Select {
|
||||||
dst,
|
dst,
|
||||||
cond: pattern.cond,
|
cond: pattern.cond,
|
||||||
then_val: pattern.then_val,
|
then_val: pattern.then_val,
|
||||||
else_val: pattern.else_val,
|
else_val: pattern.else_val,
|
||||||
|
type_hint, // Phase 63-2: Const 命令から推論した型(Integer/Bool/String など)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,3 +371,29 @@ impl IfSelectLowerer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Phase 63-2: MIR から ValueId の型を推論
|
||||||
|
///
|
||||||
|
/// Const 命令を探して、ValueId に対応する MirType を返す。
|
||||||
|
/// Select の then_val / else_val から型ヒントを埋めるために使用。
|
||||||
|
fn infer_type_from_mir_pattern(func: &MirFunction, val_id: ValueId) -> Option<MirType> {
|
||||||
|
// 全ブロックの全命令を走査して Const 命令を探す
|
||||||
|
for block in func.blocks.values() {
|
||||||
|
for inst in &block.instructions {
|
||||||
|
if let MirInstruction::Const { dst, value } = inst {
|
||||||
|
if *dst == val_id {
|
||||||
|
return Some(match value {
|
||||||
|
ConstValue::Integer(_) => MirType::Integer,
|
||||||
|
ConstValue::Bool(_) => MirType::Bool,
|
||||||
|
ConstValue::String(_) => MirType::String,
|
||||||
|
ConstValue::Void => MirType::Void,
|
||||||
|
ConstValue::Null => MirType::Unknown, // Null は Unknown として扱う
|
||||||
|
// Float は現状未サポート
|
||||||
|
_ => return None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|||||||
@ -23,6 +23,8 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::mir::ValueId;
|
use crate::mir::ValueId;
|
||||||
|
// Phase 63-3: 型ヒント用
|
||||||
|
use crate::mir::MirType;
|
||||||
|
|
||||||
// Phase 27.9: Lowering submodule
|
// Phase 27.9: Lowering submodule
|
||||||
pub mod lowering;
|
pub mod lowering;
|
||||||
@ -206,6 +208,8 @@ pub struct MergePair {
|
|||||||
pub then_val: VarId,
|
pub then_val: VarId,
|
||||||
/// else 分岐での値
|
/// else 分岐での値
|
||||||
pub else_val: VarId,
|
pub else_val: VarId,
|
||||||
|
/// Phase 63-3: 結果型ヒント(MIR PHI 生成時の型推論を回避)
|
||||||
|
pub type_hint: Option<MirType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// JoinIR 命令セット(最小版)
|
/// JoinIR 命令セット(最小版)
|
||||||
@ -296,11 +300,15 @@ pub enum JoinInst {
|
|||||||
|
|
||||||
/// Phase 33: If/Else の単純な値選択(単一値)
|
/// Phase 33: If/Else の単純な値選択(単一値)
|
||||||
/// cond が true なら then_val、false なら else_val を dst に代入
|
/// cond が true なら then_val、false なら else_val を dst に代入
|
||||||
|
///
|
||||||
|
/// Phase 63-3: type_hint で結果型を伝播(infer_type_from_phi 削減用)
|
||||||
Select {
|
Select {
|
||||||
dst: VarId,
|
dst: VarId,
|
||||||
cond: VarId,
|
cond: VarId,
|
||||||
then_val: VarId,
|
then_val: VarId,
|
||||||
else_val: VarId,
|
else_val: VarId,
|
||||||
|
/// Phase 63-3: 結果型ヒント(MIR PHI 生成時の型推論を回避)
|
||||||
|
type_hint: Option<MirType>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Phase 33-6: If/Else の複数変数 merge
|
/// Phase 33-6: If/Else の複数変数 merge
|
||||||
|
|||||||
@ -245,6 +245,7 @@ pub fn verify_select_minimal(
|
|||||||
cond,
|
cond,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
type_hint: _, // Phase 63-3: 検証では未使用
|
||||||
} = select_inst.unwrap()
|
} = select_inst.unwrap()
|
||||||
else {
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
|||||||
@ -133,6 +133,7 @@ fn execute_function(
|
|||||||
cond,
|
cond,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
type_hint: _, // Phase 63-3: 実行時は未使用
|
||||||
} => {
|
} => {
|
||||||
// 1. Evaluate cond (Bool or Int)
|
// 1. Evaluate cond (Bool or Int)
|
||||||
let cond_value = read_var(&locals, *cond)?;
|
let cond_value = read_var(&locals, *cond)?;
|
||||||
@ -430,6 +431,7 @@ mod tests {
|
|||||||
cond: v_cond,
|
cond: v_cond,
|
||||||
then_val: v_then,
|
then_val: v_then,
|
||||||
else_val: v_else,
|
else_val: v_else,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
// return v4
|
// return v4
|
||||||
@ -481,6 +483,7 @@ mod tests {
|
|||||||
cond: v_cond,
|
cond: v_cond,
|
||||||
then_val: v_then,
|
then_val: v_then,
|
||||||
else_val: v_else,
|
else_val: v_else,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
// return v4
|
// return v4
|
||||||
@ -531,6 +534,7 @@ mod tests {
|
|||||||
cond: v_cond,
|
cond: v_cond,
|
||||||
then_val: v_then,
|
then_val: v_then,
|
||||||
else_val: v_else,
|
else_val: v_else,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
// return v4
|
// return v4
|
||||||
@ -600,11 +604,13 @@ mod tests {
|
|||||||
dst: v_result_x,
|
dst: v_result_x,
|
||||||
then_val: v_then_x,
|
then_val: v_then_x,
|
||||||
else_val: v_else_x,
|
else_val: v_else_x,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
crate::mir::join_ir::MergePair {
|
crate::mir::join_ir::MergePair {
|
||||||
dst: v_result_y,
|
dst: v_result_y,
|
||||||
then_val: v_then_y,
|
then_val: v_then_y,
|
||||||
else_val: v_else_y,
|
else_val: v_else_y,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
k_next: None,
|
k_next: None,
|
||||||
@ -682,11 +688,13 @@ mod tests {
|
|||||||
dst: v_result_x,
|
dst: v_result_x,
|
||||||
then_val: v_then_x,
|
then_val: v_then_x,
|
||||||
else_val: v_else_x,
|
else_val: v_else_x,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
crate::mir::join_ir::MergePair {
|
crate::mir::join_ir::MergePair {
|
||||||
dst: v_result_y,
|
dst: v_result_y,
|
||||||
then_val: v_then_y,
|
then_val: v_then_y,
|
||||||
else_val: v_else_y,
|
else_val: v_else_y,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
k_next: None,
|
k_next: None,
|
||||||
@ -771,16 +779,19 @@ mod tests {
|
|||||||
dst: v_result_x,
|
dst: v_result_x,
|
||||||
then_val: v_then_x,
|
then_val: v_then_x,
|
||||||
else_val: v_else_x,
|
else_val: v_else_x,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
crate::mir::join_ir::MergePair {
|
crate::mir::join_ir::MergePair {
|
||||||
dst: v_result_y,
|
dst: v_result_y,
|
||||||
then_val: v_then_y,
|
then_val: v_then_y,
|
||||||
else_val: v_else_y,
|
else_val: v_else_y,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
crate::mir::join_ir::MergePair {
|
crate::mir::join_ir::MergePair {
|
||||||
dst: v_result_z,
|
dst: v_result_z,
|
||||||
then_val: v_then_z,
|
then_val: v_then_z,
|
||||||
else_val: v_else_z,
|
else_val: v_else_z,
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
k_next: None,
|
k_next: None,
|
||||||
|
|||||||
@ -491,6 +491,7 @@ Call {{\n\
|
|||||||
cond,
|
cond,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
type_hint: _, // Phase 63-3: MIR変換では現時点で未使用
|
||||||
} => {
|
} => {
|
||||||
// Phase 33-2: Select を MIR の if/phi に変換
|
// Phase 33-2: Select を MIR の if/phi に変換
|
||||||
// 最小実装: cond/then/else/merge の 4 ブロック構造
|
// 最小実装: cond/then/else/merge の 4 ブロック構造
|
||||||
|
|||||||
@ -145,6 +145,7 @@ mod tests {
|
|||||||
cond,
|
cond,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
..
|
||||||
}) = result
|
}) = result
|
||||||
{
|
{
|
||||||
eprintln!("✅ Simple pattern successfully lowered to Select");
|
eprintln!("✅ Simple pattern successfully lowered to Select");
|
||||||
@ -171,6 +172,7 @@ mod tests {
|
|||||||
cond,
|
cond,
|
||||||
then_val,
|
then_val,
|
||||||
else_val,
|
else_val,
|
||||||
|
..
|
||||||
}) = result
|
}) = result
|
||||||
{
|
{
|
||||||
eprintln!("✅ Local pattern successfully lowered to Select");
|
eprintln!("✅ Local pattern successfully lowered to Select");
|
||||||
@ -246,6 +248,7 @@ mod tests {
|
|||||||
cond: ValueId(0),
|
cond: ValueId(0),
|
||||||
then_val: ValueId(1),
|
then_val: ValueId(1),
|
||||||
else_val: ValueId(2),
|
else_val: ValueId(2),
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return result
|
// Return result
|
||||||
@ -270,6 +273,7 @@ mod tests {
|
|||||||
cond: ValueId(0),
|
cond: ValueId(0),
|
||||||
then_val: ValueId(10),
|
then_val: ValueId(10),
|
||||||
else_val: ValueId(20),
|
else_val: ValueId(20),
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
// Second Select (violates single PHI invariant)
|
// Second Select (violates single PHI invariant)
|
||||||
@ -278,6 +282,7 @@ mod tests {
|
|||||||
cond: ValueId(0),
|
cond: ValueId(0),
|
||||||
then_val: ValueId(30),
|
then_val: ValueId(30),
|
||||||
else_val: ValueId(40),
|
else_val: ValueId(40),
|
||||||
|
type_hint: None, // Phase 63-3
|
||||||
});
|
});
|
||||||
|
|
||||||
join_func.body.push(JoinInst::Ret {
|
join_func.body.push(JoinInst::Ret {
|
||||||
@ -591,4 +596,88 @@ mod tests {
|
|||||||
|
|
||||||
std::env::remove_var("NYASH_JOINIR_IF_SELECT");
|
std::env::remove_var("NYASH_JOINIR_IF_SELECT");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Phase 63-2: Helper to create a simple pattern MIR with Const instructions
|
||||||
|
fn create_simple_pattern_mir_with_const() -> MirFunction {
|
||||||
|
let mut blocks = BTreeMap::new();
|
||||||
|
|
||||||
|
// Entry block (bb0): create const 10/20, then branch on cond
|
||||||
|
let mut entry = BasicBlock::new(BasicBlockId::new(0));
|
||||||
|
entry.instructions.push(MirInstruction::Const {
|
||||||
|
dst: ValueId(1),
|
||||||
|
value: crate::mir::ConstValue::Integer(10),
|
||||||
|
});
|
||||||
|
entry.instructions.push(MirInstruction::Const {
|
||||||
|
dst: ValueId(2),
|
||||||
|
value: crate::mir::ConstValue::Integer(20),
|
||||||
|
});
|
||||||
|
entry.terminator = Some(MirInstruction::Branch {
|
||||||
|
condition: ValueId(0), // cond parameter
|
||||||
|
then_bb: BasicBlockId::new(1),
|
||||||
|
else_bb: BasicBlockId::new(2),
|
||||||
|
});
|
||||||
|
blocks.insert(BasicBlockId::new(0), entry);
|
||||||
|
|
||||||
|
// Then block (bb1): return 10
|
||||||
|
let mut then_block = BasicBlock::new(BasicBlockId::new(1));
|
||||||
|
then_block.terminator = Some(MirInstruction::Return {
|
||||||
|
value: Some(ValueId(1)), // const 10
|
||||||
|
});
|
||||||
|
blocks.insert(BasicBlockId::new(1), then_block);
|
||||||
|
|
||||||
|
// Else block (bb2): return 20
|
||||||
|
let mut else_block = BasicBlock::new(BasicBlockId::new(2));
|
||||||
|
else_block.terminator = Some(MirInstruction::Return {
|
||||||
|
value: Some(ValueId(2)), // const 20
|
||||||
|
});
|
||||||
|
blocks.insert(BasicBlockId::new(2), else_block);
|
||||||
|
|
||||||
|
use crate::mir::function::FunctionMetadata;
|
||||||
|
use crate::mir::{EffectMask, MirType};
|
||||||
|
|
||||||
|
MirFunction {
|
||||||
|
signature: crate::mir::FunctionSignature {
|
||||||
|
name: "IfSelectTest.test/1".to_string(),
|
||||||
|
params: vec![MirType::Unknown],
|
||||||
|
return_type: MirType::Integer,
|
||||||
|
effects: EffectMask::PURE,
|
||||||
|
},
|
||||||
|
entry_block: BasicBlockId::new(0),
|
||||||
|
blocks: blocks.into_iter().collect(),
|
||||||
|
locals: vec![],
|
||||||
|
params: vec![ValueId(0)],
|
||||||
|
next_value_id: 3,
|
||||||
|
metadata: FunctionMetadata::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Phase 63-2: Test type hint propagation from MIR Const instructions
|
||||||
|
#[test]
|
||||||
|
fn test_type_hint_propagation_simple() {
|
||||||
|
use crate::mir::MirType;
|
||||||
|
|
||||||
|
std::env::set_var("NYASH_JOINIR_IF_SELECT", "1");
|
||||||
|
|
||||||
|
let func = create_simple_pattern_mir_with_const();
|
||||||
|
let entry_block = func.entry_block;
|
||||||
|
let result = try_lower_if_to_joinir(&func, entry_block, true, None);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
result.is_some(),
|
||||||
|
"Expected simple pattern to be lowered to Select"
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(JoinInst::Select { type_hint, .. }) = result {
|
||||||
|
assert_eq!(
|
||||||
|
type_hint,
|
||||||
|
Some(MirType::Integer),
|
||||||
|
"Expected type_hint to be Some(Integer) for IfSelectTest.simple (Const 10/20)"
|
||||||
|
);
|
||||||
|
eprintln!("✅ Phase 63-2: Type hint propagation successful: {:?}", type_hint);
|
||||||
|
} else {
|
||||||
|
panic!("Expected Select instruction with type_hint");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::env::remove_var("NYASH_JOINIR_IF_SELECT");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user