From e44e36b9cd125fd9ccf7d92368a6b32632c274df Mon Sep 17 00:00:00 2001 From: nyash-codex Date: Fri, 5 Dec 2025 21:39:22 +0900 Subject: [PATCH] refactor: Extract append_defs and stage1 lowerers (Phase 4) - Created append_defs.rs with lower_case_a_append_defs_with_scope() - Extracted 173 lines of append_defs lowering logic - Implements array concatenation loop (ArrayBox.get/push) - ValueId allocation: entry(8000-8999), loop_step(9000-9999) - Created stage1_using_resolver.rs with lower_case_a_stage1_usingresolver_with_scope() - Extracted 185 lines of stage1 using resolver logic - Implements namespace resolution loop with OR accumulation - ValueId allocation: entry(10000-10999), loop_step(11000-11999) Both modules use EntryFunctionBuilder helper for boilerplate initialization. Sizes: append_defs (173 lines), stage1 (185 lines) Ref: Phase 192 modularization effort --- .../lowering/generic_case_a/append_defs.rs | 202 ++++++++++++++++ .../generic_case_a/stage1_using_resolver.rs | 228 ++++++++++++++++++ 2 files changed, 430 insertions(+) create mode 100644 src/mir/join_ir/lowering/generic_case_a/append_defs.rs create mode 100644 src/mir/join_ir/lowering/generic_case_a/stage1_using_resolver.rs diff --git a/src/mir/join_ir/lowering/generic_case_a/append_defs.rs b/src/mir/join_ir/lowering/generic_case_a/append_defs.rs new file mode 100644 index 00000000..a59471bb --- /dev/null +++ b/src/mir/join_ir/lowering/generic_case_a/append_defs.rs @@ -0,0 +1,202 @@ +//! Array Append Loop Lowering (Case A) +//! +//! Phase 192: Extracted from generic_case_a.rs monolith. +//! +//! ## Responsibility +//! +//! Lowers FuncScannerBox.append_defs/2 array concatenation loop to JoinIR. +//! +//! ## Pattern Structure +//! +//! ```text +//! entry: append_defs_entry(dst, defs_box, n) +//! i = 0 +//! call loop_step(dst, defs_box, n, i) +//! +//! loop_step(dst, defs_box, n, i): +//! if i >= n { return } // Exit condition +//! item = defs_box.get(i) +//! dst.push(item) // Append item to dst +//! continue loop_step(dst, defs_box, n, i+1) +//! ``` +//! +//! ## ValueId Allocation +//! +//! - Entry range: 8000-8999 (`value_id_ranges::funcscanner_append_defs::entry`) +//! - Loop range: 9000-9999 (`value_id_ranges::funcscanner_append_defs::loop_step`) +//! +//! ## See Also +//! +//! - `value_id_ranges::funcscanner_append_defs` - ValueId allocation strategy +//! - `loop_scope_shape::CaseAContext` - Context extraction + +use std::collections::BTreeMap; + +use crate::mir::join_ir::lowering::loop_scope_shape::CaseAContext; +use crate::mir::join_ir::lowering::value_id_ranges; +use crate::mir::join_ir::{ + BinOpKind, CompareOp, ConstValue, JoinContId, JoinFuncId, JoinFunction, JoinInst, JoinModule, + LoopExitShape, LoopHeaderShape, MirLikeInst, +}; +use crate::mir::ValueId; + +use super::entry_builder::EntryFunctionBuilder; + +/// Phase 30 F-3.0.4: LoopScopeShape を直接受け取る append_defs lowerer +/// +/// 呼び出し元で LoopScopeShape を明示的に構築し、この関数に渡す。 +/// CaseAContext::from_scope() 経由で ctx を作成。 +pub(crate) fn lower_case_a_append_defs_with_scope( + scope: crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape, +) -> Option { + let ctx = CaseAContext::from_scope(scope, "append_defs", |offset| { + value_id_ranges::funcscanner_append_defs::loop_step(offset) + })?; + lower_case_a_append_defs_core(&ctx) +} + +/// append_defs JoinModule 構築のコア実装 +/// +/// CaseAContext から JoinModule を構築する共通ロジック。 +/// `_for_append_defs_minimal` と `_with_scope` の両方から呼ばれる。 +fn lower_case_a_append_defs_core(ctx: &CaseAContext) -> Option { + let dst_key = ctx.pinned_name_or_first(0)?; + let defs_key = ctx + .pinned_name_or_first(1) + .unwrap_or_else(|| dst_key.clone()); + let n_key = ctx + .pinned_name_or_first(2) + .unwrap_or_else(|| defs_key.clone()); + let i_key = ctx.carrier_name_or_first(0)?; + + let dst_loop = ctx.get_loop_id(&dst_key)?; + let defs_loop = ctx.get_loop_id(&defs_key)?; + let n_loop = ctx.get_loop_id(&n_key)?; + let i_loop = ctx.get_loop_id(&i_key)?; + + let mut join_module = JoinModule::new(); + + // entry: append_defs_entry(dst, defs_box, n) + let entry_id = JoinFuncId::new(0); + let dst_param = value_id_ranges::funcscanner_append_defs::entry(0); + let defs_box_param = value_id_ranges::funcscanner_append_defs::entry(1); + let n_param = value_id_ranges::funcscanner_append_defs::entry(2); + let mut entry_func = JoinFunction::new( + entry_id, + "append_defs_entry".to_string(), + vec![dst_param, defs_box_param, n_param], + ); + + let i_init = value_id_ranges::funcscanner_append_defs::entry(10); + entry_func.body.push(JoinInst::Compute(MirLikeInst::Const { + dst: i_init, + value: ConstValue::Integer(0), + })); + // Phase 192: Use EntryFunctionBuilder for boilerplate initialization + let mut entry_builder = EntryFunctionBuilder::new(); + entry_builder.add_var("s".to_string(), dst_param); // intake で param0 を "s" にするため + entry_builder.add_var("dst".to_string(), dst_param); + entry_builder.add_var("param1".to_string(), defs_box_param); + entry_builder.add_var("defs_box".to_string(), defs_box_param); + entry_builder.add_var("n".to_string(), n_param); + entry_builder.add_var("i".to_string(), i_init); + let entry_name_to_id = entry_builder.get_map().clone(); + + let loop_call_args: Vec = ctx + .ordered_pinned + .iter() + .chain(ctx.ordered_carriers.iter()) + .map(|name| entry_name_to_id.get(name).copied()) + .collect::>()?; + + let loop_step_id = JoinFuncId::new(1); + entry_func.body.push(JoinInst::Call { + func: loop_step_id, + args: loop_call_args, + k_next: None, + dst: None, + }); + + join_module.entry = Some(entry_id); + join_module.add_function(entry_func); + + // loop_step(dst, defs_box, n, i) + let header_shape = LoopHeaderShape::new_manual(ctx.pinned_ids.clone(), ctx.carrier_ids.clone()); + let loop_params = header_shape.to_loop_step_params(); + let mut loop_step_func = + JoinFunction::new(loop_step_id, "loop_step".to_string(), loop_params.clone()); + + let cmp_result = value_id_ranges::funcscanner_append_defs::loop_step(10); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::Compare { + dst: cmp_result, + op: CompareOp::Ge, + lhs: i_loop, + rhs: n_loop, + })); + + let _exit_shape = LoopExitShape::new_manual(ctx.exit_args.clone()); + + loop_step_func.body.push(JoinInst::Jump { + cont: JoinContId::new(0), + args: ctx.exit_args.clone(), + cond: Some(cmp_result), + }); + + let item_value = value_id_ranges::funcscanner_append_defs::loop_step(11); + let next_i = value_id_ranges::funcscanner_append_defs::loop_step(12); + let const_1 = value_id_ranges::funcscanner_append_defs::loop_step(13); + + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::BoxCall { + dst: Some(item_value), + box_name: "ArrayBox".to_string(), + method: "get".to_string(), + args: vec![defs_loop, i_loop], + })); + + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::BoxCall { + dst: None, + box_name: "ArrayBox".to_string(), + method: "push".to_string(), + args: vec![dst_loop, item_value], + })); + + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::Const { + dst: const_1, + value: ConstValue::Integer(1), + })); + + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::BinOp { + dst: next_i, + op: BinOpKind::Add, + lhs: i_loop, + rhs: const_1, + })); + + loop_step_func.body.push(JoinInst::Call { + func: loop_step_id, + args: vec![dst_loop, defs_loop, n_loop, next_i], + k_next: None, + dst: None, + }); + + join_module.add_function(loop_step_func); + + eprintln!( + "[joinir/generic_case_a/append_defs] ✅ constructed JoinIR (functions={}, value_range={}..{})", + join_module.functions.len(), + value_id_ranges::base::FUNCSCANNER_APPEND_DEFS, + value_id_ranges::base::FUNCSCANNER_APPEND_DEFS + 1999 + ); + + Some(join_module) +} diff --git a/src/mir/join_ir/lowering/generic_case_a/stage1_using_resolver.rs b/src/mir/join_ir/lowering/generic_case_a/stage1_using_resolver.rs new file mode 100644 index 00000000..4fcde5a5 --- /dev/null +++ b/src/mir/join_ir/lowering/generic_case_a/stage1_using_resolver.rs @@ -0,0 +1,228 @@ +//! Stage-1 Using Resolver Loop Lowering (Case A) +//! +//! Phase 192: Extracted from generic_case_a.rs monolith. +//! +//! ## Responsibility +//! +//! Lowers Stage1UsingResolverBox.resolve_for_source/5 using namespace resolution loop to JoinIR. +//! +//! ## Pattern Structure +//! +//! ```text +//! entry: resolve_entries(entries, n, modules, seen, prefix_init) +//! i = 0 +//! call loop_step(entries, n, modules, seen, prefix_init, i) +//! +//! loop_step(entries, n, modules, seen, prefix, i): +//! if i >= n { return prefix } // Exit condition +//! entry = entries.get(i) +//! new_prefix = prefix | entry // OR operation (accumulate) +//! continue loop_step(entries, n, modules, seen, new_prefix, i+1) +//! ``` +//! +//! ## ValueId Allocation +//! +//! - Entry range: 10000-10999 (`value_id_ranges::stage1_using_resolver::entry`) +//! - Loop range: 11000-11999 (`value_id_ranges::stage1_using_resolver::loop_step`) +//! +//! ## See Also +//! +//! - `value_id_ranges::stage1_using_resolver` - ValueId allocation strategy +//! - `loop_scope_shape::CaseAContext` - Context extraction + +use std::collections::BTreeMap; + +use crate::mir::join_ir::lowering::loop_scope_shape::CaseAContext; +use crate::mir::join_ir::lowering::value_id_ranges; +use crate::mir::join_ir::lowering::value_id_ranges::stage1_using_resolver as stage1_vid; +use crate::mir::join_ir::{ + BinOpKind, CompareOp, ConstValue, JoinContId, JoinFuncId, JoinFunction, JoinInst, JoinModule, + LoopExitShape, LoopHeaderShape, MirLikeInst, +}; +use crate::mir::ValueId; + +use super::entry_builder::EntryFunctionBuilder; + +/// Phase 30 F-3.0.5: LoopScopeShape を直接受け取る Stage-1 UsingResolver lowerer +/// +/// 呼び出し元で LoopScopeShape を明示的に構築し、この関数に渡す。 +/// CaseAContext::from_scope() 経由で ctx を作成。 +pub(crate) fn lower_case_a_stage1_usingresolver_with_scope( + scope: crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape, +) -> Option { + let ctx = CaseAContext::from_scope(scope, "stage1", |offset| stage1_vid::loop_step(offset))?; + lower_case_a_stage1_usingresolver_core(&ctx) +} + +/// Stage-1 UsingResolver JoinModule 構築のコア実装 +/// +/// CaseAContext から JoinModule を構築する共通ロジック。 +/// `_for_stage1_usingresolver_minimal` と `_with_scope` の両方から呼ばれる。 +fn lower_case_a_stage1_usingresolver_core(ctx: &CaseAContext) -> Option { + let entries_key = ctx.pinned_name_or_first(0)?; + let n_key = ctx + .pinned_name_or_first(1) + .unwrap_or_else(|| entries_key.clone()); + let modules_key = ctx + .pinned_name_or_first(2) + .unwrap_or_else(|| entries_key.clone()); + let seen_key = ctx + .pinned_name_or_first(3) + .unwrap_or_else(|| entries_key.clone()); + let prefix_key = ctx.carrier_name_or_first(0)?; + let i_key = ctx + .carrier_name_or_first(1) + .unwrap_or_else(|| prefix_key.clone()); + + let entries_loop = ctx.get_loop_id(&entries_key)?; + let n_loop = ctx.get_loop_id(&n_key)?; + let modules_loop = ctx.get_loop_id(&modules_key)?; + let seen_loop = ctx.get_loop_id(&seen_key)?; + let prefix_loop = ctx.get_loop_id(&prefix_key)?; + let i_loop = ctx.get_loop_id(&i_key)?; + + let mut join_module = JoinModule::new(); + + // entry: resolve_entries(entries, n, modules, seen, prefix_init) + let resolve_id = JoinFuncId::new(0); + let entries_param = stage1_vid::entry(0); + let n_param = stage1_vid::entry(1); + let modules_param = stage1_vid::entry(2); + let seen_param = stage1_vid::entry(3); + let prefix_param = stage1_vid::entry(4); + let mut resolve_func = JoinFunction::new( + resolve_id, + "resolve_entries".to_string(), + vec![ + entries_param, + n_param, + modules_param, + seen_param, + prefix_param, + ], + ); + + let i_init = stage1_vid::entry(10); + resolve_func + .body + .push(JoinInst::Compute(MirLikeInst::Const { + dst: i_init, + value: ConstValue::Integer(0), + })); + + // Phase 192: Use EntryFunctionBuilder for boilerplate initialization + let mut entry_builder = EntryFunctionBuilder::new(); + entry_builder.add_var(entries_key.clone(), entries_param); + entry_builder.add_var(n_key.clone(), n_param); + entry_builder.add_var(modules_key.clone(), modules_param); + entry_builder.add_var(seen_key.clone(), seen_param); + entry_builder.add_var(prefix_key.clone(), prefix_param); + entry_builder.add_var(i_key.clone(), i_init); + let entry_name_to_id = entry_builder.get_map().clone(); + + let loop_call_args: Vec = ctx + .ordered_pinned + .iter() + .chain(ctx.ordered_carriers.iter()) + .map(|name| entry_name_to_id.get(name).copied()) + .collect::>()?; + + let loop_step_id = JoinFuncId::new(1); + resolve_func.body.push(JoinInst::Call { + func: loop_step_id, + args: loop_call_args, + k_next: None, + dst: None, + }); + + join_module.entry = Some(resolve_id); + join_module.add_function(resolve_func); + + // loop_step(entries, n, modules, seen, prefix, i) + let header_shape = LoopHeaderShape::new_manual(ctx.pinned_ids.clone(), ctx.carrier_ids.clone()); + let loop_params = header_shape.to_loop_step_params(); + let mut loop_step_func = + JoinFunction::new(loop_step_id, "loop_step".to_string(), loop_params.clone()); + + let cmp_result = stage1_vid::loop_step(10); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::Compare { + dst: cmp_result, + op: CompareOp::Ge, + lhs: i_loop, + rhs: n_loop, + })); + + let exit_shape = if ctx.exit_args.is_empty() { + LoopExitShape::new_manual(vec![prefix_loop]) + } else { + LoopExitShape::new_manual(ctx.exit_args.clone()) + }; + + loop_step_func.body.push(JoinInst::Jump { + cont: JoinContId::new(0), + args: exit_shape.exit_args.clone(), + cond: Some(cmp_result), + }); + + let entry_value = stage1_vid::loop_step(11); + let next_i = stage1_vid::loop_step(12); + let const_1 = stage1_vid::loop_step(13); + let new_prefix = stage1_vid::loop_step(14); + + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::BoxCall { + dst: Some(entry_value), + box_name: "ArrayBox".to_string(), + method: "get".to_string(), + args: vec![entries_loop, i_loop], + })); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::Const { + dst: const_1, + value: ConstValue::Integer(1), + })); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::BinOp { + dst: next_i, + op: BinOpKind::Add, + lhs: i_loop, + rhs: const_1, + })); + loop_step_func + .body + .push(JoinInst::Compute(MirLikeInst::BinOp { + dst: new_prefix, + op: BinOpKind::Or, + lhs: prefix_loop, + rhs: entry_value, + })); + loop_step_func.body.push(JoinInst::Call { + func: loop_step_id, + args: vec![ + entries_loop, + n_loop, + modules_loop, + seen_loop, + new_prefix, + next_i, + ], + k_next: None, + dst: None, + }); + + join_module.add_function(loop_step_func); + + eprintln!( + "[joinir/generic_case_a/stage1] ✅ constructed JoinIR (functions={}, value_range={}..{})", + join_module.functions.len(), + value_id_ranges::base::STAGE1_USING_RESOLVER, + value_id_ranges::base::STAGE1_USING_RESOLVER + 1999 + ); + + Some(join_module) +}