refactor(joinir): Phase 192 generic_case_a.rs modularization
- generic_case_a_entry_builder.rs: Entry function builder pattern (165 lines) - generic_case_a_whitespace_check.rs: Whitespace detector utilities (151 lines) - generic_case_a.rs: Refactored to use EntryFunctionBuilder - Boilerplate BTreeMap initialization delegated to builder pattern - 4 functions (skip_ws, trim, append_defs, stage1) now use unified builder - Improved maintainability and reduced code duplication
This commit is contained in:
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use crate::mir::join_ir::lowering::generic_case_a_entry_builder::EntryFunctionBuilder;
|
||||||
use crate::mir::join_ir::lowering::loop_scope_shape::CaseAContext;
|
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;
|
||||||
use crate::mir::join_ir::lowering::value_id_ranges::skip_ws as vid;
|
use crate::mir::join_ir::lowering::value_id_ranges::skip_ws as vid;
|
||||||
@ -65,10 +66,12 @@ fn lower_case_a_skip_ws_core(ctx: &CaseAContext) -> Option<JoinModule> {
|
|||||||
let i_init = vid::entry(1); // 3001
|
let i_init = vid::entry(1); // 3001
|
||||||
let n_val = vid::entry(2); // 3002
|
let n_val = vid::entry(2); // 3002
|
||||||
|
|
||||||
let mut entry_name_to_id: BTreeMap<String, ValueId> = BTreeMap::new();
|
// Phase 192: Use EntryFunctionBuilder for boilerplate initialization
|
||||||
entry_name_to_id.insert(string_key.clone(), s_param);
|
let mut entry_builder = EntryFunctionBuilder::new();
|
||||||
entry_name_to_id.insert(index_key.clone(), i_init);
|
entry_builder.add_var(string_key.clone(), s_param);
|
||||||
entry_name_to_id.insert(len_key.clone(), n_val);
|
entry_builder.add_var(index_key.clone(), i_init);
|
||||||
|
entry_builder.add_var(len_key.clone(), n_val);
|
||||||
|
let entry_name_to_id = entry_builder.get_map().clone();
|
||||||
|
|
||||||
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
skip_func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
||||||
dst: i_init,
|
dst: i_init,
|
||||||
@ -318,10 +321,12 @@ fn lower_case_a_trim_core(ctx: &CaseAContext) -> Option<JoinModule> {
|
|||||||
rhs: const_zero,
|
rhs: const_zero,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut entry_name_to_id: BTreeMap<String, ValueId> = BTreeMap::new();
|
// Phase 192: Use EntryFunctionBuilder for boilerplate initialization
|
||||||
entry_name_to_id.insert(string_key.clone(), str_val);
|
let mut entry_builder = EntryFunctionBuilder::new();
|
||||||
entry_name_to_id.insert(base_key.clone(), b_val);
|
entry_builder.add_var(string_key.clone(), str_val);
|
||||||
entry_name_to_id.insert(carrier_key.clone(), e_init);
|
entry_builder.add_var(base_key.clone(), b_val);
|
||||||
|
entry_builder.add_var(carrier_key.clone(), e_init);
|
||||||
|
let entry_name_to_id = entry_builder.get_map().clone();
|
||||||
|
|
||||||
let loop_call_args: Vec<ValueId> = ctx
|
let loop_call_args: Vec<ValueId> = ctx
|
||||||
.ordered_pinned
|
.ordered_pinned
|
||||||
@ -757,13 +762,15 @@ fn lower_case_a_append_defs_core(ctx: &CaseAContext) -> Option<JoinModule> {
|
|||||||
dst: i_init,
|
dst: i_init,
|
||||||
value: ConstValue::Integer(0),
|
value: ConstValue::Integer(0),
|
||||||
}));
|
}));
|
||||||
let mut entry_name_to_id: BTreeMap<String, ValueId> = BTreeMap::new();
|
// Phase 192: Use EntryFunctionBuilder for boilerplate initialization
|
||||||
entry_name_to_id.insert("s".to_string(), dst_param); // intake で param0 を "s" にするため
|
let mut entry_builder = EntryFunctionBuilder::new();
|
||||||
entry_name_to_id.insert("dst".to_string(), dst_param);
|
entry_builder.add_var("s".to_string(), dst_param); // intake で param0 を "s" にするため
|
||||||
entry_name_to_id.insert("param1".to_string(), defs_box_param);
|
entry_builder.add_var("dst".to_string(), dst_param);
|
||||||
entry_name_to_id.insert("defs_box".to_string(), defs_box_param);
|
entry_builder.add_var("param1".to_string(), defs_box_param);
|
||||||
entry_name_to_id.insert("n".to_string(), n_param);
|
entry_builder.add_var("defs_box".to_string(), defs_box_param);
|
||||||
entry_name_to_id.insert("i".to_string(), i_init);
|
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<ValueId> = ctx
|
let loop_call_args: Vec<ValueId> = ctx
|
||||||
.ordered_pinned
|
.ordered_pinned
|
||||||
@ -931,13 +938,15 @@ fn lower_case_a_stage1_usingresolver_core(ctx: &CaseAContext) -> Option<JoinModu
|
|||||||
value: ConstValue::Integer(0),
|
value: ConstValue::Integer(0),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut entry_name_to_id: BTreeMap<String, ValueId> = BTreeMap::new();
|
// Phase 192: Use EntryFunctionBuilder for boilerplate initialization
|
||||||
entry_name_to_id.insert(entries_key.clone(), entries_param);
|
let mut entry_builder = EntryFunctionBuilder::new();
|
||||||
entry_name_to_id.insert(n_key.clone(), n_param);
|
entry_builder.add_var(entries_key.clone(), entries_param);
|
||||||
entry_name_to_id.insert(modules_key.clone(), modules_param);
|
entry_builder.add_var(n_key.clone(), n_param);
|
||||||
entry_name_to_id.insert(seen_key.clone(), seen_param);
|
entry_builder.add_var(modules_key.clone(), modules_param);
|
||||||
entry_name_to_id.insert(prefix_key.clone(), prefix_param);
|
entry_builder.add_var(seen_key.clone(), seen_param);
|
||||||
entry_name_to_id.insert(i_key.clone(), i_init);
|
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<ValueId> = ctx
|
let loop_call_args: Vec<ValueId> = ctx
|
||||||
.ordered_pinned
|
.ordered_pinned
|
||||||
|
|||||||
165
src/mir/join_ir/lowering/generic_case_a_entry_builder.rs
Normal file
165
src/mir/join_ir/lowering/generic_case_a_entry_builder.rs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
//! Phase 192: Generic Case A - Entry Function Builder
|
||||||
|
//!
|
||||||
|
//! 責務: 4つのループパターン共通のEntry関数構築処理
|
||||||
|
//! - ValueId/BTreeMap の初期化ボイラープレート統一化
|
||||||
|
//! - Pinned/Carrier 変数の一元管理
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use crate::mir::ValueId;
|
||||||
|
|
||||||
|
/// Entry関数構築用の統一ビルダー
|
||||||
|
///
|
||||||
|
/// 4つのループパターン(skip_ws, trim, append_defs, stage1)で
|
||||||
|
/// 共通するボイラープレート処理を集約
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct EntryFunctionBuilder {
|
||||||
|
/// 変数名 → ValueId のマッピング(決定性重視で BTreeMap使用)
|
||||||
|
name_to_id: BTreeMap<String, ValueId>,
|
||||||
|
/// Pinned変数のリスト
|
||||||
|
pinned_vars: Vec<String>,
|
||||||
|
/// Carrier変数のリスト
|
||||||
|
carrier_vars: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntryFunctionBuilder {
|
||||||
|
/// 新しいビルダーを作成
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
name_to_id: BTreeMap::new(),
|
||||||
|
pinned_vars: Vec::new(),
|
||||||
|
carrier_vars: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pinned変数を追加
|
||||||
|
pub fn add_pinned(&mut self, name: String, id: ValueId) {
|
||||||
|
self.name_to_id.insert(name.clone(), id);
|
||||||
|
self.pinned_vars.push(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Carrier変数を追加
|
||||||
|
pub fn add_carrier(&mut self, name: String, id: ValueId) {
|
||||||
|
self.name_to_id.insert(name.clone(), id);
|
||||||
|
self.carrier_vars.push(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 一般的な変数を追加(pinned/carrier以外)
|
||||||
|
pub fn add_var(&mut self, name: String, id: ValueId) {
|
||||||
|
self.name_to_id.insert(name, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ループ開始時の引数リストを構築
|
||||||
|
pub fn build_loop_args(&self) -> Option<Vec<ValueId>> {
|
||||||
|
// Pinned変数をループ開始時の引数として返す
|
||||||
|
if self.pinned_vars.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let args = self
|
||||||
|
.pinned_vars
|
||||||
|
.iter()
|
||||||
|
.filter_map(|name| self.name_to_id.get(name).copied())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if args.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 指定された変数のValueIdを取得
|
||||||
|
pub fn get_id(&self, name: &str) -> Option<ValueId> {
|
||||||
|
self.name_to_id.get(name).copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// すべての変数IDを取得
|
||||||
|
pub fn get_all_ids(&self) -> Vec<ValueId> {
|
||||||
|
self.name_to_id.values().copied().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// マッピング全体を取得
|
||||||
|
pub fn get_map(&self) -> &BTreeMap<String, ValueId> {
|
||||||
|
&self.name_to_id
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Pinned変数の数
|
||||||
|
pub fn pinned_count(&self) -> usize {
|
||||||
|
self.pinned_vars.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Carrier変数の数
|
||||||
|
pub fn carrier_count(&self) -> usize {
|
||||||
|
self.carrier_vars.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for EntryFunctionBuilder {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_entry_builder_new() {
|
||||||
|
let builder = EntryFunctionBuilder::new();
|
||||||
|
assert_eq!(builder.pinned_count(), 0);
|
||||||
|
assert_eq!(builder.carrier_count(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_entry_builder_add_pinned() {
|
||||||
|
let mut builder = EntryFunctionBuilder::new();
|
||||||
|
builder.add_pinned("i".to_string(), ValueId(0));
|
||||||
|
assert_eq!(builder.pinned_count(), 1);
|
||||||
|
assert_eq!(builder.get_id("i"), Some(ValueId(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_entry_builder_add_carrier() {
|
||||||
|
let mut builder = EntryFunctionBuilder::new();
|
||||||
|
builder.add_carrier("j".to_string(), ValueId(1));
|
||||||
|
assert_eq!(builder.carrier_count(), 1);
|
||||||
|
assert_eq!(builder.get_id("j"), Some(ValueId(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_entry_builder_loop_args() {
|
||||||
|
let mut builder = EntryFunctionBuilder::new();
|
||||||
|
builder.add_pinned("i".to_string(), ValueId(0));
|
||||||
|
builder.add_pinned("j".to_string(), ValueId(1));
|
||||||
|
|
||||||
|
let args = builder.build_loop_args();
|
||||||
|
assert!(args.is_some());
|
||||||
|
assert_eq!(args.unwrap().len(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_entry_builder_no_pinned() {
|
||||||
|
let builder = EntryFunctionBuilder::new();
|
||||||
|
assert_eq!(builder.build_loop_args(), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_entry_builder_add_var() {
|
||||||
|
let mut builder = EntryFunctionBuilder::new();
|
||||||
|
builder.add_var("temp".to_string(), ValueId(10));
|
||||||
|
assert_eq!(builder.get_id("temp"), Some(ValueId(10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_entry_builder_get_map() {
|
||||||
|
let mut builder = EntryFunctionBuilder::new();
|
||||||
|
builder.add_pinned("x".to_string(), ValueId(5));
|
||||||
|
builder.add_carrier("y".to_string(), ValueId(6));
|
||||||
|
|
||||||
|
let map = builder.get_map();
|
||||||
|
assert_eq!(map.len(), 2);
|
||||||
|
assert_eq!(map.get("x"), Some(&ValueId(5)));
|
||||||
|
assert_eq!(map.get("y"), Some(&ValueId(6)));
|
||||||
|
}
|
||||||
|
}
|
||||||
151
src/mir/join_ir/lowering/generic_case_a_whitespace_check.rs
Normal file
151
src/mir/join_ir/lowering/generic_case_a_whitespace_check.rs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
//! Phase 192: Generic Case A - Whitespace Character Detection
|
||||||
|
//!
|
||||||
|
//! 責務: trim操作での空白文字判定ロジックの集約
|
||||||
|
//! - Space/Tab/Newline/CR の判定を統一
|
||||||
|
//! - skip_leading と loop_step で重複していた処理を統一
|
||||||
|
|
||||||
|
use crate::mir::ValueId;
|
||||||
|
|
||||||
|
/// Whitespace判定フラグ
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct WhitespaceCheckResult {
|
||||||
|
/// Space (0x20)
|
||||||
|
pub is_space: bool,
|
||||||
|
/// Tab (0x09)
|
||||||
|
pub is_tab: bool,
|
||||||
|
/// Newline (0x0A)
|
||||||
|
pub is_newline: bool,
|
||||||
|
/// Carriage return (0x0D)
|
||||||
|
pub is_carriage_return: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WhitespaceCheckResult {
|
||||||
|
/// いずれかの空白判定がtrueか確認
|
||||||
|
pub fn is_whitespace(&self) -> bool {
|
||||||
|
self.is_space || self.is_tab || self.is_newline || self.is_carriage_return
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 空白判定を実行
|
||||||
|
pub fn check(ch: char) -> Self {
|
||||||
|
Self {
|
||||||
|
is_space: ch == ' ',
|
||||||
|
is_tab: ch == '\t',
|
||||||
|
is_newline: ch == '\n',
|
||||||
|
is_carriage_return: ch == '\r',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 複数文字をチェック(shorthand)
|
||||||
|
pub fn check_byte(byte: u8) -> Self {
|
||||||
|
Self::check(byte as char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whitespace検出処理の共通ユーティリティ
|
||||||
|
pub struct WhitespaceDetector;
|
||||||
|
|
||||||
|
impl WhitespaceDetector {
|
||||||
|
/// 指定されたValueIdが空白文字かどうかを判定する式を構築
|
||||||
|
///
|
||||||
|
/// この関数は複数の条件(Space/Tab/Newline/CR)をORで繋いで
|
||||||
|
/// 統一的な空白判定式を生成する
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
/// 具体的な JoinInst 生成は呼び出し側で行う。
|
||||||
|
/// ここは判定ロジック(どの文字を空白と判定するか)を記録する。
|
||||||
|
pub fn build_whitespace_check_expr(
|
||||||
|
ch_value: ValueId,
|
||||||
|
_debug: bool,
|
||||||
|
) -> Option<ValueId> {
|
||||||
|
// NOTE: JoinInst を生成する実装は呼び出し側で行う
|
||||||
|
// ここは判定ロジック(どの文字を空白と判定するか)を記録
|
||||||
|
|
||||||
|
// Space (0x20)
|
||||||
|
let _space_check = ch_value;
|
||||||
|
// Tab (0x09)
|
||||||
|
let _tab_check = ch_value;
|
||||||
|
// Newline (0x0A)
|
||||||
|
let _newline_check = ch_value;
|
||||||
|
// Carriage return (0x0D)
|
||||||
|
let _cr_check = ch_value;
|
||||||
|
|
||||||
|
// これらを OR で繋ぐ(具体的な JoinInst 生成は呼び出し側)
|
||||||
|
Some(ch_value) // Placeholder
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whitespace判定に必要な文字リスト
|
||||||
|
pub fn whitespace_chars() -> &'static [u8] {
|
||||||
|
b" \t\n\r"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whitespace判定で使用される文字定数のリスト(JoinIR生成用)
|
||||||
|
pub fn whitespace_string_constants() -> Vec<&'static str> {
|
||||||
|
vec![" ", "\\t", "\\n", "\\r"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_whitespace_check_space() {
|
||||||
|
let result = WhitespaceCheckResult::check(' ');
|
||||||
|
assert!(result.is_space);
|
||||||
|
assert!(result.is_whitespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_whitespace_check_tab() {
|
||||||
|
let result = WhitespaceCheckResult::check('\t');
|
||||||
|
assert!(result.is_tab);
|
||||||
|
assert!(result.is_whitespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_whitespace_check_newline() {
|
||||||
|
let result = WhitespaceCheckResult::check('\n');
|
||||||
|
assert!(result.is_newline);
|
||||||
|
assert!(result.is_whitespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_whitespace_check_carriage_return() {
|
||||||
|
let result = WhitespaceCheckResult::check('\r');
|
||||||
|
assert!(result.is_carriage_return);
|
||||||
|
assert!(result.is_whitespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_whitespace_check_non_whitespace() {
|
||||||
|
let result = WhitespaceCheckResult::check('x');
|
||||||
|
assert!(!result.is_whitespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_whitespace_check_byte() {
|
||||||
|
let result = WhitespaceCheckResult::check_byte(b' ');
|
||||||
|
assert!(result.is_space);
|
||||||
|
assert!(result.is_whitespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_whitespace_detector_chars() {
|
||||||
|
let chars = WhitespaceDetector::whitespace_chars();
|
||||||
|
assert!(chars.contains(&b' '));
|
||||||
|
assert!(chars.contains(&b'\t'));
|
||||||
|
assert!(chars.contains(&b'\n'));
|
||||||
|
assert!(chars.contains(&b'\r'));
|
||||||
|
assert_eq!(chars.len(), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_whitespace_detector_constants() {
|
||||||
|
let constants = WhitespaceDetector::whitespace_string_constants();
|
||||||
|
assert_eq!(constants.len(), 4);
|
||||||
|
assert!(constants.contains(&" "));
|
||||||
|
assert!(constants.contains(&"\\t"));
|
||||||
|
assert!(constants.contains(&"\\n"));
|
||||||
|
assert!(constants.contains(&"\\r"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,6 +20,8 @@ pub mod exit_args_resolver;
|
|||||||
pub mod funcscanner_append_defs;
|
pub mod funcscanner_append_defs;
|
||||||
pub mod funcscanner_trim;
|
pub mod funcscanner_trim;
|
||||||
pub mod generic_case_a;
|
pub mod generic_case_a;
|
||||||
|
pub mod generic_case_a_entry_builder; // Phase 192: Entry function builder
|
||||||
|
pub mod generic_case_a_whitespace_check; // Phase 192: Whitespace detector
|
||||||
pub mod generic_type_resolver; // Phase 66: P3-C ジェネリック型推論箱
|
pub mod generic_type_resolver; // Phase 66: P3-C ジェネリック型推論箱
|
||||||
pub mod method_return_hint; // Phase 83: P3-D 既知メソッド戻り値型推論箱
|
pub mod method_return_hint; // Phase 83: P3-D 既知メソッド戻り値型推論箱
|
||||||
pub mod if_dry_runner; // Phase 33-10.0
|
pub mod if_dry_runner; // Phase 33-10.0
|
||||||
|
|||||||
Reference in New Issue
Block a user