feat(joinir): Phase 191 body-local init integration into Pattern2
- Integrated LoopBodyLocalInitLowerer into Pattern2 lowering - Fixed ValueId double-allocation issue (delegate to InitLowerer) - Added body_ast parameter to lower_loop_with_break_minimal() - Fixed json_program_loop.rs test for body-local scope - New test: phase191_body_local_atoi.hako (expected: 123) Supported init expressions: - Integer literals, variable references, binary operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -154,16 +154,13 @@ impl MirBuilder {
|
||||
id
|
||||
};
|
||||
|
||||
// Phase 185-2: Collect body-local variables with safe ValueId allocation
|
||||
// Phase 191: Create empty body-local environment
|
||||
// LoopBodyLocalInitLowerer will populate it during init lowering
|
||||
use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv;
|
||||
let body_locals = collect_body_local_variables(_body, &mut alloc_body_local_value);
|
||||
let body_local_env = LoopBodyLocalEnv::from_locals(body_locals);
|
||||
let mut body_local_env = LoopBodyLocalEnv::new();
|
||||
|
||||
eprintln!("[pattern2/body-local] Phase 185-2: Collected {} body-local variables (offset={})",
|
||||
body_local_env.len(), body_local_start_offset);
|
||||
for (name, vid) in body_local_env.iter() {
|
||||
eprintln!(" {} → {:?}", name, vid);
|
||||
}
|
||||
eprintln!("[pattern2/body-local] Phase 191: Created empty body-local environment (offset={})",
|
||||
body_local_start_offset);
|
||||
|
||||
// Create allocator for other JoinIR-local ValueIds (Trim pattern, etc.)
|
||||
// Continues from where body_local_counter left off
|
||||
@ -307,7 +304,8 @@ impl MirBuilder {
|
||||
&env,
|
||||
&carrier_info,
|
||||
&carrier_updates,
|
||||
Some(&body_local_env), // Phase 185-2: Pass body-local environment
|
||||
_body, // Phase 191: Pass body AST for init lowering
|
||||
Some(&mut body_local_env), // Phase 191: Pass mutable body-local environment
|
||||
) {
|
||||
Ok((module, meta)) => (module, meta),
|
||||
Err(e) => {
|
||||
|
||||
@ -129,7 +129,8 @@ use std::collections::HashMap;
|
||||
/// * `break_condition` - AST node for the break condition (e.g., `i >= 2`) - Phase 170-B
|
||||
/// * `carrier_info` - Phase 176-3: Carrier metadata for dynamic multi-carrier support
|
||||
/// * `carrier_updates` - Phase 176-3: Update expressions for each carrier variable
|
||||
/// * `body_local_env` - Phase 185-2: Optional body-local variable environment for update expressions
|
||||
/// * `body_ast` - Phase 191: Loop body AST for body-local init lowering
|
||||
/// * `body_local_env` - Phase 185-2: Optional mutable body-local variable environment for init expressions
|
||||
pub(crate) fn lower_loop_with_break_minimal(
|
||||
_scope: LoopScopeShape,
|
||||
condition: &ASTNode,
|
||||
@ -137,7 +138,8 @@ pub(crate) fn lower_loop_with_break_minimal(
|
||||
env: &ConditionEnv,
|
||||
carrier_info: &CarrierInfo,
|
||||
carrier_updates: &HashMap<String, UpdateExpr>,
|
||||
body_local_env: Option<&LoopBodyLocalEnv>,
|
||||
body_ast: &[ASTNode],
|
||||
mut body_local_env: Option<&mut LoopBodyLocalEnv>,
|
||||
) -> Result<(JoinModule, JoinFragmentMeta), String> {
|
||||
// Phase 170-D-impl-3: Validate that conditions only use supported variable scopes
|
||||
// LoopConditionScopeBox checks that loop conditions don't reference loop-body-local variables
|
||||
@ -308,6 +310,29 @@ pub(crate) fn lower_loop_with_break_minimal(
|
||||
cond: Some(break_cond_value), // Phase 170-B: Use lowered condition
|
||||
});
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Phase 191: Body-Local Variable Initialization
|
||||
// ------------------------------------------------------------------
|
||||
// Lower body-local variable initialization expressions to JoinIR
|
||||
// This must happen BEFORE carrier updates since carrier updates may reference body-locals
|
||||
if let Some(ref mut body_env) = body_local_env {
|
||||
use crate::mir::join_ir::lowering::loop_body_local_init::LoopBodyLocalInitLowerer;
|
||||
|
||||
// Create a mutable reference to the instruction buffer
|
||||
let mut init_lowerer = LoopBodyLocalInitLowerer::new(
|
||||
env,
|
||||
&mut loop_step_func.body,
|
||||
Box::new(&mut alloc_value),
|
||||
);
|
||||
|
||||
init_lowerer.lower_inits_for_loop(body_ast, body_env)?;
|
||||
|
||||
eprintln!(
|
||||
"[joinir/pattern2] Phase 191: Lowered {} body-local init expressions",
|
||||
body_env.len()
|
||||
);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Loop Body: Compute updated values for all carriers
|
||||
// ------------------------------------------------------------------
|
||||
@ -326,7 +351,7 @@ pub(crate) fn lower_loop_with_break_minimal(
|
||||
})?;
|
||||
|
||||
// Phase 185-2: Emit carrier update with body-local support
|
||||
let updated_value = if let Some(body_env) = body_local_env {
|
||||
let updated_value = if let Some(ref body_env) = body_local_env {
|
||||
// Use UpdateEnv for body-local variable resolution
|
||||
let update_env = UpdateEnv::new(env, body_env);
|
||||
emit_carrier_update_with_env(
|
||||
|
||||
Reference in New Issue
Block a user