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>
136 lines
5.0 KiB
Rust
136 lines
5.0 KiB
Rust
//! AOT-Plan v1 → MIR13 importer (Phase 15.1)
|
|
//! Feature-gated behind `aot-plan-import`.
|
|
|
|
use crate::mir::function_emission as femit;
|
|
use crate::mir::{
|
|
BasicBlockId, ConstValue, EffectMask, FunctionSignature, MirFunction, MirModule, MirType,
|
|
};
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
struct PlanV1 {
|
|
version: String, // "1"
|
|
name: Option<String>,
|
|
functions: Vec<PlanFunction>,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
struct PlanFunction {
|
|
name: String,
|
|
#[serde(default)]
|
|
params: Vec<PlanParam>,
|
|
return_type: Option<String>, // "integer" | "string" | ...
|
|
#[serde(default)]
|
|
body: Option<PlanBody>,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
struct PlanParam {
|
|
name: String,
|
|
r#type: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
#[serde(tag = "kind")]
|
|
enum PlanBody {
|
|
#[serde(rename = "const_return")]
|
|
ConstReturn { value: serde_json::Value },
|
|
#[serde(rename = "empty")]
|
|
Empty,
|
|
}
|
|
|
|
fn map_type(s: Option<&str>) -> MirType {
|
|
match s.unwrap_or("") {
|
|
"integer" => MirType::Integer,
|
|
"float" => MirType::Float,
|
|
"bool" => MirType::Bool,
|
|
"string" => MirType::String,
|
|
"void" => MirType::Void,
|
|
_ => MirType::Unknown,
|
|
}
|
|
}
|
|
|
|
fn const_from_json(v: &serde_json::Value) -> Option<ConstValue> {
|
|
if let Some(i) = v.as_i64() {
|
|
return Some(ConstValue::Integer(i));
|
|
}
|
|
if let Some(b) = v.as_bool() {
|
|
return Some(ConstValue::Bool(b));
|
|
}
|
|
if let Some(f) = v.as_f64() {
|
|
return Some(ConstValue::Float(f));
|
|
}
|
|
if let Some(s) = v.as_str() {
|
|
return Some(ConstValue::String(s.to_string()));
|
|
}
|
|
None
|
|
}
|
|
|
|
/// Import a v1 plan JSON string into a MIR13 module with skeleton bodies.
|
|
pub fn import_from_str(plan_json: &str) -> Result<MirModule, String> {
|
|
let plan: PlanV1 =
|
|
serde_json::from_str(plan_json).map_err(|e| format!("invalid plan json: {}", e))?;
|
|
if plan.version != "1" {
|
|
return Err("unsupported plan version".into());
|
|
}
|
|
let mut module = MirModule::new(plan.name.unwrap_or_else(|| "aot_plan".into()));
|
|
|
|
for f in plan.functions.iter() {
|
|
// Signatures: keep types minimal; params exist but VM uses stackless calling for main
|
|
let ret_ty = map_type(f.return_type.as_deref());
|
|
let sig = FunctionSignature {
|
|
name: f.name.clone(),
|
|
params: vec![],
|
|
return_type: ret_ty.clone(),
|
|
effects: EffectMask::PURE,
|
|
};
|
|
let mut mf = MirFunction::new(sig, BasicBlockId::new(0));
|
|
let bb = mf.entry_block;
|
|
// Body lowering (skeleton)
|
|
match &f.body {
|
|
Some(PlanBody::ConstReturn { value }) => {
|
|
let cst = const_from_json(value)
|
|
.ok_or_else(|| format!("unsupported const value in {}", f.name))?;
|
|
let dst = match cst {
|
|
ConstValue::Integer(i) => femit::emit_const_integer(&mut mf, bb, i),
|
|
ConstValue::Bool(b) => femit::emit_const_bool(&mut mf, bb, b),
|
|
ConstValue::Float(fl) => {
|
|
// function_emission currently has no float helper; use manual emit via integer as placeholder is wrong.
|
|
// Fall back to direct const emission inline here to avoid adding a new helper unnecessarily.
|
|
let d = mf.next_value_id();
|
|
if let Some(block) = mf.get_block_mut(bb) {
|
|
block.add_instruction(crate::mir::MirInstruction::Const {
|
|
dst: d,
|
|
value: ConstValue::Float(fl),
|
|
});
|
|
}
|
|
d
|
|
}
|
|
ConstValue::String(s) => femit::emit_const_string(&mut mf, bb, s),
|
|
other => {
|
|
// Null/Void are not expected in PlanBody::ConstReturn; still handle gracefully.
|
|
let d = mf.next_value_id();
|
|
if let Some(block) = mf.get_block_mut(bb) {
|
|
block.add_instruction(crate::mir::MirInstruction::Const {
|
|
dst: d,
|
|
value: other,
|
|
});
|
|
}
|
|
d
|
|
}
|
|
};
|
|
femit::emit_return_value(&mut mf, bb, dst);
|
|
// If return_type is unspecified, keep Unknown to allow VM dynamic display; otherwise retain declared type
|
|
if matches!(ret_ty, MirType::Unknown) { /* keep Unknown */ }
|
|
}
|
|
Some(PlanBody::Empty) | None => {
|
|
// Return default 0 for display stability; mark signature Unknown for runtime display parity
|
|
let dst = femit::emit_const_integer(&mut mf, bb, 0);
|
|
femit::emit_return_value(&mut mf, bb, dst);
|
|
mf.signature.return_type = MirType::Unknown;
|
|
}
|
|
}
|
|
module.add_function(mf);
|
|
}
|
|
Ok(module)
|
|
}
|