refactor(mir): Phase 137-6-S2 - dev-only で canonicalizer decision を提案として受け取る
## 目的 Canonicalizer の decision を router に差し込む(既定挙動不変) ## 変更内容 ### choose_pattern_kind() に parity check 統合 - dev-only 時に Canonicalizer を呼び出し - router_choice と canonical_choice を比較 - 不一致時の動作: - strict mode (`HAKO_JOINIR_STRICT=1`): panic (Fail-Fast) - debug mode (`NYASH_JOINIR_DEV=1`): ログのみ - 既定挙動: router_choice を維持(Canonicalizer は提案のみ) ### ログ出力 ``` [choose_pattern_kind/PARITY] OK: canonical and actual agree on Pattern2Break ``` ## 効果 - ✅ Canonicalizer → Router の parity check 統合 - ✅ SSOT 入口での一致性検証 - ✅ 既定挙動完全不変(フラグOFF時) - ✅ 新 env 追加なし(既存の `joinir_dev_enabled()` と `strict_enabled()` を使用) ## テスト結果 - ✅ `cargo build --release`: 成功 - ✅ skip_whitespace: parity green ``` NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1 ./target/release/hakorune \ tools/selfhost/test_pattern3_skip_whitespace.hako → [choose_pattern_kind/PARITY] OK ``` - ✅ スモークテスト(simple_*): 5/5 PASS - ✅ 退行なし 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -36,37 +36,15 @@ pub static OPERATORS_DIV_RULES: &[(&str, &str, &str, &str)] = &[
|
|||||||
];
|
];
|
||||||
pub fn lookup_keyword(word: &str) -> Option<&'static str> {
|
pub fn lookup_keyword(word: &str) -> Option<&'static str> {
|
||||||
for (k, t) in KEYWORDS {
|
for (k, t) in KEYWORDS {
|
||||||
if *k == word { return Some(*t); }
|
if *k == word {
|
||||||
|
return Some(*t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static SYNTAX_ALLOWED_STATEMENTS: &[&str] = &[
|
pub static SYNTAX_ALLOWED_STATEMENTS: &[&str] = &[
|
||||||
"box",
|
"box", "global", "function", "static", "if", "loop", "break", "return", "print", "nowait",
|
||||||
"global",
|
"include", "local", "outbox", "try", "throw", "using", "from",
|
||||||
"function",
|
|
||||||
"static",
|
|
||||||
"if",
|
|
||||||
"loop",
|
|
||||||
"break",
|
|
||||||
"return",
|
|
||||||
"print",
|
|
||||||
"nowait",
|
|
||||||
"include",
|
|
||||||
"local",
|
|
||||||
"outbox",
|
|
||||||
"try",
|
|
||||||
"throw",
|
|
||||||
"using",
|
|
||||||
"from",
|
|
||||||
];
|
];
|
||||||
pub static SYNTAX_ALLOWED_BINOPS: &[&str] = &[
|
pub static SYNTAX_ALLOWED_BINOPS: &[&str] = &["add", "sub", "mul", "div", "and", "or", "eq", "ne"];
|
||||||
"add",
|
|
||||||
"sub",
|
|
||||||
"mul",
|
|
||||||
"div",
|
|
||||||
"and",
|
|
||||||
"or",
|
|
||||||
"eq",
|
|
||||||
"ne",
|
|
||||||
];
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ use crate::mir::ValueId;
|
|||||||
/// 将来的には Canonicalizer decision に委譲する。
|
/// 将来的には Canonicalizer decision に委譲する。
|
||||||
///
|
///
|
||||||
/// Phase 137-6-S1: 現時点では既存の router ロジック(LoopFeatures ベース)を使用
|
/// Phase 137-6-S1: 現時点では既存の router ロジック(LoopFeatures ベース)を使用
|
||||||
|
/// Phase 137-6-S2: dev-only で canonicalizer decision を提案として受け取る
|
||||||
pub(in crate::mir::builder) fn choose_pattern_kind(
|
pub(in crate::mir::builder) fn choose_pattern_kind(
|
||||||
condition: &ASTNode,
|
condition: &ASTNode,
|
||||||
body: &[ASTNode],
|
body: &[ASTNode],
|
||||||
@ -25,8 +26,51 @@ pub(in crate::mir::builder) fn choose_pattern_kind(
|
|||||||
// Phase 193: Extract features using modularized extractor
|
// Phase 193: Extract features using modularized extractor
|
||||||
let features = ast_features::extract_features(condition, body, has_continue, has_break);
|
let features = ast_features::extract_features(condition, body, has_continue, has_break);
|
||||||
|
|
||||||
// Phase 192: Classify pattern based on features
|
// Phase 192: Classify pattern based on features (既存の router 結果)
|
||||||
loop_pattern_detection::classify(&features)
|
let router_choice = loop_pattern_detection::classify(&features);
|
||||||
|
|
||||||
|
// Phase 137-6-S2: dev-only で Canonicalizer の提案を取得
|
||||||
|
if crate::config::env::joinir_dev_enabled() {
|
||||||
|
use crate::ast::Span;
|
||||||
|
use crate::mir::loop_canonicalizer::canonicalize_loop_expr;
|
||||||
|
|
||||||
|
let loop_ast = ASTNode::Loop {
|
||||||
|
condition: Box::new(condition.clone()),
|
||||||
|
body: body.to_vec(),
|
||||||
|
span: Span::unknown(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok((_skeleton, decision)) = canonicalize_loop_expr(&loop_ast) {
|
||||||
|
if let Some(canonical_choice) = decision.chosen {
|
||||||
|
// parity check
|
||||||
|
if canonical_choice != router_choice {
|
||||||
|
let msg = format!(
|
||||||
|
"[choose_pattern_kind/PARITY] router={:?}, canonicalizer={:?}",
|
||||||
|
router_choice, canonical_choice
|
||||||
|
);
|
||||||
|
|
||||||
|
if crate::config::env::joinir_dev::strict_enabled() {
|
||||||
|
// strict mode: 不一致は Fail-Fast
|
||||||
|
panic!("{}", msg);
|
||||||
|
} else {
|
||||||
|
// debug mode: ログのみ
|
||||||
|
eprintln!("{}", msg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Patterns match - success!
|
||||||
|
eprintln!(
|
||||||
|
"[choose_pattern_kind/PARITY] OK: canonical and actual agree on {:?}",
|
||||||
|
canonical_choice
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO (Phase 137-6-S3): ここで canonical_choice を返す
|
||||||
|
// 現時点では router_choice を維持(既定挙動不変)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
router_choice
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MirBuilder {
|
impl MirBuilder {
|
||||||
|
|||||||
Reference in New Issue
Block a user