feat(joinir): Phase 200-B/C/D capture analysis + Phase 201-A reserved_value_ids infra

Phase 200-B: FunctionScopeCaptureAnalyzer implementation
- analyze_captured_vars_v2() with structural loop matching
- CapturedEnv for immutable function-scope variables
- ParamRole::Condition for condition-only variables

Phase 200-C: ConditionEnvBuilder extension
- build_with_captures() integrates CapturedEnv into ConditionEnv
- fn_body propagation through LoopPatternContext to Pattern 2

Phase 200-D: E2E verification
- capture detection working for base, limit, n etc.
- Test files: phase200d_capture_minimal.hako, phase200d_capture_in_condition.hako

Phase 201-A: MirBuilder reserved_value_ids infrastructure
- reserved_value_ids: HashSet<ValueId> field in MirBuilder
- next_value_id() skips reserved IDs
- merge/mod.rs sets/clears reserved IDs around JoinIR merge

Phase 201: JoinValueSpace design document
- Param/Local/PHI disjoint regions design
- API: alloc_param(), alloc_local(), reserve_phi()
- Migration plan for Pattern 1-4 lowerers

🤖 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 18:32:03 +09:00
parent 3a9b44c4e2
commit 32a91e31ac
24 changed files with 2815 additions and 193 deletions

View File

@ -156,6 +156,17 @@ pub struct MirBuilder {
/// - NYASH_REGION_TRACE=1 のときだけ使われる開発用メタデータだよ。
pub(super) current_region_stack: Vec<RegionId>,
/// Phase 200-C: Original function body AST for capture analysis
/// Stored temporarily during function lowering to support FunctionScopeCaptureAnalyzer.
/// None when not lowering a function, or when fn_body is not available.
pub(super) fn_body_ast: Option<Vec<ASTNode>>,
/// Phase 201-A: Reserved ValueIds that must not be allocated
/// These are PHI dst ValueIds created by LoopHeaderPhiBuilder.
/// When next_value_id() encounters a reserved ID, it skips to the next.
/// Cleared after JoinIR merge completes.
pub(super) reserved_value_ids: HashSet<ValueId>,
// include guards removed
/// Loop context stacks for lowering break/continue inside nested control flow
/// Top of stack corresponds to the innermost active loop
@ -273,6 +284,8 @@ impl MirBuilder {
method_tail_index_source_len: 0,
current_region_stack: Vec::new(),
fn_body_ast: None, // Phase 200-C: Initialize to None
reserved_value_ids: HashSet::new(), // Phase 201-A: Initialize to empty
loop_header_stack: Vec::new(),
loop_exit_stack: Vec::new(),