feat(joinir): Phase 200-A ConditionEnv extension infrastructure

Added type and skeleton infrastructure for function-scoped variable
capture, preparing for Phase 200-B integration with ConditionEnv.

New Types:
- CapturedVar: { name, host_id, is_immutable }
- CapturedEnv: Collection of captured variables
- ParamRole: { LoopParam, Condition, Carrier, ExprResult }

New Functions (Skeletons):
- analyze_captured_vars(): Detects function-scoped "constants"
- build_with_captures(): ConditionEnvBuilder v2 entry point
- add_param_with_role(): Role-based parameter routing

New File:
- src/mir/loop_pattern_detection/function_scope_capture.rs

Design Principles:
- Infra only: Types and skeletons, no behavior changes
- Existing behavior maintained: All current loops work identically
- Box-first: New responsibilities in new file
- Documentation: Future implementation plans in code comments

Test Results:
- 6 new unit tests (function_scope_capture: 3, param_role: 3)
- All 804 existing tests PASS (0 regressions)

Next: Phase 200-B (actual capture detection and integration)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-09 16:19:08 +09:00
parent f47fa9a7a8
commit 3a9b44c4e2
7 changed files with 914 additions and 1 deletions

View File

@ -27,6 +27,8 @@
use crate::ast::ASTNode;
use crate::mir::join_ir::lowering::condition_env::{ConditionBinding, ConditionEnv};
use crate::mir::join_ir::lowering::condition_to_joinir::extract_condition_variables;
use crate::mir::join_ir::lowering::inline_boundary_builder::JoinInlineBoundaryBuilder;
use crate::mir::loop_pattern_detection::function_scope_capture::CapturedEnv;
use crate::mir::ValueId;
use std::collections::BTreeMap;
@ -122,6 +124,64 @@ impl ConditionEnvBuilder {
env.insert(loop_var_name.to_string(), ValueId(0));
env
}
/// Build ConditionEnv with optional captured variables (Phase 200-A v2 entry point)
///
/// # Phase 200-A Status
///
/// Currently ignores `captured` parameter and delegates to existing implementation.
/// Integration with CapturedEnv will be implemented in Phase 200-B.
///
/// # Future Behavior (Phase 200-B+)
///
/// - Add captured variables to ConditionEnv
/// - Generate condition_bindings for captured vars in boundary
/// - Track captured vars separately from loop params
/// - Ensure captured vars do NOT participate in header PHI or exit_bindings
///
/// # Arguments
///
/// * `loop_var_name` - Loop parameter name (e.g., "i", "pos")
/// * `_captured` - Function-scoped captured variables (Phase 200-B+)
/// * `_boundary` - Boundary builder for adding condition_bindings (Phase 200-B+)
///
/// # Returns
///
/// ConditionEnv with loop parameter mapping (Phase 200-A: same as build_loop_param_only)
///
/// # Example (Future Phase 200-B)
///
/// ```ignore
/// let captured = analyze_captured_vars(fn_body, loop_ast, scope);
/// let mut boundary = JoinInlineBoundaryBuilder::new();
/// let env = ConditionEnvBuilder::build_with_captures(
/// "pos",
/// &captured, // Contains "digits" with host ValueId(42)
/// &mut boundary,
/// );
/// // Phase 200-B: env will contain "pos" → ValueId(0), "digits" → ValueId(1)
/// // Phase 200-B: boundary.condition_bindings will have entry for "digits"
/// ```
pub fn build_with_captures(
loop_var_name: &str,
_captured: &CapturedEnv,
_boundary: &mut JoinInlineBoundaryBuilder,
) -> ConditionEnv {
// Phase 200-A: Delegate to existing implementation
// TODO(Phase 200-B): Integrate captured vars into ConditionEnv
//
// Integration steps:
// 1. Start with loop parameter in env (ValueId(0))
// 2. For each captured var:
// a. Allocate JoinIR-local ValueId (starting from 1)
// b. Add to ConditionEnv (var.name → join_id)
// c. Add to boundary.condition_bindings (host_id ↔ join_id)
// d. Mark as ParamRole::Condition (not Carrier or LoopParam)
// 3. Ensure captured vars are NOT in exit_bindings (condition-only)
// 4. Return populated ConditionEnv
Self::build_loop_param_only(loop_var_name)
}
}
#[cfg(test)]