refactor(joinir): Split ast_lowerer and join_ir_vm_bridge into modules
ast_lowerer.rs → ast_lowerer/ (10 files): - mod.rs: public surface + entry dispatch - context.rs: ExtractCtx helpers - expr.rs: expression-to-JoinIR extraction - if_return.rs: simple if→Select lowering - loop_patterns.rs: loop variants (simple/break/continue) - read_quoted.rs: read_quoted_from lowering (Phase 45-46) - nested_if.rs: NestedIfMerge lowering - analysis.rs: loop if-var analysis + metadata helpers - tests.rs: frontend lowering tests - README.md: module documentation join_ir_vm_bridge.rs → join_ir_vm_bridge/ (5 files): - mod.rs: public surface + shared helpers - convert.rs: JoinIR→MIR lowering - runner.rs: VM execution entry (run_joinir_via_vm) - meta.rs: experimental metadata-aware hooks - tests.rs: bridge-specific unit tests - README.md: module documentation Benefits: - Clear separation of concerns per pattern - Easier navigation and maintenance - Each file has single responsibility - README documents module boundaries Co-authored-by: ChatGPT <noreply@openai.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
137
src/mir/join_ir/frontend/ast_lowerer/mod.rs
Normal file
137
src/mir/join_ir/frontend/ast_lowerer/mod.rs
Normal file
@ -0,0 +1,137 @@
|
||||
//! AST/CFG → JoinIR Lowering
|
||||
//!
|
||||
//! このモジュールは AST/CFG ノードを JoinIR 命令に変換する。
|
||||
//!
|
||||
//! ## 責務
|
||||
//!
|
||||
//! - **If 文→Select/IfMerge 変換**: 条件分岐を JoinIR の継続渡しスタイルに変換
|
||||
//! - **Loop 文→loop_step/k_exit 変換**: ループを関数呼び出しと継続に正規化
|
||||
//! - **Break/Continue/Return→k_* 変換**: 制御フローを継続 ID として表現
|
||||
//!
|
||||
//! ## Phase 34-2 での実装スコープ
|
||||
//!
|
||||
//! 最初は `IfSelectTest.*` 相当の tiny ケースのみ対応:
|
||||
//! - Simple pattern: `if cond { return 1 } else { return 2 }`
|
||||
//!
|
||||
//! ## 設計原則
|
||||
//!
|
||||
//! - **JoinIR = PHI 生成器**: 既存 PHI の変換器にはしない(Phase 33-10 原則)
|
||||
//! - **段階的移行**: 既存 MIR Builder 経路は保持、新経路はデフォルト OFF
|
||||
//! - **A/B テスト可能**: 既存経路と新経路の両方で実行して比較検証
|
||||
|
||||
pub(crate) use crate::mir::join_ir::{
|
||||
BinOpKind, CompareOp, ConstValue, JoinFuncId, JoinFunction, JoinInst, JoinModule, MergePair,
|
||||
VarId,
|
||||
};
|
||||
pub(crate) use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
mod analysis;
|
||||
mod context;
|
||||
mod expr;
|
||||
mod if_return;
|
||||
mod loop_patterns;
|
||||
mod nested_if;
|
||||
mod read_quoted;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub(crate) use context::ExtractCtx;
|
||||
|
||||
/// AST/CFG → JoinIR 変換器
|
||||
///
|
||||
/// Phase 34-2: Program(JSON v0) から tiny IfSelect ケースを JoinIR に変換
|
||||
pub struct AstToJoinIrLowerer {
|
||||
pub(crate) next_func_id: u32,
|
||||
#[allow(dead_code)]
|
||||
pub(crate) next_var_id: u32,
|
||||
}
|
||||
|
||||
impl AstToJoinIrLowerer {
|
||||
/// 新しい lowerer を作成
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
next_func_id: 0,
|
||||
next_var_id: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Program(JSON v0) → JoinModule
|
||||
///
|
||||
/// Phase 34-2/34-3/34-4: simple/local/json_shape pattern に対応
|
||||
/// Phase 34-5: extract_value 統一化(Int/Var/Method 構造まで)
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - パターンに合わない Program(JSON) が来た場合(Phase 34 は tiny テスト専用)
|
||||
/// - ループ・複数変数・副作用付き if(Phase 34-6 以降で対応予定)
|
||||
pub fn lower_program_json(&mut self, program_json: &serde_json::Value) -> JoinModule {
|
||||
// 1. Program(JSON) から defs を取得
|
||||
let defs = program_json["defs"]
|
||||
.as_array()
|
||||
.expect("Program(JSON v0) must have 'defs' array");
|
||||
|
||||
// 2. 最初の関数定義を取得
|
||||
let func_def = defs
|
||||
.get(0)
|
||||
.expect("At least one function definition required");
|
||||
|
||||
let func_name = func_def["name"]
|
||||
.as_str()
|
||||
.expect("Function must have 'name'");
|
||||
|
||||
// 3. 関数名で分岐(Phase 34-2/34-3/34-4/34-5/34-7/34-8/41-4/45)
|
||||
// test/local/_read_value_from_pair: If Return pattern
|
||||
// simple: Loop pattern (Phase 34-7/34-8)
|
||||
// parse_loop: Phase 41-4 NestedIfMerge pattern
|
||||
// read_quoted_from: Phase 45 Guard if + Loop with break + accumulator
|
||||
match func_name {
|
||||
"test" | "local" | "_read_value_from_pair" => {
|
||||
self.lower_if_return_pattern(program_json)
|
||||
}
|
||||
"simple" => {
|
||||
// Phase 34-8: Loop パターンの詳細分析(break/continue 検出)
|
||||
self.lower_loop_with_break_continue(program_json)
|
||||
}
|
||||
"parse_loop" => {
|
||||
// Phase 41-4: NestedIfMerge pattern (dev flag gated)
|
||||
// Guard: HAKO_JOINIR_NESTED_IF=1 を要求
|
||||
if std::env::var("HAKO_JOINIR_NESTED_IF").ok().as_deref() == Some("1") {
|
||||
self.lower_nested_if_pattern(program_json)
|
||||
} else {
|
||||
// Dev flag が OFF の場合は panic(旧ルートにフォールバックするため)
|
||||
panic!(
|
||||
"parse_loop NestedIfMerge requires HAKO_JOINIR_NESTED_IF=1. \
|
||||
Set env var to enable Phase 41-4 route."
|
||||
);
|
||||
}
|
||||
}
|
||||
"read_quoted_from" => {
|
||||
// Phase 45: read_quoted_from pattern (dev flag gated)
|
||||
// Guard if + Loop with break + accumulator
|
||||
if std::env::var("HAKO_JOINIR_READ_QUOTED").ok().as_deref() == Some("1") {
|
||||
self.lower_read_quoted_pattern(program_json)
|
||||
} else {
|
||||
panic!(
|
||||
"read_quoted_from JoinIR requires HAKO_JOINIR_READ_QUOTED=1. \
|
||||
Set env var to enable Phase 45 route."
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => panic!("Unsupported function: {}", func_name),
|
||||
}
|
||||
}
|
||||
|
||||
/// 次の関数 ID を生成
|
||||
pub(crate) fn next_func_id(&mut self) -> JoinFuncId {
|
||||
let id = JoinFuncId::new(self.next_func_id);
|
||||
self.next_func_id += 1;
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AstToJoinIrLowerer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user