2025-09-19 08:34:29 +09:00
|
|
|
//! Control-flow entrypoints (if/loop/try/throw) centralized here.
|
2025-12-05 20:41:19 +09:00
|
|
|
//!
|
|
|
|
|
//! This module is being modularized in phases:
|
2025-12-05 20:45:23 +09:00
|
|
|
//! - Phase 1: Debug utilities (debug.rs) ✅
|
|
|
|
|
//! - Phase 2: Pattern lowerers (joinir/patterns/) ✅
|
2025-12-05 20:48:31 +09:00
|
|
|
//! - Phase 3: JoinIR routing (joinir/routing.rs) ✅
|
2025-12-05 21:05:03 +09:00
|
|
|
//! - Phase 4: Merge implementation (joinir/merge/) ✅
|
|
|
|
|
//! - Phase 5: Exception handling (exception/) ✅
|
2025-12-05 21:06:58 +09:00
|
|
|
//! - Phase 6: Utility functions (utils.rs) ✅
|
2025-12-05 20:41:19 +09:00
|
|
|
|
2025-12-05 21:05:03 +09:00
|
|
|
use super::ValueId;
|
2025-11-29 06:51:43 +09:00
|
|
|
use crate::ast::ASTNode;
|
2025-09-19 08:34:29 +09:00
|
|
|
|
2025-12-05 20:41:19 +09:00
|
|
|
// Phase 1: Debug utilities
|
|
|
|
|
pub(in crate::mir::builder) mod debug;
|
2025-12-05 19:35:30 +09:00
|
|
|
|
2025-12-05 21:05:03 +09:00
|
|
|
// Phase 2-4: JoinIR integration (patterns, routing, merge)
|
2025-12-05 20:45:23 +09:00
|
|
|
pub(in crate::mir::builder) mod joinir;
|
|
|
|
|
|
2025-12-05 21:05:03 +09:00
|
|
|
// Phase 5: Exception handling
|
|
|
|
|
pub(in crate::mir::builder) mod exception;
|
|
|
|
|
|
2025-12-05 21:06:58 +09:00
|
|
|
// Phase 6: Utility functions
|
|
|
|
|
pub(in crate::mir::builder) mod utils;
|
|
|
|
|
|
2025-12-05 20:41:19 +09:00
|
|
|
impl super::MirBuilder {
|
2025-09-19 08:34:29 +09:00
|
|
|
/// Control-flow: block
|
|
|
|
|
pub(super) fn cf_block(&mut self, statements: Vec<ASTNode>) -> Result<ValueId, String> {
|
|
|
|
|
// identical to build_block; kept here for future policy hooks
|
|
|
|
|
self.build_block(statements)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Control-flow: if
|
2025-12-04 06:17:10 +09:00
|
|
|
///
|
2025-12-04 06:29:54 +09:00
|
|
|
/// # Phase 124: JoinIR-Only (hako_check専用化完了)
|
2025-12-04 06:17:10 +09:00
|
|
|
///
|
2025-12-04 06:29:54 +09:00
|
|
|
/// If statements are now always routed through the canonical lowering path
|
|
|
|
|
/// (lower_if_form), which internally uses JoinIR-based PHI generation.
|
2025-12-04 06:17:10 +09:00
|
|
|
///
|
2025-12-04 06:29:54 +09:00
|
|
|
/// Phase 123 の環境変数による分岐は削除済み。
|
2025-09-19 08:34:29 +09:00
|
|
|
pub(super) fn cf_if(
|
|
|
|
|
&mut self,
|
|
|
|
|
condition: ASTNode,
|
|
|
|
|
then_branch: ASTNode,
|
|
|
|
|
else_branch: Option<ASTNode>,
|
|
|
|
|
) -> Result<ValueId, String> {
|
2025-12-04 06:29:54 +09:00
|
|
|
// Phase 124: JoinIR-only path (環境変数分岐削除)
|
|
|
|
|
// lower_if_form は JoinIR ベースの PHI 生成を使用
|
2025-09-19 08:34:29 +09:00
|
|
|
self.lower_if_form(condition, then_branch, else_branch)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Control-flow: loop
|
2025-11-28 19:12:59 +09:00
|
|
|
///
|
|
|
|
|
/// # Phase 49: JoinIR Frontend Mainline Integration
|
|
|
|
|
///
|
2025-11-28 20:12:39 +09:00
|
|
|
/// This is the unified entry point for all loop lowering. Specific functions
|
|
|
|
|
/// are routed through JoinIR Frontend instead of the traditional LoopBuilder path
|
2025-12-01 11:10:46 +09:00
|
|
|
/// when enabled via dev flags (Phase 49) or Core policy (Phase 80):
|
2025-11-28 20:12:39 +09:00
|
|
|
///
|
2025-12-01 11:10:46 +09:00
|
|
|
/// - Core ON (`joinir_core_enabled()`): print_tokens / ArrayExt.filter はまず JoinIR Frontend を試す
|
|
|
|
|
/// - Dev フラグ(既存):
|
|
|
|
|
/// - `HAKO_JOINIR_PRINT_TOKENS_MAIN=1`: JsonTokenizer.print_tokens/0
|
|
|
|
|
/// - `HAKO_JOINIR_ARRAY_FILTER_MAIN=1`: ArrayExtBox.filter/2
|
2025-11-28 20:12:39 +09:00
|
|
|
///
|
|
|
|
|
/// Note: Arity does NOT include implicit `me` receiver.
|
2025-09-19 08:34:29 +09:00
|
|
|
pub(super) fn cf_loop(
|
|
|
|
|
&mut self,
|
|
|
|
|
condition: ASTNode,
|
|
|
|
|
body: Vec<ASTNode>,
|
|
|
|
|
) -> Result<ValueId, String> {
|
2025-12-01 11:10:46 +09:00
|
|
|
// Phase 49/80: Try JoinIR Frontend route for mainline targets
|
2025-11-28 19:12:59 +09:00
|
|
|
if let Some(result) = self.try_cf_loop_joinir(&condition, &body)? {
|
|
|
|
|
return Ok(result);
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-18 06:39:45 +09:00
|
|
|
if std::env::var("NYASH_LOOPFORM_DEBUG").is_ok() {
|
|
|
|
|
eprintln!("[cf_loop] CALLED from somewhere");
|
|
|
|
|
eprintln!("[cf_loop] Current stack (simulated): check build_statement vs build_expression_impl");
|
|
|
|
|
}
|
2025-12-04 23:35:33 +09:00
|
|
|
|
2025-12-04 23:51:49 +09:00
|
|
|
// Phase 186: LoopBuilder Hard Freeze - Legacy path disabled
|
|
|
|
|
// Phase 187-2: LoopBuilder module removed - all loops must use JoinIR
|
|
|
|
|
return Err(format!(
|
|
|
|
|
"[joinir/freeze] Loop lowering failed: JoinIR does not support this pattern, and LoopBuilder has been removed.\n\
|
|
|
|
|
Function: {}\n\
|
|
|
|
|
Hint: This loop pattern is not supported. All loops must use JoinIR lowering.",
|
|
|
|
|
self.current_function.as_ref().map(|f| f.signature.name.as_str()).unwrap_or("<unknown>")
|
|
|
|
|
));
|
2025-09-19 08:34:29 +09:00
|
|
|
}
|
|
|
|
|
|
2025-11-28 19:12:59 +09:00
|
|
|
/// Phase 49: Try JoinIR Frontend for mainline integration
|
|
|
|
|
///
|
|
|
|
|
/// Returns `Ok(Some(value))` if the current function should use JoinIR Frontend,
|
|
|
|
|
/// `Ok(None)` to fall through to the legacy LoopBuilder path.
|
2025-11-28 20:12:39 +09:00
|
|
|
///
|
|
|
|
|
/// # Phase 49-4: Multi-target support
|
|
|
|
|
///
|
|
|
|
|
/// Targets are enabled via separate dev flags:
|
|
|
|
|
/// - `HAKO_JOINIR_PRINT_TOKENS_MAIN=1`: JsonTokenizer.print_tokens/0
|
|
|
|
|
/// - `HAKO_JOINIR_ARRAY_FILTER_MAIN=1`: ArrayExtBox.filter/2
|
|
|
|
|
///
|
|
|
|
|
/// Note: Arity in function names does NOT include implicit `me` receiver.
|
|
|
|
|
/// - Instance method `print_tokens()` → `/0` (no explicit params)
|
|
|
|
|
/// - Static method `filter(arr, pred)` → `/2` (two params)
|
2025-12-05 16:04:15 +09:00
|
|
|
|
2025-11-28 19:45:23 +09:00
|
|
|
/// Phase 49-3.2: Merge JoinIR-generated MIR blocks into current_function
|
2025-11-28 19:29:45 +09:00
|
|
|
///
|
2025-12-05 21:00:55 +09:00
|
|
|
/// **Phase 4 Refactoring Complete**: This function now delegates to the modular
|
|
|
|
|
/// merge implementation in `joinir::merge::merge_joinir_mir_blocks()`.
|
|
|
|
|
///
|
|
|
|
|
/// The original 714-line implementation has been broken down into 6 focused modules:
|
|
|
|
|
/// 1. block_allocator.rs - Block ID allocation
|
|
|
|
|
/// 2. value_collector.rs - Value collection
|
|
|
|
|
/// 3. ID remapping (using JoinIrIdRemapper)
|
|
|
|
|
/// 4. instruction_rewriter.rs - Instruction rewriting
|
|
|
|
|
/// 5. exit_phi_builder.rs - Exit PHI construction
|
|
|
|
|
/// 6. Boundary reconnection (in merge/mod.rs)
|
2025-11-28 19:29:45 +09:00
|
|
|
fn merge_joinir_mir_blocks(
|
|
|
|
|
&mut self,
|
|
|
|
|
mir_module: &crate::mir::MirModule,
|
2025-12-05 13:46:44 +09:00
|
|
|
boundary: Option<&crate::mir::join_ir::lowering::inline_boundary::JoinInlineBoundary>,
|
2025-11-28 19:29:45 +09:00
|
|
|
debug: bool,
|
2025-12-05 19:27:52 +09:00
|
|
|
) -> Result<Option<ValueId>, String> {
|
2025-12-05 21:00:55 +09:00
|
|
|
// Phase 4: Delegate to modular implementation
|
|
|
|
|
joinir::merge::merge_joinir_mir_blocks(self, mir_module, boundary, debug)
|
2025-11-28 19:12:59 +09:00
|
|
|
}
|
|
|
|
|
|
2025-09-19 08:34:29 +09:00
|
|
|
/// Control-flow: try/catch/finally
|
2025-12-05 21:05:03 +09:00
|
|
|
///
|
|
|
|
|
/// Delegates to exception::cf_try_catch for implementation.
|
2025-09-19 08:34:29 +09:00
|
|
|
pub(super) fn cf_try_catch(
|
|
|
|
|
&mut self,
|
|
|
|
|
try_body: Vec<ASTNode>,
|
|
|
|
|
catch_clauses: Vec<crate::ast::CatchClause>,
|
|
|
|
|
finally_body: Option<Vec<ASTNode>>,
|
|
|
|
|
) -> Result<ValueId, String> {
|
2025-12-05 21:05:03 +09:00
|
|
|
exception::cf_try_catch(self, try_body, catch_clauses, finally_body)
|
2025-09-19 08:34:29 +09:00
|
|
|
}
|
|
|
|
|
|
2025-12-05 13:03:48 +09:00
|
|
|
/// Phase 188-Impl-2: Extract loop variable name from condition
|
|
|
|
|
///
|
|
|
|
|
/// For `i < 3`, extracts `i`.
|
|
|
|
|
/// For `arr.length() > 0`, extracts `arr`.
|
|
|
|
|
///
|
2025-12-05 21:06:58 +09:00
|
|
|
/// Delegates to utils::extract_loop_variable_from_condition for implementation.
|
2025-12-05 13:03:48 +09:00
|
|
|
fn extract_loop_variable_from_condition(&self, condition: &ASTNode) -> Result<String, String> {
|
2025-12-05 21:06:58 +09:00
|
|
|
utils::extract_loop_variable_from_condition(condition)
|
2025-12-05 13:03:48 +09:00
|
|
|
}
|
|
|
|
|
|
2025-09-19 08:34:29 +09:00
|
|
|
/// Control-flow: throw
|
2025-12-05 21:05:03 +09:00
|
|
|
///
|
|
|
|
|
/// Delegates to exception::cf_throw for implementation.
|
2025-09-19 08:34:29 +09:00
|
|
|
pub(super) fn cf_throw(&mut self, expression: ASTNode) -> Result<ValueId, String> {
|
2025-12-05 21:05:03 +09:00
|
|
|
exception::cf_throw(self, expression)
|
2025-09-19 08:34:29 +09:00
|
|
|
}
|
|
|
|
|
}
|