feat(joinir): Add Phase 40 implementation templates and integration points
Phase 35-39整理(C): JoinIR Frontend拡張雛形作成 - ast_lowerer.rs: extract_if_in_loop_modified_vars() template (~80 lines) - ast_lowerer.rs: extract_assigned_vars_from_body() template (~80 lines) - ast_lowerer.rs: lower_loop_case_a_simple() integration point marked - join_ir_vm_bridge.rs: convert_join_function_to_mir() extension template (~100 lines) Templates include: - Detailed purpose and implementation plan - Integration points in existing code - Example usage (array_ext.filter) - Links to Phase 39 design docs - TODO(Phase 40-1/2/3/4) markers Effect: Phase 40 implementation ready to start (追加箇所明確、実装漏れ防止) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -20,7 +20,7 @@
|
||||
//! - **A/B テスト可能**: 既存経路と新経路の両方で実行して比較検証
|
||||
|
||||
use crate::mir::join_ir::{ConstValue, JoinFunction, JoinFuncId, JoinInst, JoinModule, VarId};
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
|
||||
/// Phase 34-5: 式から値を抽出する際のコンテキスト
|
||||
///
|
||||
@ -334,7 +334,24 @@ impl AstToJoinIrLowerer {
|
||||
/// - k_exit: 結果を return
|
||||
///
|
||||
/// Phase 34-7.4b: Local ノード処理(同名再宣言 = 再代入)
|
||||
/// ループ本体lowering(Phase 34実装)
|
||||
///
|
||||
/// # Phase 40拡張予定
|
||||
///
|
||||
/// この関数に以下を追加:
|
||||
/// 1. `extract_if_in_loop_modified_vars()`呼び出し
|
||||
/// 2. 検出された変数をloop exit PHI生成に使用
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// // TODO(Phase 40-1): Add if-in-loop variable tracking
|
||||
/// // let loop_vars = self.get_loop_carried_vars(&loop_ctx);
|
||||
/// // let modified_in_if = self.extract_if_in_loop_modified_vars(&loop_body, &loop_vars);
|
||||
/// // Pass modified_in_if to create_exit_function() for PHI generation
|
||||
/// ```
|
||||
fn lower_loop_case_a_simple(&mut self, program_json: &serde_json::Value) -> JoinModule {
|
||||
// TODO(Phase 40-1): Add if-in-loop variable tracking here
|
||||
// Integration point for extract_if_in_loop_modified_vars()
|
||||
|
||||
// 1. Program(JSON) から defs を取得
|
||||
let defs = program_json["defs"]
|
||||
.as_array()
|
||||
@ -1228,6 +1245,166 @@ impl AstToJoinIrLowerer {
|
||||
_ => panic!("Unsupported expr type: {}", expr_type),
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Phase 40拡張予定: If-in-loop AST Lowering
|
||||
// ========================================
|
||||
|
||||
/// Phase 40-1で実装予定: ループ内if文の変数追跡
|
||||
///
|
||||
/// # Purpose
|
||||
///
|
||||
/// array_ext.filter等のif-in-loopパターンで、ループ内で修正される変数を
|
||||
/// 追跡し、ループ出口PHI生成に使用する。
|
||||
///
|
||||
/// # Implementation Plan (Phase 40-1)
|
||||
///
|
||||
/// ## Input
|
||||
/// - `loop_body`: ループ本体AST(JSON v0形式)
|
||||
/// - `loop_vars`: ループで使用される変数(Header PHIで定義)
|
||||
///
|
||||
/// ## Output
|
||||
/// - `HashSet<String>`: if分岐内で修正された変数名セット
|
||||
///
|
||||
/// ## Logic
|
||||
/// 1. Recursive AST walk (helper: `extract_assigned_vars_from_body`)
|
||||
/// 2. Detect assignments in if branches only
|
||||
/// 3. Filter for variables in `loop_vars` (loop-carried variables)
|
||||
/// 4. Return set of modified variable names
|
||||
///
|
||||
/// ## Integration Point
|
||||
/// - Call from: `lower_loop_case_a_simple()` or similar loop lowering
|
||||
/// - Use output for: Loop exit PHI generation in `create_exit_function()`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```nyash,ignore
|
||||
/// local out = new ArrayBox() // loop_vars = {out, i}
|
||||
/// local i = 0
|
||||
/// loop(i < n) {
|
||||
/// if fn(arr[i]) { // ← この中の代入を検出
|
||||
/// out.push(arr[i]) // ← out修正検出
|
||||
/// }
|
||||
/// i = i + 1
|
||||
/// }
|
||||
/// // Result: extract_if_in_loop_modified_vars() = {out}
|
||||
/// // → Loop exit PHI: phi out_exit = (out_header, out_loop_modified)
|
||||
/// ```
|
||||
///
|
||||
/// # Replaces (Phase 40-1削除対象)
|
||||
///
|
||||
/// - `if_phi::collect_assigned_vars()` (32 lines)
|
||||
/// - Current callsites: loop_builder.rs:1069, 1075
|
||||
/// - この関数実装でcallsites削除可能
|
||||
///
|
||||
/// # See Also
|
||||
///
|
||||
/// - Design: `docs/.../phase-39-if-phi-level2/joinir_extension_design.md`
|
||||
/// - A/B test: array_ext.filter (Primary representative function)
|
||||
///
|
||||
/// # TODO(Phase 40-1)
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// fn extract_if_in_loop_modified_vars(
|
||||
/// &mut self,
|
||||
/// loop_body: &serde_json::Value,
|
||||
/// loop_vars: &HashSet<String>,
|
||||
/// ) -> HashSet<String> {
|
||||
/// // Step 1: Recursive AST walk
|
||||
/// let all_assigned = self.extract_assigned_vars_from_body(loop_body);
|
||||
///
|
||||
/// // Step 2: Filter for if-statement assignments only
|
||||
/// let if_assigned = all_assigned.iter()
|
||||
/// .filter(|var| self.is_assigned_in_if_branch(loop_body, var))
|
||||
/// .cloned()
|
||||
/// .collect::<HashSet<_>>();
|
||||
///
|
||||
/// // Step 3: Filter for loop-carried variables
|
||||
/// if_assigned.intersection(loop_vars).cloned().collect()
|
||||
/// }
|
||||
/// ```
|
||||
#[allow(dead_code)]
|
||||
fn extract_if_in_loop_modified_vars(
|
||||
&mut self,
|
||||
_loop_body: &serde_json::Value,
|
||||
_loop_vars: &HashSet<String>,
|
||||
) -> HashSet<String> {
|
||||
// TODO(Phase 40-1): Implement if-in-loop variable tracking
|
||||
// See: docs/.../phase-39-if-phi-level2/joinir_extension_design.md
|
||||
unimplemented!("Phase 40-1: If-in-loop variable tracking for array_ext.filter")
|
||||
}
|
||||
|
||||
/// Phase 40-1で実装予定: 再帰的AST走査(代入検出)
|
||||
///
|
||||
/// # Purpose
|
||||
///
|
||||
/// AST bodyを再帰的に走査し、代入文を検出する。
|
||||
///
|
||||
/// # Implementation Plan
|
||||
///
|
||||
/// ## Recursive Descent
|
||||
/// - Handle: "Local" assignments (`local x = ...` or `x = ...`)
|
||||
/// - Handle: Nested blocks (`{ ... }`)
|
||||
/// - Handle: If/Loop bodies (recursive call)
|
||||
///
|
||||
/// ## Return
|
||||
/// - `HashSet<String>`: 代入された変数名全て
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```json
|
||||
/// {
|
||||
/// "type": "Block",
|
||||
/// "body": [
|
||||
/// {"type": "Local", "name": "x", "expr": ...}, // x assigned
|
||||
/// {"type": "If", "cond": ..., "then": [
|
||||
/// {"type": "Local", "name": "y", "expr": ...} // y assigned
|
||||
/// ]}
|
||||
/// ]
|
||||
/// }
|
||||
/// ```
|
||||
/// Result: {x, y}
|
||||
///
|
||||
/// # TODO(Phase 40-1)
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// fn extract_assigned_vars_from_body(
|
||||
/// &mut self,
|
||||
/// body: &serde_json::Value,
|
||||
/// ) -> HashSet<String> {
|
||||
/// let mut assigned = HashSet::new();
|
||||
///
|
||||
/// if let Some(stmts) = body.get("body").and_then(|b| b.as_array()) {
|
||||
/// for stmt in stmts {
|
||||
/// match stmt.get("type").and_then(|t| t.as_str()) {
|
||||
/// Some("Local") => {
|
||||
/// if let Some(name) = stmt.get("name").and_then(|n| n.as_str()) {
|
||||
/// assigned.insert(name.to_string());
|
||||
/// }
|
||||
/// }
|
||||
/// Some("If") => {
|
||||
/// // Recursive: then/else branches
|
||||
/// if let Some(then_body) = stmt.get("then") {
|
||||
/// assigned.extend(self.extract_assigned_vars_from_body(then_body));
|
||||
/// }
|
||||
/// }
|
||||
/// // ... other cases ...
|
||||
/// _ => {}
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assigned
|
||||
/// }
|
||||
/// ```
|
||||
#[allow(dead_code)]
|
||||
fn extract_assigned_vars_from_body(
|
||||
&mut self,
|
||||
_body: &serde_json::Value,
|
||||
) -> HashSet<String> {
|
||||
// TODO(Phase 40-1): Implement recursive AST assignment detection
|
||||
unimplemented!("Phase 40-1: Recursive AST assignment detection")
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AstToJoinIrLowerer {
|
||||
|
||||
Reference in New Issue
Block a user