Files
hakorune/src/mir/join_ir/mod.rs

659 lines
21 KiB
Rust
Raw Normal View History

//! JoinIR — 関数正規化 IRPhase 26-H
//!
//! 目的: Hakorune の制御構造を **関数呼び出し+継続だけに正規化** する IR 層。
//! - φ ノード = 関数の引数
//! - merge ブロック = join 関数
//! - ループ = 再帰関数loop_step exit 継続k_exit
//! - break / continue = 適切な関数呼び出し
//!
//! 位置づけ:
//! ```text
//! AST → MIR+LoopForm v2 → JoinIR → VM / LLVM
//! ```
//!
//! Phase 26-H スコープ:
//! - 型定義のみ(変換ロジックは次フェーズ)
//! - 最小限の命令セット
//! - Debug 出力で妥当性確認
//!
//! Phase 27.9: Modular Structure
//! - Type definitions and common utilities in this file
//! - Lowering functions in `lowering/` submodule
use std::collections::BTreeMap;
use crate::mir::ValueId;
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>
2025-11-29 17:58:06 +09:00
// Phase 63-3: 型ヒント用
use crate::mir::MirType;
// Phase 27.9: Lowering submodule
pub mod lowering;
// Phase 29 L-5.2: Progress verification
pub mod verify;
// Phase 30.x: JSON serialization (jsonir v0)
pub mod json;
// Phase 26-H.B: Normalized JoinIR (テスト専用ミニ)
pub mod normalized;
feat(joinir): Phase 34-6 MethodCall 構造と本物の substring 意味論 **Phase 34-6 実装完了**: MethodCall 構造を JoinIR に追加し、本物の substring 呼び出しを通すことに成功。 ## 主要変更 ### 1. MethodCall 構造追加 (34-6.1) - `src/mir/join_ir/mod.rs`: JoinInst::MethodCall バリアント (+8 lines) - 構造: `{ dst, receiver, method, args }` - 設計原則: JoinIR は構造のみ、意味論は MIR レベル ### 2. extract_value 更新 (34-6.2) - `src/mir/join_ir/frontend/ast_lowerer.rs`: Method 処理本物化 (+37 lines) - receiver/args を extract_value で再帰処理 - ダミー Const(0) 削除 → 本物の MethodCall 生成 - cond 処理修正: ValueId(0) ハードコード → extract_value で取得 ### 3. JoinIR→MIR 変換実装 (34-6.3) - `src/mir/join_ir_vm_bridge.rs`: MethodCall → BoxCall 変換 (+12 lines) - `src/mir/join_ir/json.rs`: MethodCall JSON シリアライゼーション (+16 lines) - `src/mir/join_ir_runner.rs`: MethodCall 未対応エラー (+7 lines) ### 4. テスト更新 (34-6.4) - `docs/.../fixtures/json_shape_read_value.program.json`: 本物の substring 構造 - `src/tests/joinir_frontend_if_select.rs`: run_joinir_via_vm 使用 - テスト成功: v="hello", at=3 → "hel" ✅ ## 成果 - ✅ テスト全通過(1 passed; 0 failed) - ✅ 設計原則確立: JoinIR = 構造 SSOT、意味論 = MIR レベル - ✅ Phase 33-10 原則との整合性: Method でも同じ原則適用 **ドキュメント更新**: CURRENT_TASK.md + TASKS.md(Phase 34-6 完了記録) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:05:46 +09:00
// Phase 34-1: Frontend (AST→JoinIR) — skeleton only
pub mod frontend;
// Phase 56: Ownership analysis (reads/writes → owned/relay/capture)
pub mod ownership;
obs(joinir): Phase 72 - PHI Reserved Region Observation Complete ## Summary Observed PHI dst ValueId distribution to determine if verifier can enforce reserved region (0-99). **Conclusion: Verifier strengthening NOT recommended.** ## Key Finding PHI dst allocation does NOT architecturally respect reserved region: - PHI dst comes from `builder.next_value_id()` (host MirBuilder) - Reserved region (0-99) is a JoinValueSpace contract for JoinIR lowering - These are separate allocation pools with no enforcement mechanism - Current stability is accidental (ValueId allocation ordering) ## Evidence Manual verification (`apps/tests/loop_min_while.hako`): - PHI dst = %3 (ValueId(3)) ✅ in reserved region - Works because PHI allocated early in function (0-20 typical) - JoinValueSpace allocates high (100+, 1000+) - Accidental separation, not enforced ## Implementation Added observation infrastructure (debug-only): - `src/mir/join_ir/verify_phi_reserved.rs` (266 lines) - PHI dst observer with distribution analyzer - Region classifier (Reserved/Param/Local) - Human-readable report generator - Instrumentation at PHI allocation points: - loop_header_phi_builder.rs:94, 151 - Debug-only `observe_phi_dst()` calls ## Test Results - Unit tests: ✅ 4/4 PASS (verify_phi_reserved module) - Lib tests: ✅ 950/950 PASS, 56 ignored - Normalized tests: ✅ 54/54 PASS - Manual verification: ✅ PHI dst in 0-99 observed ## Decision: Document, Don't Enforce **Rationale**: 1. No architectural mechanism to enforce PHI dst ∈ [0, 99] 2. Adding verifier creates false assumptions about allocation order 3. Current system stable through separate pools (950/950 tests) 4. Future architectural fix possible (Phase 73+) but not urgent ## Documentation - PHASE_72_SUMMARY.md: Executive summary and implementation record - phase72-phi-reserved-observation.md: Detailed findings and analysis - CURRENT_TASK.md: Phase 72 completion entry ## Next Steps - Phase 73: Update architecture overview with Phase 72 findings - Optional: Explicit PHI reserved pool (future enhancement) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 03:23:02 +09:00
// Phase 72: PHI reserved region verifier
#[cfg(debug_assertions)]
pub mod verify_phi_reserved;
// Re-export lowering functions for backward compatibility
pub use lowering::{
lower_funcscanner_trim_to_joinir, lower_min_loop_to_joinir, lower_skip_ws_to_joinir,
};
// Re-export verification functions
pub use normalized::{
normalize_pattern1_minimal, normalize_pattern2_minimal, normalized_pattern1_to_structured,
normalized_pattern2_to_structured, NormalizedModule,
};
pub use verify::verify_progress_for_skip_ws;
// Phase 200-3: Contract verification functions are in merge/mod.rs (private module access)
/// JoinIR 関数IDMIR 関数とは別 ID でもよい)
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct JoinFuncId(pub u32);
impl JoinFuncId {
pub fn new(id: u32) -> Self {
JoinFuncId(id)
}
feat(joinir): Phase 34-7.5 helpers + Phase 34-8 Break/Continue implementation Phase 34-7.5: Code organization improvements - Added type conversion helpers (as_cont/as_func) in join_ir/mod.rs - Enhanced docstrings for JoinCall/JoinJump with usage examples - Improved error messages in join_ir_vm_bridge.rs JoinIrFrontendTestRunner box implementation - Created src/tests/helpers/joinir_frontend.rs (119 lines) - Reduced test code by 83% (70 lines → 12 lines per test) - 26% overall reduction in test file (284 → 209 lines) Phase 34-8: Break/Continue pattern implementation - Extended ast_lowerer.rs (+630 lines) - lower_loop_break_pattern(): Break as Jump (early return) - lower_loop_continue_pattern(): Continue as Select + Call - Added Bool literal support in extract_value() - Created 2 fixtures: loop_frontend_{break,continue}.program.json - Added 2 A/B tests (all 6 Phase 34 tests PASS) Technical achievements: - Break = Jump (early return pattern) - Continue = Select + Call (NOT Jump) - critical discovery - 3-function structure sufficient (no k_continue needed) - SSA-style re-assignment with natural var_map updates Test results: ✅ joinir_frontend_if_select_simple_ab_test ✅ joinir_frontend_if_select_local_ab_test ✅ joinir_frontend_json_shape_read_value_ab_test ✅ joinir_frontend_loop_simple_ab_test ✅ joinir_frontend_loop_break_ab_test ✅ joinir_frontend_loop_continue_ab_test 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 01:02:49 +09:00
/// JoinFuncId を JoinContId に変換
///
/// # Use Case
/// Jump 命令で関数を continuation として使う場合
/// ```rust
/// let func_id = JoinFuncId(42);
/// let cont_id = func_id.as_cont();
/// Jump { cont: cont_id, args: vec![], cond: None }
/// ```
///
/// # Phase 34-7 Note
/// JoinFuncId と JoinContId は別の newtype だが、内部的には同じ u32 ID を共有する。
/// この変換は型レベルでの役割の明示(関数 vs 継続)を可能にする。
pub fn as_cont(self) -> JoinContId {
JoinContId(self.0)
}
}
/// 継続join / ループ step / exit continuationを識別するID
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct JoinContId(pub u32);
impl JoinContId {
pub fn new(id: u32) -> Self {
JoinContId(id)
}
feat(joinir): Phase 34-7.5 helpers + Phase 34-8 Break/Continue implementation Phase 34-7.5: Code organization improvements - Added type conversion helpers (as_cont/as_func) in join_ir/mod.rs - Enhanced docstrings for JoinCall/JoinJump with usage examples - Improved error messages in join_ir_vm_bridge.rs JoinIrFrontendTestRunner box implementation - Created src/tests/helpers/joinir_frontend.rs (119 lines) - Reduced test code by 83% (70 lines → 12 lines per test) - 26% overall reduction in test file (284 → 209 lines) Phase 34-8: Break/Continue pattern implementation - Extended ast_lowerer.rs (+630 lines) - lower_loop_break_pattern(): Break as Jump (early return) - lower_loop_continue_pattern(): Continue as Select + Call - Added Bool literal support in extract_value() - Created 2 fixtures: loop_frontend_{break,continue}.program.json - Added 2 A/B tests (all 6 Phase 34 tests PASS) Technical achievements: - Break = Jump (early return pattern) - Continue = Select + Call (NOT Jump) - critical discovery - 3-function structure sufficient (no k_continue needed) - SSA-style re-assignment with natural var_map updates Test results: ✅ joinir_frontend_if_select_simple_ab_test ✅ joinir_frontend_if_select_local_ab_test ✅ joinir_frontend_json_shape_read_value_ab_test ✅ joinir_frontend_loop_simple_ab_test ✅ joinir_frontend_loop_break_ab_test ✅ joinir_frontend_loop_continue_ab_test 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 01:02:49 +09:00
/// JoinContId を JoinFuncId に変換
///
/// # Use Case
/// 継続 ID を関数 ID として参照する場合JoinModule の functions map でルックアップ時など)
/// ```rust
/// let cont_id = JoinContId(42);
/// let func = join_module.functions.get(&cont_id.as_func())?;
/// ```
///
/// # Phase 34-7 Note
/// JoinIR では継続も関数として実装されるため、この変換が必要になる。
pub fn as_func(self) -> JoinFuncId {
JoinFuncId(self.0)
}
}
/// 変数IDPhase 26-H では MIR の ValueId を再利用)
pub type VarId = ValueId;
/// 環境変数フラグが "1" かチェックするヘルパーJoinIR 実験経路用)
/// Phase 72-C Step 2: SSOT統一 - すべてのリードを config::env::joinir_dev 経由に
pub(crate) fn env_flag_is_1(name: &str) -> bool {
use crate::config::env::joinir_dev;
match name {
"NYASH_JOINIR_LOWER_GENERIC" => joinir_dev::lower_generic_enabled(),
"NYASH_JOINIR_MAINLINE_DEBUG" => joinir_dev::mainline_debug_enabled(),
"NYASH_JOINIR_IF_MERGE" => joinir_dev::if_merge_enabled(),
"NYASH_JOINIR_DEBUG" => joinir_dev::debug_enabled(),
"NYASH_JOINIR_VM_BRIDGE" => joinir_dev::vm_bridge_enabled(),
"NYASH_JOINIR_STRICT" => joinir_dev::strict_enabled(),
"NYASH_JOINIR_SNAPSHOT_GENERATE" => joinir_dev::snapshot_generate_enabled(),
"NYASH_JOINIR_SNAPSHOT_TEST" => joinir_dev::snapshot_test_enabled(),
"NYASH_JOINIR_LOWER_FROM_MIR" => joinir_dev::lower_from_mir_enabled(),
"NYASH_JOINIR_LLVM_EXPERIMENT" => joinir_dev::llvm_experiment_enabled(),
"HAKO_JOINIR_IF_TOPLEVEL" => joinir_dev::if_toplevel_enabled(),
"HAKO_JOINIR_IF_TOPLEVEL_TRACE" => joinir_dev::if_toplevel_trace_enabled(),
"HAKO_JOINIR_IF_IN_LOOP_TRACE" => joinir_dev::if_in_loop_trace_enabled(),
"HAKO_JOINIR_NESTED_IF" => joinir_dev::nested_if_enabled(),
"HAKO_JOINIR_PRINT_TOKENS_MAIN" => joinir_dev::print_tokens_main_enabled(),
"HAKO_JOINIR_ARRAY_FILTER_MAIN" => joinir_dev::array_filter_main_enabled(),
"HAKO_JOINIR_READ_QUOTED" => joinir_dev::read_quoted_enabled(),
"HAKO_JOINIR_READ_QUOTED_IFMERGE" => joinir_dev::read_quoted_ifmerge_enabled(),
// Fallback for unknown flags (shouldn't happen in normal operation)
// NYASH_JOINIR_EXPERIMENT is handled by test helpers, not body code
_ => std::env::var(name).ok().as_deref() == Some("1"),
}
}
/// Phase 27.4-A: ループ header φ の意味を表す構造Pinned/Carrier 分類)
///
/// HeaderPhiBuilder が生成していた「ループ変数の合流」を JoinIR の loop_step 引数として表現するためのヘルパー。
///
/// 用語:
/// - **Pinned**: ループ中で値が変わらない変数(例: skip_ws の s, n / trim の str, b
/// - **Carrier**: ループで更新される変数(例: skip_ws の i / trim の e
///
/// Phase 27.4 では minimal/trim 用に手動で構成するが、将来は LoopScopeShape から自動導出する。
#[derive(Debug, Clone)]
#[allow(dead_code)] // Phase 27.4-C で実際に使用予定(現在は設計の雛形)
pub(crate) struct LoopHeaderShape {
/// Pinned: ループ中で不変の変数リスト(初期値がそのまま使われる)
pinned: Vec<ValueId>,
/// Carrier: ループで更新される変数リスト(φ ノードで合流が必要)
carriers: Vec<ValueId>,
}
#[allow(dead_code)] // Phase 27.4-C で実際に使用予定
impl LoopHeaderShape {
/// Phase 27.4-A: 手動で Pinned/Carrier を指定して構築
pub(crate) fn new_manual(pinned: Vec<ValueId>, carriers: Vec<ValueId>) -> Self {
LoopHeaderShape { pinned, carriers }
}
/// loop_step 関数の引数リストを生成pinned → carrier の順)
pub(crate) fn to_loop_step_params(&self) -> Vec<ValueId> {
let mut params = self.pinned.clone();
params.extend(self.carriers.clone());
params
}
}
/// Phase 27.5: ループ exit φ の意味を表す構造
///
/// ExitPhiBuilder が生成していた「ループ脱出時の変数合流」を JoinIR の k_exit 引数として表現するためのヘルパー。
///
/// 用語:
/// - **exit_args**: ループから脱出する際に k_exit に渡す値のリスト
///
/// 例:
/// - **minimal_ssa_skip_ws**: exit_args = [i]
/// - ループから抜ける時、現在の i の値を返す
/// - **FuncScanner.trim**: exit_args = [e] (Option A)
/// - ループから抜ける時、現在の e の値を返す(後続で substring(b, e) を呼ぶ)
///
/// Phase 27.5 では minimal/trim 用に手動で構成するが、将来は ExitPhiBuilder の分析から自動導出する。
#[derive(Debug, Clone)]
#[allow(dead_code)] // Phase 27.6 で Exit φ 統合の実装フェーズで使用予定(現在は設計の雛形)
pub(crate) struct LoopExitShape {
/// Exit 時に k_exit に渡したい値JoinIR 引数)
exit_args: Vec<ValueId>,
}
#[allow(dead_code)] // Phase 27.6 で実際に使用予定
impl LoopExitShape {
/// Phase 27.5: 手動で exit_args を指定して構築
pub(crate) fn new_manual(exit_args: Vec<ValueId>) -> Self {
LoopExitShape { exit_args }
}
}
/// JoinIR フェーズメタデータ。
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum JoinIrPhase {
/// Lowering 直後の構造化 JoinIRPattern15 / CarrierInfo / Boundary/ExitLine
Structured,
/// 将来導入予定の正規化済み JoinIR関数継続Env、TailCall-only
Normalized,
}
/// JoinIR 関数
#[derive(Debug, Clone)]
pub struct JoinFunction {
/// 関数ID
pub id: JoinFuncId,
/// 関数名(デバッグ用)
pub name: String,
/// 引数(φ に相当)
pub params: Vec<VarId>,
/// 命令列(現在は直列、将来的にはブロック構造も可)
pub body: Vec<JoinInst>,
/// 呼び出し元に返す継続(ルートは None
pub exit_cont: Option<JoinContId>,
}
impl JoinFunction {
pub fn new(id: JoinFuncId, name: String, params: Vec<VarId>) -> Self {
Self {
id,
name,
params,
body: Vec::new(),
exit_cont: None,
}
}
}
feat(joinir): Phase 34-6 MethodCall 構造と本物の substring 意味論 **Phase 34-6 実装完了**: MethodCall 構造を JoinIR に追加し、本物の substring 呼び出しを通すことに成功。 ## 主要変更 ### 1. MethodCall 構造追加 (34-6.1) - `src/mir/join_ir/mod.rs`: JoinInst::MethodCall バリアント (+8 lines) - 構造: `{ dst, receiver, method, args }` - 設計原則: JoinIR は構造のみ、意味論は MIR レベル ### 2. extract_value 更新 (34-6.2) - `src/mir/join_ir/frontend/ast_lowerer.rs`: Method 処理本物化 (+37 lines) - receiver/args を extract_value で再帰処理 - ダミー Const(0) 削除 → 本物の MethodCall 生成 - cond 処理修正: ValueId(0) ハードコード → extract_value で取得 ### 3. JoinIR→MIR 変換実装 (34-6.3) - `src/mir/join_ir_vm_bridge.rs`: MethodCall → BoxCall 変換 (+12 lines) - `src/mir/join_ir/json.rs`: MethodCall JSON シリアライゼーション (+16 lines) - `src/mir/join_ir_runner.rs`: MethodCall 未対応エラー (+7 lines) ### 4. テスト更新 (34-6.4) - `docs/.../fixtures/json_shape_read_value.program.json`: 本物の substring 構造 - `src/tests/joinir_frontend_if_select.rs`: run_joinir_via_vm 使用 - テスト成功: v="hello", at=3 → "hel" ✅ ## 成果 - ✅ テスト全通過(1 passed; 0 failed) - ✅ 設計原則確立: JoinIR = 構造 SSOT、意味論 = MIR レベル - ✅ Phase 33-10 原則との整合性: Method でも同じ原則適用 **ドキュメント更新**: CURRENT_TASK.md + TASKS.md(Phase 34-6 完了記録) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:05:46 +09:00
/// Phase 33-6: 複数変数を merge する if/else のペア
#[derive(Debug, Clone)]
pub struct MergePair {
/// merge 先の変数
pub dst: VarId,
/// then 分岐での値
pub then_val: VarId,
/// else 分岐での値
pub else_val: VarId,
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>
2025-11-29 17:58:06 +09:00
/// Phase 63-3: 結果型ヒントMIR PHI 生成時の型推論を回避)
pub type_hint: Option<MirType>,
feat(joinir): Phase 34-6 MethodCall 構造と本物の substring 意味論 **Phase 34-6 実装完了**: MethodCall 構造を JoinIR に追加し、本物の substring 呼び出しを通すことに成功。 ## 主要変更 ### 1. MethodCall 構造追加 (34-6.1) - `src/mir/join_ir/mod.rs`: JoinInst::MethodCall バリアント (+8 lines) - 構造: `{ dst, receiver, method, args }` - 設計原則: JoinIR は構造のみ、意味論は MIR レベル ### 2. extract_value 更新 (34-6.2) - `src/mir/join_ir/frontend/ast_lowerer.rs`: Method 処理本物化 (+37 lines) - receiver/args を extract_value で再帰処理 - ダミー Const(0) 削除 → 本物の MethodCall 生成 - cond 処理修正: ValueId(0) ハードコード → extract_value で取得 ### 3. JoinIR→MIR 変換実装 (34-6.3) - `src/mir/join_ir_vm_bridge.rs`: MethodCall → BoxCall 変換 (+12 lines) - `src/mir/join_ir/json.rs`: MethodCall JSON シリアライゼーション (+16 lines) - `src/mir/join_ir_runner.rs`: MethodCall 未対応エラー (+7 lines) ### 4. テスト更新 (34-6.4) - `docs/.../fixtures/json_shape_read_value.program.json`: 本物の substring 構造 - `src/tests/joinir_frontend_if_select.rs`: run_joinir_via_vm 使用 - テスト成功: v="hello", at=3 → "hel" ✅ ## 成果 - ✅ テスト全通過(1 passed; 0 failed) - ✅ 設計原則確立: JoinIR = 構造 SSOT、意味論 = MIR レベル - ✅ Phase 33-10 原則との整合性: Method でも同じ原則適用 **ドキュメント更新**: CURRENT_TASK.md + TASKS.md(Phase 34-6 完了記録) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:05:46 +09:00
}
/// JoinIR 命令セット(最小版)
#[derive(Debug, Clone)]
pub enum JoinInst {
feat(joinir): Phase 34-7.5 helpers + Phase 34-8 Break/Continue implementation Phase 34-7.5: Code organization improvements - Added type conversion helpers (as_cont/as_func) in join_ir/mod.rs - Enhanced docstrings for JoinCall/JoinJump with usage examples - Improved error messages in join_ir_vm_bridge.rs JoinIrFrontendTestRunner box implementation - Created src/tests/helpers/joinir_frontend.rs (119 lines) - Reduced test code by 83% (70 lines → 12 lines per test) - 26% overall reduction in test file (284 → 209 lines) Phase 34-8: Break/Continue pattern implementation - Extended ast_lowerer.rs (+630 lines) - lower_loop_break_pattern(): Break as Jump (early return) - lower_loop_continue_pattern(): Continue as Select + Call - Added Bool literal support in extract_value() - Created 2 fixtures: loop_frontend_{break,continue}.program.json - Added 2 A/B tests (all 6 Phase 34 tests PASS) Technical achievements: - Break = Jump (early return pattern) - Continue = Select + Call (NOT Jump) - critical discovery - 3-function structure sufficient (no k_continue needed) - SSA-style re-assignment with natural var_map updates Test results: ✅ joinir_frontend_if_select_simple_ab_test ✅ joinir_frontend_if_select_local_ab_test ✅ joinir_frontend_json_shape_read_value_ab_test ✅ joinir_frontend_loop_simple_ab_test ✅ joinir_frontend_loop_break_ab_test ✅ joinir_frontend_loop_continue_ab_test 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 01:02:49 +09:00
/// 通常の関数呼び出し(末尾再帰): f(args..., k_next)
///
/// # Semantics
/// - 他の JoinIR 関数を呼び出すMIR の Call に変換)
/// - ループでは末尾再帰として使うのが典型的
///
/// # MIR 変換
/// - `MirInstruction::Call { func, args, ... }` を生成
///
/// # Constraints (Phase 31/34 時点)
/// - **k_next は常に None にすること!**
/// JoinIR→MIR bridge が `k_next: Some(...)` 未対応
/// → エラー: "Call with k_next is not yet supported"
/// - 典型的な使い方: `Call { func, args, k_next: None, dst: Some(...) }`
///
/// # Loop Pattern での使い方 (Phase 34-7)
/// ```rust
/// // ✅ 正解: 末尾再帰
/// Call {
/// func: loop_step_id,
/// args: vec![i_next, acc_next, n],
/// k_next: None, // ⚠️ 必須: None にすること
/// dst: Some(result),
/// }
/// ```
Call {
func: JoinFuncId,
args: Vec<VarId>,
k_next: Option<JoinContId>,
/// 呼び出し結果を書き込む変数None の場合は末尾呼び出しとして扱う)
dst: Option<VarId>,
},
feat(joinir): Phase 34-7.5 helpers + Phase 34-8 Break/Continue implementation Phase 34-7.5: Code organization improvements - Added type conversion helpers (as_cont/as_func) in join_ir/mod.rs - Enhanced docstrings for JoinCall/JoinJump with usage examples - Improved error messages in join_ir_vm_bridge.rs JoinIrFrontendTestRunner box implementation - Created src/tests/helpers/joinir_frontend.rs (119 lines) - Reduced test code by 83% (70 lines → 12 lines per test) - 26% overall reduction in test file (284 → 209 lines) Phase 34-8: Break/Continue pattern implementation - Extended ast_lowerer.rs (+630 lines) - lower_loop_break_pattern(): Break as Jump (early return) - lower_loop_continue_pattern(): Continue as Select + Call - Added Bool literal support in extract_value() - Created 2 fixtures: loop_frontend_{break,continue}.program.json - Added 2 A/B tests (all 6 Phase 34 tests PASS) Technical achievements: - Break = Jump (early return pattern) - Continue = Select + Call (NOT Jump) - critical discovery - 3-function structure sufficient (no k_continue needed) - SSA-style re-assignment with natural var_map updates Test results: ✅ joinir_frontend_if_select_simple_ab_test ✅ joinir_frontend_if_select_local_ab_test ✅ joinir_frontend_json_shape_read_value_ab_test ✅ joinir_frontend_loop_simple_ab_test ✅ joinir_frontend_loop_break_ab_test ✅ joinir_frontend_loop_continue_ab_test 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 01:02:49 +09:00
/// 継続呼び出し(早期 return / exit 継続)
///
/// # Semantics
/// - **「早期 return」条件付き関数脱出として使う**
/// - cond=Some(v): v が true なら cont に Jump、false なら次の命令へ
/// - cond=None: 無条件 Jump
///
/// # MIR 変換
/// - cond=Some(v): `Branch(v, exit_block[Return], continue_block)` を生成
/// - exit_block: cont 関数を Call して Return
/// - continue_block: 次の JoinInst に続く
/// - cond=None: 無条件に cont を Call して Return
///
/// # Loop Pattern での使い方 (Phase 34-7)
/// ```rust
/// // ✅ 正解: 条件付き早期 return
/// Jump {
/// cont: k_exit_id.as_cont(),
/// args: vec![acc],
/// cond: Some(exit_cond), // exit_cond が true なら k_exit へ
/// }
/// // ↑ exit_cond が false なら次の命令body 処理)へ進む
///
/// // ❌ 間違い: Call で条件分岐しようとする
/// Call {
/// func: k_exit_id,
/// cond: Some(exit_cond), // こんなフィールドはない!
/// }
/// ```
///
/// # 典型的なパターン
/// ```text
/// loop_step(i, acc, n):
/// exit_cond = !(i < n)
/// Jump(k_exit, [acc], cond=exit_cond) // 🔑 早期 return
/// // ↓ Jump で抜けなかった場合のみ実行
/// acc_next = acc + 1
/// i_next = i + 1
/// Call(loop_step, [i_next, acc_next, n]) // 🔑 末尾再帰
/// ```
Jump {
cont: JoinContId,
args: Vec<VarId>,
/// None のときは無条件ジャンプ、Some(var) のときは var が truthy のときだけ実行
cond: Option<VarId>,
},
/// ルート関数 or 上位への戻り
Ret { value: Option<VarId> },
feat(joinir): Phase 34-6 MethodCall 構造と本物の substring 意味論 **Phase 34-6 実装完了**: MethodCall 構造を JoinIR に追加し、本物の substring 呼び出しを通すことに成功。 ## 主要変更 ### 1. MethodCall 構造追加 (34-6.1) - `src/mir/join_ir/mod.rs`: JoinInst::MethodCall バリアント (+8 lines) - 構造: `{ dst, receiver, method, args }` - 設計原則: JoinIR は構造のみ、意味論は MIR レベル ### 2. extract_value 更新 (34-6.2) - `src/mir/join_ir/frontend/ast_lowerer.rs`: Method 処理本物化 (+37 lines) - receiver/args を extract_value で再帰処理 - ダミー Const(0) 削除 → 本物の MethodCall 生成 - cond 処理修正: ValueId(0) ハードコード → extract_value で取得 ### 3. JoinIR→MIR 変換実装 (34-6.3) - `src/mir/join_ir_vm_bridge.rs`: MethodCall → BoxCall 変換 (+12 lines) - `src/mir/join_ir/json.rs`: MethodCall JSON シリアライゼーション (+16 lines) - `src/mir/join_ir_runner.rs`: MethodCall 未対応エラー (+7 lines) ### 4. テスト更新 (34-6.4) - `docs/.../fixtures/json_shape_read_value.program.json`: 本物の substring 構造 - `src/tests/joinir_frontend_if_select.rs`: run_joinir_via_vm 使用 - テスト成功: v="hello", at=3 → "hel" ✅ ## 成果 - ✅ テスト全通過(1 passed; 0 failed) - ✅ 設計原則確立: JoinIR = 構造 SSOT、意味論 = MIR レベル - ✅ Phase 33-10 原則との整合性: Method でも同じ原則適用 **ドキュメント更新**: CURRENT_TASK.md + TASKS.md(Phase 34-6 完了記録) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:05:46 +09:00
/// Phase 33: If/Else の単純な値選択(単一値)
/// cond が true なら then_val、false なら else_val を dst に代入
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>
2025-11-29 17:58:06 +09:00
///
/// Phase 63-3: type_hint で結果型を伝播infer_type_from_phi 削減用)
Select {
dst: VarId,
cond: VarId,
then_val: VarId,
else_val: VarId,
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>
2025-11-29 17:58:06 +09:00
/// Phase 63-3: 結果型ヒントMIR PHI 生成時の型推論を回避)
type_hint: Option<MirType>,
},
feat(joinir): Phase 34-6 MethodCall 構造と本物の substring 意味論 **Phase 34-6 実装完了**: MethodCall 構造を JoinIR に追加し、本物の substring 呼び出しを通すことに成功。 ## 主要変更 ### 1. MethodCall 構造追加 (34-6.1) - `src/mir/join_ir/mod.rs`: JoinInst::MethodCall バリアント (+8 lines) - 構造: `{ dst, receiver, method, args }` - 設計原則: JoinIR は構造のみ、意味論は MIR レベル ### 2. extract_value 更新 (34-6.2) - `src/mir/join_ir/frontend/ast_lowerer.rs`: Method 処理本物化 (+37 lines) - receiver/args を extract_value で再帰処理 - ダミー Const(0) 削除 → 本物の MethodCall 生成 - cond 処理修正: ValueId(0) ハードコード → extract_value で取得 ### 3. JoinIR→MIR 変換実装 (34-6.3) - `src/mir/join_ir_vm_bridge.rs`: MethodCall → BoxCall 変換 (+12 lines) - `src/mir/join_ir/json.rs`: MethodCall JSON シリアライゼーション (+16 lines) - `src/mir/join_ir_runner.rs`: MethodCall 未対応エラー (+7 lines) ### 4. テスト更新 (34-6.4) - `docs/.../fixtures/json_shape_read_value.program.json`: 本物の substring 構造 - `src/tests/joinir_frontend_if_select.rs`: run_joinir_via_vm 使用 - テスト成功: v="hello", at=3 → "hel" ✅ ## 成果 - ✅ テスト全通過(1 passed; 0 failed) - ✅ 設計原則確立: JoinIR = 構造 SSOT、意味論 = MIR レベル - ✅ Phase 33-10 原則との整合性: Method でも同じ原則適用 **ドキュメント更新**: CURRENT_TASK.md + TASKS.md(Phase 34-6 完了記録) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:05:46 +09:00
/// Phase 33-6: If/Else の複数変数 merge
/// cond が true なら各 dst に then_val を、false なら else_val を代入
/// 複数の PHI ノードを一括で表現する
IfMerge {
cond: VarId,
merges: Vec<MergePair>,
k_next: Option<JoinContId>,
},
/// Phase 34-6: メソッド呼び出し構造
/// receiver.method(args...) の構造を JoinIR で表現
/// 意味論BoxCall/Call への変換)は JoinIR→MIR ブリッジで実装
///
/// Phase 65-2-A: type_hint で戻り値型を伝播infer_type_from_phi 削減用)
feat(joinir): Phase 34-6 MethodCall 構造と本物の substring 意味論 **Phase 34-6 実装完了**: MethodCall 構造を JoinIR に追加し、本物の substring 呼び出しを通すことに成功。 ## 主要変更 ### 1. MethodCall 構造追加 (34-6.1) - `src/mir/join_ir/mod.rs`: JoinInst::MethodCall バリアント (+8 lines) - 構造: `{ dst, receiver, method, args }` - 設計原則: JoinIR は構造のみ、意味論は MIR レベル ### 2. extract_value 更新 (34-6.2) - `src/mir/join_ir/frontend/ast_lowerer.rs`: Method 処理本物化 (+37 lines) - receiver/args を extract_value で再帰処理 - ダミー Const(0) 削除 → 本物の MethodCall 生成 - cond 処理修正: ValueId(0) ハードコード → extract_value で取得 ### 3. JoinIR→MIR 変換実装 (34-6.3) - `src/mir/join_ir_vm_bridge.rs`: MethodCall → BoxCall 変換 (+12 lines) - `src/mir/join_ir/json.rs`: MethodCall JSON シリアライゼーション (+16 lines) - `src/mir/join_ir_runner.rs`: MethodCall 未対応エラー (+7 lines) ### 4. テスト更新 (34-6.4) - `docs/.../fixtures/json_shape_read_value.program.json`: 本物の substring 構造 - `src/tests/joinir_frontend_if_select.rs`: run_joinir_via_vm 使用 - テスト成功: v="hello", at=3 → "hel" ✅ ## 成果 - ✅ テスト全通過(1 passed; 0 failed) - ✅ 設計原則確立: JoinIR = 構造 SSOT、意味論 = MIR レベル - ✅ Phase 33-10 原則との整合性: Method でも同じ原則適用 **ドキュメント更新**: CURRENT_TASK.md + TASKS.md(Phase 34-6 完了記録) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:05:46 +09:00
MethodCall {
dst: VarId,
receiver: VarId,
method: String,
args: Vec<VarId>,
/// Phase 65-2-A: 戻り値型ヒントP3-A StringBox メソッド対応)
type_hint: Option<MirType>,
feat(joinir): Phase 34-6 MethodCall 構造と本物の substring 意味論 **Phase 34-6 実装完了**: MethodCall 構造を JoinIR に追加し、本物の substring 呼び出しを通すことに成功。 ## 主要変更 ### 1. MethodCall 構造追加 (34-6.1) - `src/mir/join_ir/mod.rs`: JoinInst::MethodCall バリアント (+8 lines) - 構造: `{ dst, receiver, method, args }` - 設計原則: JoinIR は構造のみ、意味論は MIR レベル ### 2. extract_value 更新 (34-6.2) - `src/mir/join_ir/frontend/ast_lowerer.rs`: Method 処理本物化 (+37 lines) - receiver/args を extract_value で再帰処理 - ダミー Const(0) 削除 → 本物の MethodCall 生成 - cond 処理修正: ValueId(0) ハードコード → extract_value で取得 ### 3. JoinIR→MIR 変換実装 (34-6.3) - `src/mir/join_ir_vm_bridge.rs`: MethodCall → BoxCall 変換 (+12 lines) - `src/mir/join_ir/json.rs`: MethodCall JSON シリアライゼーション (+16 lines) - `src/mir/join_ir_runner.rs`: MethodCall 未対応エラー (+7 lines) ### 4. テスト更新 (34-6.4) - `docs/.../fixtures/json_shape_read_value.program.json`: 本物の substring 構造 - `src/tests/joinir_frontend_if_select.rs`: run_joinir_via_vm 使用 - テスト成功: v="hello", at=3 → "hel" ✅ ## 成果 - ✅ テスト全通過(1 passed; 0 failed) - ✅ 設計原則確立: JoinIR = 構造 SSOT、意味論 = MIR レベル - ✅ Phase 33-10 原則との整合性: Method でも同じ原則適用 **ドキュメント更新**: CURRENT_TASK.md + TASKS.md(Phase 34-6 完了記録) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:05:46 +09:00
},
feat(joinir): Phase 56 ArrayExtBox.filter JoinIR lowering完全実装 ## Summary ArrayExtBox.filter/2 の JoinIR Frontend lowering を完全実装し、 ConditionalMethodCall 命令を導入して filter パターンに対応。 56 JoinIR テスト全て PASS(退行なし)。 ## Technical Changes ### 1. ConditionalMethodCall 命令追加 - **新規命令**: `if pred(v) { acc.push(v) }` パターン用 - **構造**: cond が true なら method 実行、false なら no-op - **MIR 変換**: 4ブロック構造 (cond→then/else→merge) ### 2. AST JSON 拡張 - Break/Continue/FunctionCall に "type" フィールド追加 - ArrayLiteral/MapLiteral に "type" フィールド追加 - JoinIR Frontend 互換性向上 ### 3. Expression Handler 拡張 - Unary 演算子(not, 負号)サポート - Call(変数関数呼び出し)を MethodCall に変換 ### 4. Loop Pattern Binding 修正 - `BoundExpr::Variable("n")` 問題修正 - `MethodCall { receiver: "arr", method: "size" }` に変更 - external_refs (arr, pred) を step 関数に伝播 ### 5. If Statement Handler 拡張 - 条件付き側効果パターン(ケース4)追加 - MethodCall/Method 形式の statement を ConditionalMethodCall に変換 ## Files Modified (10 files, +456/-45 lines) - ast_json.rs: AST JSON "type" フィールド追加 - loop_frontend_binding.rs: n バインディング修正 - control_flow.rs: external_refs params 追加 - loop_patterns.rs: external_refs step 関数伝播 - expr.rs: Unary, Call handler 追加 - stmt_handlers.rs: ConditionalMethodCall パターン追加 - mod.rs: ConditionalMethodCall, UnaryOp 定義 - json.rs: ConditionalMethodCall, UnaryOp シリアライズ - join_ir_runner.rs: ConditionalMethodCall, UnaryOp スタブ - convert.rs: ConditionalMethodCall → MIR 変換 ## Test Results - 56 JoinIR tests: ✅ PASSED - Regression: ❌ None - ArrayExtBox.filter/2: ✅ JoinIR lowering 成功 ## Milestone JoinIR 2ループ完走達成: - ✅ JsonTokenizer.print_tokens/0 - ✅ ArrayExtBox.filter/2 (NEW!) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 06:51:43 +09:00
/// Phase 56: 条件付きメソッド呼び出しfilter パターン用)
/// cond が true の場合のみ receiver.method(args) を実行
/// cond が false の場合は dst = receiver変更なし
///
/// 使用例: `if pred(v) { acc.push(v) }` → ConditionalMethodCall
ConditionalMethodCall {
cond: VarId,
dst: VarId,
receiver: VarId,
method: String,
args: Vec<VarId>,
},
/// Phase 51: フィールドアクセス
/// object.field の構造を JoinIR で表現
/// MIR 変換時に Load 命令に変換
FieldAccess {
dst: VarId,
object: VarId,
field: String,
},
/// Phase 51: Box インスタンス生成
/// new BoxName(args...) の構造を JoinIR で表現
/// MIR 変換時に NewBox 命令に変換
///
/// Phase 65-2-B: type_hint で生成される Box 型を伝播infer_type_from_phi 削減用)
NewBox {
dst: VarId,
box_name: String,
args: Vec<VarId>,
/// Phase 65-2-B: 生成される Box の型ヒントP3-B Box コンストラクタ対応)
type_hint: Option<MirType>,
},
/// Phase 41-4: 深いネスト if の複数変数 mergeelse なし)
///
/// # Pattern
/// ```text
/// if cond1 {
/// if cond2 {
/// if cond3 {
/// x = new_val // modifications only at deepest level
/// }
/// }
/// }
/// // merge: x = phi(new_val if all conds true, original otherwise)
/// ```
///
/// # Semantics
/// - `conds`: 外側から内側への条件リスト
/// - `merges`: 最深レベルでの変数更新
/// - then_val: 全ての conds が true の場合の値
/// - else_val: いずれかの cond が false の場合の値(元の値)
/// - MIR 変換時に多段 Branch + PHI を生成
///
/// # Target
/// ParserControlBox.parse_loop() の 4 レベルネスト if パターン
NestedIfMerge {
/// 条件リスト(外側から内側へ)
conds: Vec<VarId>,
/// 変数更新(全条件 true 時 → then_val、いずれか false 時 → else_val
merges: Vec<MergePair>,
/// merge 後の継続
k_next: Option<JoinContId>,
},
/// それ以外の演算は、現行 MIR の算術/比較/boxcall を再利用
Compute(MirLikeInst),
}
/// MIR からの算術・比較命令のラッパーPhase 26-H では最小限)
#[derive(Debug, Clone)]
pub enum MirLikeInst {
/// 定数代入
Const { dst: VarId, value: ConstValue },
/// 二項演算
BinOp {
dst: VarId,
op: BinOpKind,
lhs: VarId,
rhs: VarId,
},
/// 比較演算
Compare {
dst: VarId,
op: CompareOp,
lhs: VarId,
rhs: VarId,
},
/// Box呼び出し将来的には統一 Call に統合予定)
BoxCall {
dst: Option<VarId>,
box_name: String,
method: String,
args: Vec<VarId>,
},
feat(joinir): Phase 56 ArrayExtBox.filter JoinIR lowering完全実装 ## Summary ArrayExtBox.filter/2 の JoinIR Frontend lowering を完全実装し、 ConditionalMethodCall 命令を導入して filter パターンに対応。 56 JoinIR テスト全て PASS(退行なし)。 ## Technical Changes ### 1. ConditionalMethodCall 命令追加 - **新規命令**: `if pred(v) { acc.push(v) }` パターン用 - **構造**: cond が true なら method 実行、false なら no-op - **MIR 変換**: 4ブロック構造 (cond→then/else→merge) ### 2. AST JSON 拡張 - Break/Continue/FunctionCall に "type" フィールド追加 - ArrayLiteral/MapLiteral に "type" フィールド追加 - JoinIR Frontend 互換性向上 ### 3. Expression Handler 拡張 - Unary 演算子(not, 負号)サポート - Call(変数関数呼び出し)を MethodCall に変換 ### 4. Loop Pattern Binding 修正 - `BoundExpr::Variable("n")` 問題修正 - `MethodCall { receiver: "arr", method: "size" }` に変更 - external_refs (arr, pred) を step 関数に伝播 ### 5. If Statement Handler 拡張 - 条件付き側効果パターン(ケース4)追加 - MethodCall/Method 形式の statement を ConditionalMethodCall に変換 ## Files Modified (10 files, +456/-45 lines) - ast_json.rs: AST JSON "type" フィールド追加 - loop_frontend_binding.rs: n バインディング修正 - control_flow.rs: external_refs params 追加 - loop_patterns.rs: external_refs step 関数伝播 - expr.rs: Unary, Call handler 追加 - stmt_handlers.rs: ConditionalMethodCall パターン追加 - mod.rs: ConditionalMethodCall, UnaryOp 定義 - json.rs: ConditionalMethodCall, UnaryOp シリアライズ - join_ir_runner.rs: ConditionalMethodCall, UnaryOp スタブ - convert.rs: ConditionalMethodCall → MIR 変換 ## Test Results - 56 JoinIR tests: ✅ PASSED - Regression: ❌ None - ArrayExtBox.filter/2: ✅ JoinIR lowering 成功 ## Milestone JoinIR 2ループ完走達成: - ✅ JsonTokenizer.print_tokens/0 - ✅ ArrayExtBox.filter/2 (NEW!) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 06:51:43 +09:00
/// Phase 56: 単項演算not, 負号)
UnaryOp {
dst: VarId,
op: UnaryOp,
operand: VarId,
},
/// Phase 188: Print 文(コンソール出力)
/// print(value) の構造を JoinIR で表現
/// MIR 変換時に Print 命令に変換
Print { value: VarId },
feat(joinir): Phase 188-Impl-3 Pattern 3 (Loop with If-Else PHI) implementation Add Pattern 3 lowerer for `loop { if cond { x = a } else { x = b } ... }` pattern. New files: - loop_with_if_phi_minimal.rs (381 lines): JoinIR lowerer for Pattern 3 - Multiple loop variables (counter + accumulator) - In-loop if/else PHI using Select instruction - Carriers passed to next iteration via tail recursion Modified files: - join_ir/mod.rs: Add Mod to BinOpKind, Select to MirLikeInst - loop_pattern_detection.rs: Add is_loop_with_conditional_phi_pattern() detection - lowering/mod.rs: Pattern 3 router integration - loop_patterns.rs: Pattern 3 entry point delegation - json.rs: Mod/Select JSON serialization - join_ir_ops.rs: Mod operation evaluation (a % b) - join_ir_runner.rs: Select instruction execution - join_ir_vm_bridge/convert.rs: Mod/Select conversion handlers Implementation: - Pattern 3 generates 3 JoinIR functions: main, loop_step(i, sum), k_exit(sum_final) - Exit condition: !(i <= 5) with Jump to k_exit - In-loop if/else: if (i % 2 == 1) { sum + i } else { sum + 0 } - Select instruction: sum_new = Select(if_cond, sum_then, sum_else) - Both carriers updated: Call(loop_step, [i_next, sum_new]) Build status: ✅ Compiles successfully (0 errors, 34 warnings) Integration: Infrastructure complete, MIR boundary mapping pending All 3 patterns now have lowering infrastructure in place for Phase 188. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 15:45:42 +09:00
/// Phase 188-Impl-3: 条件付き値選択(三項演算子)
/// cond が true なら then_val を、false なら else_val を dst に代入
/// JoinIR の Select 命令と同じ semantics
Select {
dst: VarId,
cond: VarId,
then_val: VarId,
else_val: VarId,
},
feat(joinir): Phase 56 ArrayExtBox.filter JoinIR lowering完全実装 ## Summary ArrayExtBox.filter/2 の JoinIR Frontend lowering を完全実装し、 ConditionalMethodCall 命令を導入して filter パターンに対応。 56 JoinIR テスト全て PASS(退行なし)。 ## Technical Changes ### 1. ConditionalMethodCall 命令追加 - **新規命令**: `if pred(v) { acc.push(v) }` パターン用 - **構造**: cond が true なら method 実行、false なら no-op - **MIR 変換**: 4ブロック構造 (cond→then/else→merge) ### 2. AST JSON 拡張 - Break/Continue/FunctionCall に "type" フィールド追加 - ArrayLiteral/MapLiteral に "type" フィールド追加 - JoinIR Frontend 互換性向上 ### 3. Expression Handler 拡張 - Unary 演算子(not, 負号)サポート - Call(変数関数呼び出し)を MethodCall に変換 ### 4. Loop Pattern Binding 修正 - `BoundExpr::Variable("n")` 問題修正 - `MethodCall { receiver: "arr", method: "size" }` に変更 - external_refs (arr, pred) を step 関数に伝播 ### 5. If Statement Handler 拡張 - 条件付き側効果パターン(ケース4)追加 - MethodCall/Method 形式の statement を ConditionalMethodCall に変換 ## Files Modified (10 files, +456/-45 lines) - ast_json.rs: AST JSON "type" フィールド追加 - loop_frontend_binding.rs: n バインディング修正 - control_flow.rs: external_refs params 追加 - loop_patterns.rs: external_refs step 関数伝播 - expr.rs: Unary, Call handler 追加 - stmt_handlers.rs: ConditionalMethodCall パターン追加 - mod.rs: ConditionalMethodCall, UnaryOp 定義 - json.rs: ConditionalMethodCall, UnaryOp シリアライズ - join_ir_runner.rs: ConditionalMethodCall, UnaryOp スタブ - convert.rs: ConditionalMethodCall → MIR 変換 ## Test Results - 56 JoinIR tests: ✅ PASSED - Regression: ❌ None - ArrayExtBox.filter/2: ✅ JoinIR lowering 成功 ## Milestone JoinIR 2ループ完走達成: - ✅ JsonTokenizer.print_tokens/0 - ✅ ArrayExtBox.filter/2 (NEW!) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 06:51:43 +09:00
}
/// Phase 56: 単項演算種別
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UnaryOp {
/// 論理否定
Not,
/// 算術否定(負号)
Neg,
}
/// 定数値MIR の ConstValue を簡略化)
#[derive(Debug, Clone)]
pub enum ConstValue {
Integer(i64),
Bool(bool),
String(String),
Null,
}
/// 二項演算種別
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BinOpKind {
Add,
Sub,
Mul,
Div,
feat(joinir): Phase 188-Impl-3 Pattern 3 (Loop with If-Else PHI) implementation Add Pattern 3 lowerer for `loop { if cond { x = a } else { x = b } ... }` pattern. New files: - loop_with_if_phi_minimal.rs (381 lines): JoinIR lowerer for Pattern 3 - Multiple loop variables (counter + accumulator) - In-loop if/else PHI using Select instruction - Carriers passed to next iteration via tail recursion Modified files: - join_ir/mod.rs: Add Mod to BinOpKind, Select to MirLikeInst - loop_pattern_detection.rs: Add is_loop_with_conditional_phi_pattern() detection - lowering/mod.rs: Pattern 3 router integration - loop_patterns.rs: Pattern 3 entry point delegation - json.rs: Mod/Select JSON serialization - join_ir_ops.rs: Mod operation evaluation (a % b) - join_ir_runner.rs: Select instruction execution - join_ir_vm_bridge/convert.rs: Mod/Select conversion handlers Implementation: - Pattern 3 generates 3 JoinIR functions: main, loop_step(i, sum), k_exit(sum_final) - Exit condition: !(i <= 5) with Jump to k_exit - In-loop if/else: if (i % 2 == 1) { sum + i } else { sum + 0 } - Select instruction: sum_new = Select(if_cond, sum_then, sum_else) - Both carriers updated: Call(loop_step, [i_next, sum_new]) Build status: ✅ Compiles successfully (0 errors, 34 warnings) Integration: Infrastructure complete, MIR boundary mapping pending All 3 patterns now have lowering infrastructure in place for Phase 188. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 15:45:42 +09:00
Mod, // Phase 188-Impl-3: 剰余演算 (a % b)
Or, // Phase 27.1: 論理OR (bool || bool)
And, // Phase 27.1: 論理AND (bool && bool)
}
/// 比較演算種別
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompareOp {
Lt,
Le,
Gt,
Ge,
Eq,
Ne,
}
/// JoinIR モジュール(複数の関数を保持)
#[derive(Debug, Clone)]
pub struct JoinModule {
/// 関数マップ
pub functions: BTreeMap<JoinFuncId, JoinFunction>,
/// エントリーポイント関数ID
pub entry: Option<JoinFuncId>,
/// JoinIR のフェーズ(構造化 / 正規化)
pub phase: JoinIrPhase,
}
impl JoinModule {
pub fn new() -> Self {
Self {
functions: BTreeMap::new(),
entry: None,
phase: JoinIrPhase::Structured,
}
}
pub fn add_function(&mut self, func: JoinFunction) {
self.functions.insert(func.id, func);
}
pub fn is_structured(&self) -> bool {
self.phase == JoinIrPhase::Structured
}
pub fn is_normalized(&self) -> bool {
self.phase == JoinIrPhase::Normalized
}
pub fn mark_normalized(&mut self) {
self.phase = JoinIrPhase::Normalized;
}
feat(llvm): Phase 132 - Pattern 1 exit value parity fix + Box-First refactoring ## Phase 132: Exit PHI Value Parity Fix ### Problem Pattern 1 (Simple While) returned 0 instead of final loop variable value (3) - VM: RC: 3 ✅ (correct) - LLVM: Result: 0 ❌ (wrong) ### Root Cause (Two Layers) 1. **JoinIR/Boundary**: Missing exit_bindings → ExitLineReconnector not firing 2. **LLVM Python**: block_end_values snapshot dropping PHI values ### Fix **JoinIR** (simple_while_minimal.rs): - Jump(k_exit, [i_param]) passes exit value **Boundary** (pattern1_minimal.rs): - Added LoopExitBinding with carrier_name="i", role=LoopState - Enables ExitLineReconnector to update variable_map **LLVM** (block_lower.py): - Use predeclared_ret_phis for reliable PHI filtering - Protect builder.vmap PHIs from overwrites (SSOT principle) ### Result - ✅ VM: RC: 3 - ✅ LLVM: Result: 3 - ✅ VM/LLVM parity achieved ## Phase 132-Post: Box-First Refactoring ### Rust Side **JoinModule::require_function()** (mod.rs): - Encapsulate function search logic - 10 lines → 1 line (90% reduction) - Reusable for Pattern 2-5 ### Python Side **PhiManager Box** (phi_manager.py - new): - Centralized PHI lifecycle management - 47 lines → 8 lines (83% reduction) - SSOT: builder.vmap owns PHIs - Fail-Fast: No silent overwrites **Integration**: - LLVMBuilder: Added phi_manager - block_lower.py: Delegated to PhiManager - tagging.py: Register PHIs with manager ### Documentation **New Files**: - docs/development/architecture/exit-phi-design.md - docs/development/current/main/investigations/phase132-llvm-exit-phi-wrong-result.md - docs/development/current/main/phases/phase-132/ **Updated**: - docs/development/current/main/10-Now.md - docs/development/current/main/phase131-3-llvm-lowering-inventory.md ### Design Principles - Box-First: Logic encapsulated in classes/methods - SSOT: Single Source of Truth (builder.vmap for PHIs) - Fail-Fast: Early explicit failures, no fallbacks - Separation of Concerns: 3-layer architecture 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 03:17:31 +09:00
// Phase 132-Post: Box-First principle - encapsulate function search logic
/// Find function by name
pub fn get_function_by_name(&self, name: &str) -> Option<&JoinFunction> {
self.functions.values().find(|f| f.name == name)
}
/// Find function by name or panic with descriptive message
pub fn require_function(&self, name: &str, context: &str) -> &JoinFunction {
self.get_function_by_name(name)
.unwrap_or_else(|| panic!("{}: missing required function '{}'", context, name))
}
}
impl Default for JoinModule {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_join_function_creation() {
let func_id = JoinFuncId::new(0);
let func = JoinFunction::new(
func_id,
"test_func".to_string(),
vec![ValueId(1), ValueId(2)],
);
assert_eq!(func.id, func_id);
assert_eq!(func.name, "test_func");
assert_eq!(func.params.len(), 2);
assert_eq!(func.body.len(), 0);
assert_eq!(func.exit_cont, None);
}
#[test]
fn test_join_module() {
let mut module = JoinModule::new();
let func = JoinFunction::new(JoinFuncId::new(0), "main".to_string(), vec![]);
module.add_function(func);
assert_eq!(module.functions.len(), 1);
assert!(module.functions.contains_key(&JoinFuncId::new(0)));
assert_eq!(module.phase, JoinIrPhase::Structured);
assert!(module.is_structured());
}
#[test]
fn test_mark_normalized() {
let mut module = JoinModule::new();
assert!(module.is_structured());
module.mark_normalized();
assert!(module.is_normalized());
}
#[test]
fn loop_header_shape_params_order_is_pinned_then_carrier() {
// Phase 27.4-A: to_loop_step_params() が pinned→carriers の順を返すことを保証
let v1 = ValueId(1);
let v2 = ValueId(2);
let v3 = ValueId(3);
let shape = LoopHeaderShape::new_manual(vec![v1, v2], vec![v3]);
let params = shape.to_loop_step_params();
assert_eq!(params, vec![v1, v2, v3]);
}
}