feat(joinir): Phase 33-8 Stage-1 rollout infrastructure

Add environment variable controls and debug logging for JoinIR lowering rollout.

Changes:
- Add HAKO_JOINIR_STAGE1 env var for Stage-1 function rollout control
- Add HAKO_JOINIR_DEBUG (0-3) for granular debug logging
  - Level 0: Silent (default)
  - Level 1: Basic lowering info
  - Level 2: Pattern matching details
  - Level 3: Full variable/instruction dump
- Implement 3-tier whitelist system:
  - Tier 1: Test functions (always enabled)
  - Tier 2: Stage-1 rollout (env-controlled)
  - Tier 3: Explicit approvals (validated in Phase 33-4)
- Add A/B test automation script (tools/joinir_ab_test.sh)
- Update if_merge.rs and if_select.rs with debug_level support

Environment variables (with NYASH_* fallback for compatibility):
- HAKO_JOINIR_IF_SELECT: Enable JoinIR lowering
- HAKO_JOINIR_STAGE1: Enable Stage-1 function rollout
- HAKO_JOINIR_DEBUG: Debug log level (0-3)

A/B test verification: PASSED on joinir_if_merge_{simple,multiple}.hako

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-27 09:30:54 +09:00
parent 5b7818f5c9
commit 517b20fe88
5 changed files with 211 additions and 39 deletions

View File

@ -73,15 +73,29 @@ pub fn try_lower_if_to_joinir(
return None;
}
// 2. Phase 33-7: 関数名ガード拡張(テスト + Stage-1/Stage-B 候補
let is_allowed = func.signature.name.starts_with("IfSelectTest.")
|| func.signature.name.starts_with("IfMergeTest.") // Phase 33-7
|| func.signature.name.starts_with("Stage1JsonScannerTestBox.") // Phase 33-5 test
|| func.signature.name == "JsonShapeToMap._read_value_from_pair/1"
|| func.signature.name == "Stage1JsonScannerBox.value_start_after_key_pos/2";
// Phase 33-8: デバッグログレベル取得0-3
let debug_level = crate::config::env::joinir_debug_level();
let _debug = debug || debug_level >= 1;
// 2. Phase 33-8: 関数名ガード拡張(テスト + Stage-1 rollout + 明示承認)
let is_allowed =
// Test functions (always enabled)
func.signature.name.starts_with("IfSelectTest.") ||
func.signature.name.starts_with("IfMergeTest.") ||
func.signature.name.starts_with("Stage1JsonScannerTestBox.") || // Phase 33-5 test
// Stage-1 rollout (env-controlled)
(crate::config::env::joinir_stage1_enabled() &&
func.signature.name.starts_with("Stage1")) ||
// Explicit approvals (Phase 33-4で検証済み, always on)
matches!(func.signature.name.as_str(),
"JsonShapeToMap._read_value_from_pair/1" |
"Stage1JsonScannerBox.value_start_after_key_pos/2"
);
if !is_allowed {
if debug {
if debug_level >= 2 {
eprintln!(
"[try_lower_if_to_joinir] skipping non-allowed function: {}",
func.signature.name
@ -90,15 +104,19 @@ pub fn try_lower_if_to_joinir(
return None;
}
if debug_level >= 1 {
eprintln!("[try_lower_if_to_joinir] trying to lower {}", func.signature.name);
}
// 3. Phase 33-7: IfMerge を優先的に試行(複数変数パターン)
// IfMerge が成功すればそれを返す、失敗したら Select を試行
let if_merge_lowerer = if_merge::IfMergeLowerer::new(debug);
let if_merge_lowerer = if_merge::IfMergeLowerer::new(debug_level);
if if_merge_lowerer.can_lower_to_if_merge(func, block_id) {
if let Some(result) = if_merge_lowerer.lower_if_to_if_merge(func, block_id) {
if debug {
if debug_level >= 1 {
eprintln!(
"[try_lower_if_to_joinir] IfMerge lowering used for {}",
"[try_lower_if_to_joinir] IfMerge lowering used for {}",
func.signature.name
);
}
@ -107,10 +125,10 @@ pub fn try_lower_if_to_joinir(
}
// 4. IfMerge が失敗したら Select を試行(単一変数パターン)
let if_select_lowerer = if_select::IfSelectLowerer::new(debug);
let if_select_lowerer = if_select::IfSelectLowerer::new(debug_level);
if !if_select_lowerer.can_lower_to_select(func, block_id) {
if debug {
if debug_level >= 1 {
eprintln!(
"[try_lower_if_to_joinir] pattern not matched for {}",
func.signature.name
@ -121,9 +139,9 @@ pub fn try_lower_if_to_joinir(
let result = if_select_lowerer.lower_if_to_select(func, block_id);
if result.is_some() && debug {
if result.is_some() && debug_level >= 1 {
eprintln!(
"[try_lower_if_to_joinir] Select lowering used for {}",
"[try_lower_if_to_joinir] Select lowering used for {}",
func.signature.name
);
}