feat(joinir): Phase 170-4 Structure-based routing opt-in
Add NYASH_JOINIR_STRUCTURE_ONLY=1 environment variable to bypass function name whitelist and route purely based on loop structure. When enabled: - Skips hardcoded function name whitelist (13 entries) - Routes directly to pattern detection (LoopPatternContext) - Falls back to legacy LoopBuilder if no pattern matches This is Phase 1 of structure-based routing migration: - Phase 1: Opt-in via env flag (this commit) ✅ - Phase 2: Make structure-based default (future) - Phase 3: Remove whitelist entirely (future) Verified: - test_loop_return.hako → RC: 2 ✅ - test_trim_loop.hako → RC: 3 ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -35,53 +35,65 @@ impl MirBuilder {
|
|||||||
// Phase 195: Use unified trace
|
// Phase 195: Use unified trace
|
||||||
trace::trace().routing("router", &func_name, "try_cf_loop_joinir called");
|
trace::trace().routing("router", &func_name, "try_cf_loop_joinir called");
|
||||||
|
|
||||||
// Phase 49-4 + Phase 80: Multi-target routing
|
// Phase 170-4: Structure-based routing option
|
||||||
// - Core ON なら代表2本(print_tokens / ArrayExt.filter)は JoinIR を優先し、失敗したら LoopBuilder へフォールバック
|
// When NYASH_JOINIR_STRUCTURE_ONLY=1, skip function name whitelist
|
||||||
// - Core OFF では従来通り dev フラグで opt-in
|
// and route purely based on loop structure analysis
|
||||||
// Note: Arity does NOT include implicit `me` receiver
|
let structure_only = std::env::var("NYASH_JOINIR_STRUCTURE_ONLY")
|
||||||
// Phase 188: Add "main" routing for loop pattern expansion
|
.ok()
|
||||||
// Phase 170: Add JsonParserBox methods for selfhost validation
|
.as_deref()
|
||||||
let core_on = crate::config::env::joinir_core_enabled();
|
== Some("1");
|
||||||
let is_target = match func_name.as_str() {
|
|
||||||
"main" => true, // Phase 188-Impl-1: Enable JoinIR for main function (Pattern 1)
|
|
||||||
"JoinIrMin.main/0" => true, // Phase 188-Impl-2: Enable JoinIR for JoinIrMin.main/0 (Pattern 2)
|
|
||||||
"JsonTokenizer.print_tokens/0" => {
|
|
||||||
if core_on {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
std::env::var("HAKO_JOINIR_PRINT_TOKENS_MAIN")
|
|
||||||
.ok()
|
|
||||||
.as_deref()
|
|
||||||
== Some("1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"ArrayExtBox.filter/2" => {
|
|
||||||
if core_on {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
std::env::var("HAKO_JOINIR_ARRAY_FILTER_MAIN")
|
|
||||||
.ok()
|
|
||||||
.as_deref()
|
|
||||||
== Some("1")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Phase 170-A-1: Enable JsonParserBox methods for JoinIR routing
|
|
||||||
"JsonParserBox._trim/1" => true,
|
|
||||||
"JsonParserBox._skip_whitespace/2" => true,
|
|
||||||
"JsonParserBox._match_literal/2" => true,
|
|
||||||
"JsonParserBox._parse_string/2" => true,
|
|
||||||
"JsonParserBox._parse_array/2" => true,
|
|
||||||
"JsonParserBox._parse_object/2" => true,
|
|
||||||
// Phase 170-A-1: Test methods (simplified versions)
|
|
||||||
"TrimTest.trim/1" => true,
|
|
||||||
"Main.trim/1" => true, // Phase 171-fix: Main box variant
|
|
||||||
"Main.trim_string_simple/1" => true, // Phase 33-13: Simple trim variant
|
|
||||||
"TrimTest.main/0" => true, // Phase 170: TrimTest.main for loop pattern test
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
if !is_target {
|
if structure_only {
|
||||||
return Ok(None);
|
trace::trace().routing("router", &func_name, "Structure-only mode enabled, skipping whitelist");
|
||||||
|
} else {
|
||||||
|
// Phase 49-4 + Phase 80: Multi-target routing (legacy whitelist)
|
||||||
|
// - Core ON なら代表2本(print_tokens / ArrayExt.filter)は JoinIR を優先し、失敗したら LoopBuilder へフォールバック
|
||||||
|
// - Core OFF では従来通り dev フラグで opt-in
|
||||||
|
// Note: Arity does NOT include implicit `me` receiver
|
||||||
|
// Phase 188: Add "main" routing for loop pattern expansion
|
||||||
|
// Phase 170: Add JsonParserBox methods for selfhost validation
|
||||||
|
let core_on = crate::config::env::joinir_core_enabled();
|
||||||
|
let is_target = match func_name.as_str() {
|
||||||
|
"main" => true, // Phase 188-Impl-1: Enable JoinIR for main function (Pattern 1)
|
||||||
|
"JoinIrMin.main/0" => true, // Phase 188-Impl-2: Enable JoinIR for JoinIrMin.main/0 (Pattern 2)
|
||||||
|
"JsonTokenizer.print_tokens/0" => {
|
||||||
|
if core_on {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
std::env::var("HAKO_JOINIR_PRINT_TOKENS_MAIN")
|
||||||
|
.ok()
|
||||||
|
.as_deref()
|
||||||
|
== Some("1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"ArrayExtBox.filter/2" => {
|
||||||
|
if core_on {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
std::env::var("HAKO_JOINIR_ARRAY_FILTER_MAIN")
|
||||||
|
.ok()
|
||||||
|
.as_deref()
|
||||||
|
== Some("1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Phase 170-A-1: Enable JsonParserBox methods for JoinIR routing
|
||||||
|
"JsonParserBox._trim/1" => true,
|
||||||
|
"JsonParserBox._skip_whitespace/2" => true,
|
||||||
|
"JsonParserBox._match_literal/2" => true,
|
||||||
|
"JsonParserBox._parse_string/2" => true,
|
||||||
|
"JsonParserBox._parse_array/2" => true,
|
||||||
|
"JsonParserBox._parse_object/2" => true,
|
||||||
|
// Phase 170-A-1: Test methods (simplified versions)
|
||||||
|
"TrimTest.trim/1" => true,
|
||||||
|
"Main.trim/1" => true, // Phase 171-fix: Main box variant
|
||||||
|
"Main.trim_string_simple/1" => true, // Phase 33-13: Simple trim variant
|
||||||
|
"TrimTest.main/0" => true, // Phase 170: TrimTest.main for loop pattern test
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !is_target {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug log when routing through JoinIR Frontend
|
// Debug log when routing through JoinIR Frontend
|
||||||
|
|||||||
Reference in New Issue
Block a user