JoinIR Pattern Policies - ルーティング箱の責務
概要
このディレクトリには、Pattern認識とルーティング(policy決定)を行う「箱」が格納されています。
Policy箱の責務
ルーティング決定
- 入力: LoopSkeleton、break条件、carrier情報
- 出力: 適用可能なPattern(Pattern2, Pattern3, etc.)とLoweringResult
- 判断基準: パターンマッチング条件(Trim, ConditionalStep, Escape, etc.)
Lowering Result生成
- Pattern固有の情報(ConditionOnlyRecipe, ConditionalStepInfo, etc.)を生成
- CarrierInfo拡張(promoted variables, trim_helper, etc.)
- ConditionBinding設定
Policy箱の候補(将来の整理対象)
trim_loop_lowering.rs (Phase 180/92/93)
現在の場所: patterns/trim_loop_lowering.rs
責務: Trimパターン認識とConditionOnlyルーティング
判断基準:
- LoopBodyLocal変数がTrim条件(whitespace check)
- break条件がConditionOnly(毎イテレーション再計算)
出力:
TrimLoweringResult- condition, carrier_info, condition_only_recipe
将来的な整理:
- Trimパターン判断ロジックをpolicies/へ移動検討
- 現在はpatterns/直下に配置(Phase 180統合済み)
p5b_escape_derived_policy.rs (Phase 94)
現在の場所: patterns/policies/p5b_escape_derived_policy.rs
責務: P5b escapeパターン認識とBodyLocalDerivedルーティング
判断基準:
- body-local変数の再代入(例:
ch = s.substring(...)) - escape skip条件(例:
if ch == "\\" { i = i + 2 }) - loop変数の条件付き更新
出力:
P5bEscapeDerivedDecision::UseDerived(BodyLocalDerivedRecipe)- escape recipeP5bEscapeDerivedDecision::Reject(String)- 検出失敗理由P5bEscapeDerivedDecision::None- 該当なし
将来的な整理:
- policies/配下でpolicy箱として統一済み(Phase 96)
loop_true_read_digits_policy.rs (Phase 104/105)
現在の場所: patterns/policies/loop_true_read_digits_policy.rs
責務: loop(true) + break-only digits(read_digits_from family)の認識とルーティング
判断基準:
loop(true)である- read-digits(loop(true)) detector に一致する
ReadDigitsBreakConditionBoxが eos 条件 + digit 条件を抽出できる
出力:
PolicyDecision::Use(LoopTrueReadDigitsPolicyResult)-break_when_true := (ch == \"\") || !(digit_cond)とchallow-listPolicyDecision::Reject(String)- 検出失敗理由(Fail-Fast)PolicyDecision::None- 該当なし
body_local_policy.rs
現在の場所: patterns/body_local_policy.rs
責務: Body-local変数の昇格判断
判断基準:
- body-local変数がloop carrier候補か
- 昇格可能なパターンか(Trim, Escape, etc.)
将来的な整理:
- policies/へ移動してpolicy箱として統一
設計原則
単一判断の原則
- 各policy箱は1つのパターン判断のみ
- 複数パターンの判断は別のpolicy箱に委譲
非破壊的判断
- 入力を変更しない
- 判断結果をResultで返す(
Ok(Some(result))/Ok(None)/Err(msg))
Fail-Fast
- パターンマッチング失敗は即座に
Ok(None)を返す - エラーは明示的に
Err(msg) - Reject理由は
error_tags::freeze()でタグ付与
Decision型の統一
PolicyDecision<T>(Use / Reject / None)をSSOTにする- 例:
P5bEscapeDerivedDecision = PolicyDecision<BodyLocalDerivedRecipe>,TrimPolicyResult
使用パターン
Pattern2ルーティング(現在のパターン)
// Step 1: P5b escapeパターン判断
match classify_p5b_escape_derived(body, loop_var_name) {
P5bEscapeDerivedDecision::UseDerived(recipe) => {
// P5b escape適用
return lower_with_p5b_escape(recipe, ...);
}
P5bEscapeDerivedDecision::Reject(reason) => {
return Err(reason);
}
P5bEscapeDerivedDecision::None => {
// 次のパターンへ
}
}
// Step 2: Trimパターン判断
if let Some(trim_result) = TrimLoopLowerer::try_lower_trim_pattern(...)? {
// Trimパターン適用
return Ok(trim_result);
}
// Step 3: デフォルトパターン
Ok(default_pattern2_lowering(...))
将来の統一パターン(policies/移動後)
use patterns::policies::{P5bEscapePolicy, TrimPolicy, ConditionalStepPolicy};
// Policy boxの統一インターフェース
trait PatternPolicy {
type Decision;
fn classify(&self, context: &PatternContext) -> Self::Decision;
}
// ルーティングパイプライン
let decision = P5bEscapePolicy.classify(&ctx)
.or_else(|| TrimPolicy.classify(&ctx))
.or_else(|| ConditionalStepPolicy.classify(&ctx))
.unwrap_or(DefaultDecision);
デバッグ
ログprefixの統一
[policy/p5b-escape]- P5b escape判断[policy/trim]- Trim判断[policy/conditional-step]- ConditionalStep判断
環境変数
HAKO_JOINIR_DEBUG=1- JoinIR全般のデバッグログjoinir_dev_enabled()- 既存の制御機構
デバッグ出力例
if joinir_dev_enabled() {
eprintln!("[policy/p5b-escape] Detected escape pattern: {:?}", info);
}
命名規則
ファイル命名
<パターン名>_policy.rs- パターン判断policy箱- 例:
trim_policy.rs,escape_policy.rs,conditional_step_policy.rs
型命名
<パターン名>Decision- 判断結果型<パターン名>Policy- policy箱の構造体(将来)
列挙型パターン
pub enum Decision {
None, // 該当なし
Use(Recipe), // 適用可能
Reject(String), // 検出失敗
}
将来の拡張
Phase 95以降の候補
trim_policy.rs- Trimパターン判断をpolicies/へ移動escape_policy.rs- P5b escapeを統一インターフェースにarray_loop_policy.rs- 配列ループパターン判断map_loop_policy.rs- Mapループパターン判断conditional_step_policy.rs- ConditionalStep独立箱化
段階的な移行計画
Phase 1: ディレクトリ準備(今回)
- policies/ディレクトリ作成 ✅
- README.md作成 ✅
- mod.rs作成 ✅
Phase 2: 既存policy箱の移動(将来)
p5b_escape_derived_policy.rs→policies/escape_policy.rsbody_local_policy.rs→policies/body_local_policy.rs- trim関連ロジック抽出 →
policies/trim_policy.rs
Phase 3: インターフェース統一(将来)
PatternPolicytrait定義- Decision型の統一
- ルーティングパイプラインの実装
拡張時の注意
- README.mdにpolicy箱の責務を追加
- Decision型を統一パターンに従う
- 既存のpolicy箱との一貫性を保つ
- Fail-Fastタグを明記
参考資料
関連ドキュメント
- JoinIR アーキテクチャ概要
- JoinIR 設計マップ
- Pattern Pipeline - パターン判断の統合処理
- Escape Pattern Recognizer - escape検出ロジック
Phase Log
- Phase 92 Log - ConditionalStep
- Phase 93 Log - ConditionOnly
- Phase 94 Log - BodyLocalDerived
設計哲学(Box Theory)
箱理論の適用
- 箱にする: Policy判断を独立した箱に分離
- 境界を作る: Decisionを統一インターフェースに
- 戻せる: 段階的移行で既存コードを壊さない
- 見える化: ログprefixで判断過程を可視化
Fail-Fast原則の徹底
- フォールバック処理は原則禁止
- Reject理由を明示的に返す
- エラータグで根本原因を追跡可能に
単一責任の箱
- 1つのpolicy箱 = 1つのパターン判断
- 複数パターンの組み合わせは上位層で制御
- policy箱同士は独立・疎結合