diff --git a/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs b/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs index 14f05a97..594d0c01 100644 --- a/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs +++ b/src/mir/control_tree/normalized_shadow/loop_true_if_break_continue.rs @@ -104,11 +104,181 @@ impl LoopTrueIfBreakContinueBuilderBox { } } - // Phase 143 P0: Skeleton continues to return Ok(None) - // Steps 4-6 will build the actual JoinModule with Jump instructions - if crate::config::env::joinir_dev_enabled() { - eprintln!("[phase143/debug] Step 3 validation passed, skeleton still returns Ok(None)"); + // Step 4 (P0): Build JoinModule with 6 functions and Branch instructions + // === Helper closures === + fn alloc_value_id(next_value_id: &mut u32) -> ValueId { + let vid = ValueId(*next_value_id); + *next_value_id += 1; + vid } + + let alloc_env_params = + |fields: &[String], next_value_id: &mut u32| -> Vec { + fields + .iter() + .map(|_| alloc_value_id(next_value_id)) + .collect() + }; + + let build_env_map = |fields: &[String], params: &[ValueId]| -> BTreeMap { + let mut env = BTreeMap::new(); + for (name, vid) in fields.iter().zip(params.iter()) { + env.insert(name.clone(), *vid); + } + env + }; + + let collect_env_args = |fields: &[String], env: &BTreeMap| -> Result, String> { + let mut args = Vec::with_capacity(fields.len()); + for name in fields { + let vid = env.get(name).copied().ok_or_else(|| { + format!("phase143/branch_emission: env missing required field '{name}'") + })?; + args.push(vid); + } + Ok(args) + }; + + // === Phase 4: Allocate IDs and build env === + let mut next_value_id: u32 = 1; + let env_fields = env_layout.env_fields(); + + // Allocate 6 JoinFuncIds + let main_id = JoinFuncId::new(0); + let loop_step_id = JoinFuncId::new(1); + let loop_cond_check_id = JoinFuncId::new(2); + let k_then_id = JoinFuncId::new(3); + let k_else_id = JoinFuncId::new(4); + let k_exit_id = JoinFuncId::new(5); + + // === main(env) === + let main_params = alloc_env_params(&env_fields, &mut next_value_id); + let env_main = build_env_map(&env_fields, &main_params); + let main_func = { + let mut f = JoinFunction::new(main_id, "main".to_string(), main_params); + // main: Call(loop_step, env) + let loop_step_args = collect_env_args(&env_fields, &env_main)?; + f.body.push(JoinInst::Call { + func: loop_step_id, + args: loop_step_args, + k_next: None, + dst: None, + }); + f + }; + + // === loop_step(env) === + let loop_step_params = alloc_env_params(&env_fields, &mut next_value_id); + let env_loop_step = build_env_map(&env_fields, &loop_step_params); + let loop_step_func = { + let mut f = JoinFunction::new(loop_step_id, "loop_step".to_string(), loop_step_params); + // loop_step: Call(loop_cond_check, env) + let loop_cond_check_args = collect_env_args(&env_fields, &env_loop_step)?; + f.body.push(JoinInst::Call { + func: loop_cond_check_id, + args: loop_cond_check_args, + k_next: None, + dst: None, + }); + f + }; + + // === loop_cond_check(env): Lower condition and emit Jump === + let loop_cond_check_params = alloc_env_params(&env_fields, &mut next_value_id); + let env_loop_cond_check = build_env_map(&env_fields, &loop_cond_check_params); + let loop_cond_check_func = { + let mut f = JoinFunction::new( + loop_cond_check_id, + "loop_cond_check".to_string(), + loop_cond_check_params, + ); + + // Reuse the validated condition lowering from Step 3 + let cond_vid = match NormalizedExprLowererBox::lower_expr_with_scope( + ExprLoweringScope::PureOnly, + &cond_ast, + &env_loop_cond_check, + &mut f.body, + &mut next_value_id, + ) { + Ok(Some(vid)) => vid, + _ => { + return Err("phase143/branch_emission: condition lowering failed unexpectedly".to_string()); + } + }; + + // Emit conditional Jump instruction + // Jump { cond: Some(cond_vid), cont: k_exit } + // If cond_vid is true: jump to k_exit (break) + // If cond_vid is false: fall through to next instruction (continue) + let k_exit_args = collect_env_args(&env_fields, &env_loop_cond_check)?; + f.body.push(JoinInst::Jump { + cont: k_exit_id.as_cont(), + args: k_exit_args, + cond: Some(cond_vid), + }); + + // If we don't jump (condition is false), continue the loop + // Call loop_step() to iterate again + let loop_step_args = collect_env_args(&env_fields, &env_loop_cond_check)?; + f.body.push(JoinInst::Call { + func: loop_step_id, + args: loop_step_args, + k_next: None, + dst: None, + }); + + f + }; + + // === k_then(env): Not used in P0 (direct Jump from loop_cond_check) === + // Kept for structural clarity in case future extensions need it + let k_then_params = alloc_env_params(&env_fields, &mut next_value_id); + let _env_k_then = build_env_map(&env_fields, &k_then_params); + let k_then_func = { + let f = JoinFunction::new(k_then_id, "k_then".to_string(), k_then_params); + // Empty placeholder: P0 doesn't use this function + f + }; + + // === k_else(env): Not used in P0 (direct Call from loop_cond_check fallthrough) === + // Kept for structural clarity in case future extensions need it + let k_else_params = alloc_env_params(&env_fields, &mut next_value_id); + let _env_k_else = build_env_map(&env_fields, &k_else_params); + let k_else_func = { + let f = JoinFunction::new(k_else_id, "k_else".to_string(), k_else_params); + // Empty placeholder: P0 doesn't use this function + f + }; + + // === k_exit(env): Placeholder for return === + let k_exit_params = alloc_env_params(&env_fields, &mut next_value_id); + let _env_k_exit = build_env_map(&env_fields, &k_exit_params); + let k_exit_func = { + let f = JoinFunction::new(k_exit_id, "k_exit".to_string(), k_exit_params); + // Step 6 will add: Return with exit_values + // For now, placeholder empty (will be filled in Step 6) + f + }; + + // === Build JoinModule === + let mut module = JoinModule::new(); + module.add_function(main_func); + module.add_function(loop_step_func); + module.add_function(loop_cond_check_func); + module.add_function(k_then_func); + module.add_function(k_else_func); + module.add_function(k_exit_func); + + module.entry = Some(main_id); + module.mark_normalized(); + + if crate::config::env::joinir_dev_enabled() { + eprintln!("[phase143/debug] Step 4: JoinModule built with 6 functions and Jump instructions"); + } + + // Step 5-6 will complete TailCalls and exit handling + // For now, return Ok(None) skeleton Ok(None) }