Add dev normalized→MIR bridge for P1/P2 mini and JP _atoi

This commit is contained in:
nyash-codex
2025-12-11 22:12:46 +09:00
parent af6f95cd4b
commit a4756f3ce1
13 changed files with 539 additions and 94 deletions

View File

@ -112,3 +112,27 @@ pub fn build_jsonparser_skip_ws_structured_for_normalized_dev() -> JoinModule {
let mut lowerer = AstToJoinIrLowerer::new();
lowerer.lower_program_json(&program_json)
}
/// JsonParser _atoi 相当のミニ P2 ループを Structured で組み立てるヘルパー。
///
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_atoi_mini.program.json
pub fn build_jsonparser_atoi_structured_for_normalized_dev() -> JoinModule {
const FIXTURE: &str = include_str!(
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_atoi_mini.program.json"
);
let program_json: serde_json::Value =
serde_json::from_str(FIXTURE).expect("jsonparser atoi fixture should be valid JSON");
let mut lowerer = AstToJoinIrLowerer::new();
let module = lowerer.lower_program_json(&program_json);
if std::env::var("JOINIR_TEST_DEBUG").is_ok() {
eprintln!(
"[joinir/normalized-dev] jsonparser_atoi_mini structured module: {:#?}",
module
);
}
module
}

View File

@ -7,10 +7,14 @@ pub(crate) enum NormalizedDevShape {
Pattern1Mini,
Pattern2Mini,
JsonparserSkipWsMini,
JsonparserAtoiMini,
}
pub(crate) fn supported_shapes(module: &JoinModule) -> Vec<NormalizedDevShape> {
let mut shapes = Vec::new();
if is_jsonparser_atoi_mini(module) {
shapes.push(NormalizedDevShape::JsonparserAtoiMini);
}
if is_jsonparser_skip_ws_mini(module) {
shapes.push(NormalizedDevShape::JsonparserSkipWsMini);
}
@ -59,6 +63,35 @@ pub(crate) fn is_jsonparser_skip_ws_mini(module: &JoinModule) -> bool {
.any(|f| f.name == "jsonparser_skip_ws_mini")
}
pub(crate) fn is_jsonparser_atoi_mini(module: &JoinModule) -> bool {
if !module.is_structured() || module.functions.len() != 3 {
return false;
}
let loop_func = match find_loop_step(module) {
Some(f) => f,
None => return false,
};
if !(3..=8).contains(&loop_func.params.len()) {
return false;
}
let has_cond_jump = loop_func
.body
.iter()
.any(|inst| matches!(inst, JoinInst::Jump { cond: Some(_), .. }));
let has_tail_call = loop_func
.body
.iter()
.any(|inst| matches!(inst, JoinInst::Call { k_next: None, .. }));
has_cond_jump
&& has_tail_call
&& module
.functions
.values()
.any(|f| f.name.contains("atoi"))
}
fn find_loop_step(module: &JoinModule) -> Option<&JoinFunction> {
module
.functions