Phase 76 introduces type-safe promotion tracking via promoted_bindings (BindingId→BindingId map). Replaces fragile string matching hacks with compiler-checked identity mapping. Changes: - carrier_info.rs: Added promoted_bindings field and resolution methods - pattern4_carrier_analyzer.rs: Updated for BindingId integration - pattern_pipeline.rs: Carrier resolution via promoted_bindings - loop_with_break_minimal/tests.rs: Added promoted_bindings tests - normalized/fixtures.rs: Extended with Phase 76 fixtures Tests: 5/5 new unit tests PASS (record/resolve/merge/default/overwrite) Tests: lib 958/958 PASS, normalized_dev 54/54 PASS (no regressions) Design: Dual-path (BindingId OR name) enables gradual Phase 77+ transition. 🤖 Generated with Claude Code Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
820 lines
28 KiB
Rust
820 lines
28 KiB
Rust
#![cfg(feature = "normalized_dev")]
|
||
|
||
use crate::ast::{ASTNode, BinaryOperator, LiteralValue, Span};
|
||
use crate::mir::join_ir::frontend::AstToJoinIrLowerer;
|
||
use crate::mir::join_ir::lowering::condition_env::ConditionEnv;
|
||
use crate::mir::join_ir::lowering::join_value_space::JoinValueSpace;
|
||
use crate::mir::join_ir::lowering::loop_scope_shape::LoopScopeShape;
|
||
use crate::mir::join_ir::lowering::loop_update_analyzer::UpdateExpr;
|
||
use crate::mir::join_ir::lowering::loop_with_break_minimal::lower_loop_with_break_minimal;
|
||
use crate::mir::join_ir::lowering::loop_with_if_phi_if_sum::lower_if_sum_pattern;
|
||
use crate::mir::join_ir::{
|
||
BinOpKind, CompareOp, ConstValue, JoinFuncId, JoinFunction, JoinInst, JoinModule, MirLikeInst,
|
||
UnaryOp,
|
||
};
|
||
use crate::mir::{BasicBlockId, ValueId};
|
||
use crate::{config::env::joinir_dev_enabled, config::env::joinir_test_debug_enabled};
|
||
use std::collections::{BTreeMap, BTreeSet};
|
||
|
||
fn const_i64(func: &mut JoinFunction, dst: ValueId, value: i64) {
|
||
func.body.push(JoinInst::Compute(MirLikeInst::Const {
|
||
dst,
|
||
value: ConstValue::Integer(value),
|
||
}));
|
||
}
|
||
|
||
fn compare(func: &mut JoinFunction, dst: ValueId, op: CompareOp, lhs: ValueId, rhs: ValueId) {
|
||
func.body.push(JoinInst::Compute(MirLikeInst::Compare { dst, op, lhs, rhs }));
|
||
}
|
||
|
||
fn unary_not(func: &mut JoinFunction, dst: ValueId, operand: ValueId) {
|
||
func.body.push(JoinInst::Compute(MirLikeInst::UnaryOp {
|
||
dst,
|
||
op: UnaryOp::Not,
|
||
operand,
|
||
}));
|
||
}
|
||
|
||
fn bin_add(func: &mut JoinFunction, dst: ValueId, lhs: ValueId, rhs: ValueId) {
|
||
func.body.push(JoinInst::Compute(MirLikeInst::BinOp {
|
||
dst,
|
||
op: BinOpKind::Add,
|
||
lhs,
|
||
rhs,
|
||
}));
|
||
}
|
||
|
||
fn select(func: &mut JoinFunction, dst: ValueId, cond: ValueId, then_val: ValueId, else_val: ValueId) {
|
||
func.body.push(JoinInst::Compute(MirLikeInst::Select {
|
||
dst,
|
||
cond,
|
||
then_val,
|
||
else_val,
|
||
}));
|
||
}
|
||
|
||
/// Structured Pattern2 (joinir_min_loop 相当) をテスト用に生成するヘルパー。
|
||
pub fn build_pattern2_minimal_structured() -> JoinModule {
|
||
let loop_cond = ASTNode::BinaryOp {
|
||
operator: BinaryOperator::Less,
|
||
left: Box::new(ASTNode::Variable {
|
||
name: "i".to_string(),
|
||
span: Span::unknown(),
|
||
}),
|
||
right: Box::new(ASTNode::Literal {
|
||
value: LiteralValue::Integer(3),
|
||
span: Span::unknown(),
|
||
}),
|
||
span: Span::unknown(),
|
||
};
|
||
|
||
let break_cond = ASTNode::BinaryOp {
|
||
operator: BinaryOperator::GreaterEqual,
|
||
left: Box::new(ASTNode::Variable {
|
||
name: "i".to_string(),
|
||
span: Span::unknown(),
|
||
}),
|
||
right: Box::new(ASTNode::Literal {
|
||
value: LiteralValue::Integer(2),
|
||
span: Span::unknown(),
|
||
}),
|
||
span: Span::unknown(),
|
||
};
|
||
|
||
let mut scope = LoopScopeShape {
|
||
header: BasicBlockId(0),
|
||
body: BasicBlockId(1),
|
||
latch: BasicBlockId(2),
|
||
exit: BasicBlockId(3),
|
||
pinned: BTreeSet::new(),
|
||
carriers: BTreeSet::new(),
|
||
body_locals: BTreeSet::new(),
|
||
exit_live: BTreeSet::new(),
|
||
progress_carrier: None,
|
||
variable_definitions: BTreeMap::new(),
|
||
};
|
||
scope.pinned.insert("i".to_string());
|
||
|
||
let mut condition_env = ConditionEnv::new();
|
||
condition_env.insert("i".to_string(), ValueId(100));
|
||
|
||
let carrier_info = crate::mir::join_ir::lowering::carrier_info::CarrierInfo {
|
||
loop_var_name: "i".to_string(),
|
||
loop_var_id: ValueId(1),
|
||
carriers: vec![],
|
||
trim_helper: None,
|
||
promoted_loopbodylocals: vec![],
|
||
#[cfg(feature = "normalized_dev")]
|
||
promoted_bindings: std::collections::BTreeMap::new(),
|
||
};
|
||
|
||
let carrier_updates: BTreeMap<String, UpdateExpr> = BTreeMap::new();
|
||
let mut join_value_space = JoinValueSpace::new();
|
||
|
||
let (module, _) = lower_loop_with_break_minimal(
|
||
scope,
|
||
&loop_cond,
|
||
&break_cond,
|
||
&condition_env,
|
||
&carrier_info,
|
||
&carrier_updates,
|
||
&[],
|
||
None,
|
||
&mut join_value_space,
|
||
)
|
||
.expect("pattern2 minimal lowering should succeed");
|
||
|
||
module
|
||
}
|
||
|
||
/// Pattern2 ブレークループ(fixture ベース)を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/phase-34-joinir-frontend/fixtures/loop_frontend_break.program.json
|
||
pub fn build_pattern2_break_fixture_structured() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/phase-34-joinir-frontend/fixtures/loop_frontend_break.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value =
|
||
serde_json::from_str(FIXTURE).expect("fixture JSON should be valid");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
lowerer.lower_program_json(&program_json)
|
||
}
|
||
|
||
/// JsonParser 由来のミニ P2 ループ(空白スキップ相当)を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_skip_ws_mini.program.json
|
||
pub fn build_jsonparser_skip_ws_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_skip_ws_mini.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value =
|
||
serde_json::from_str(FIXTURE).expect("jsonparser skip_ws fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
lowerer.lower_program_json(&program_json)
|
||
}
|
||
|
||
/// JsonParser _skip_whitespace 本体相当の P2 ループを Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_skip_ws_real.program.json
|
||
pub fn build_jsonparser_skip_ws_real_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_skip_ws_real.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value =
|
||
serde_json::from_str(FIXTURE).expect("jsonparser skip_ws real fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] jsonparser_skip_ws_real structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// JsonParser _parse_number 本体相当の P2 ループを Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_parse_number_real.program.json
|
||
pub fn build_jsonparser_parse_number_real_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_parse_number_real.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value =
|
||
serde_json::from_str(FIXTURE).expect("jsonparser parse_number real fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] jsonparser_parse_number_real structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// selfhost token-scan 系の P2 ループを Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_token_scan_p2.program.json
|
||
pub fn build_selfhost_token_scan_p2_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_token_scan_p2.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value =
|
||
serde_json::from_str(FIXTURE).expect("selfhost token_scan P2 fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] selfhost_token_scan_p2 structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// selfhost token-scan 系の P2 ループ(accum 拡張)を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_token_scan_p2_accum.program.json
|
||
pub fn build_selfhost_token_scan_p2_accum_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_token_scan_p2_accum.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value = serde_json::from_str(FIXTURE)
|
||
.expect("selfhost token_scan P2 accum fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] selfhost_token_scan_p2_accum structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// Phase 47-B: Pattern3 if-sum (multi carrier) を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/pattern3_if_sum_multi_min.program.json
|
||
pub fn build_pattern3_if_sum_multi_min_structured_for_normalized_dev() -> JoinModule {
|
||
// 手書き JoinIR(i/sum/count の 3 キャリア)
|
||
let mut module = JoinModule::new();
|
||
let mut next_id = 0u32;
|
||
let mut alloc = || {
|
||
let id = ValueId(next_id);
|
||
next_id += 1;
|
||
id
|
||
};
|
||
|
||
let main_id = JoinFuncId::new(0);
|
||
let loop_id = JoinFuncId::new(1);
|
||
let exit_id = JoinFuncId::new(2);
|
||
|
||
// main: init i/sum/count = 0 → tail call loop_step
|
||
let i0 = alloc();
|
||
let sum0 = alloc();
|
||
let count0 = alloc();
|
||
let mut main = JoinFunction::new(main_id, "main".to_string(), vec![]);
|
||
const_i64(&mut main, i0, 0);
|
||
const_i64(&mut main, sum0, 0);
|
||
const_i64(&mut main, count0, 0);
|
||
main.body.push(JoinInst::Call {
|
||
func: loop_id,
|
||
args: vec![i0, sum0, count0],
|
||
k_next: None,
|
||
dst: None,
|
||
});
|
||
module.add_function(main);
|
||
|
||
// loop_step params: i, sum, count
|
||
let i_param = alloc();
|
||
let sum_param = alloc();
|
||
let count_param = alloc();
|
||
let mut loop_step = JoinFunction::new(
|
||
loop_id,
|
||
"loop_step".to_string(),
|
||
vec![i_param, sum_param, count_param],
|
||
);
|
||
|
||
// loop condition: i < 3
|
||
let limit_const = alloc();
|
||
let cmp_loop = alloc();
|
||
let exit_cond = alloc();
|
||
const_i64(&mut loop_step, limit_const, 3);
|
||
compare(
|
||
&mut loop_step,
|
||
cmp_loop,
|
||
CompareOp::Lt,
|
||
i_param,
|
||
limit_const,
|
||
);
|
||
unary_not(&mut loop_step, exit_cond, cmp_loop);
|
||
loop_step.body.push(JoinInst::Jump {
|
||
cont: exit_id.as_cont(),
|
||
args: vec![sum_param, count_param],
|
||
cond: Some(exit_cond),
|
||
});
|
||
|
||
// if condition: i > 0
|
||
let cond_cmp = alloc();
|
||
let zero_const = alloc();
|
||
const_i64(&mut loop_step, zero_const, 0);
|
||
compare(
|
||
&mut loop_step,
|
||
cond_cmp,
|
||
CompareOp::Gt,
|
||
i_param,
|
||
zero_const,
|
||
);
|
||
|
||
// then: sum = sum + 1, count = count + 1
|
||
let one_const = alloc();
|
||
let sum_then = alloc();
|
||
let count_then = alloc();
|
||
const_i64(&mut loop_step, one_const, 1);
|
||
bin_add(&mut loop_step, sum_then, sum_param, one_const);
|
||
bin_add(&mut loop_step, count_then, count_param, one_const);
|
||
|
||
// else: identity
|
||
let sum_else = alloc();
|
||
let count_else = alloc();
|
||
bin_add(&mut loop_step, sum_else, sum_param, zero_const);
|
||
bin_add(&mut loop_step, count_else, count_param, zero_const);
|
||
|
||
// select
|
||
let sum_new = alloc();
|
||
let count_new = alloc();
|
||
select(&mut loop_step, sum_new, cond_cmp, sum_then, sum_else);
|
||
select(&mut loop_step, count_new, cond_cmp, count_then, count_else);
|
||
|
||
// counter update: i = i + 1
|
||
let one_const2 = alloc();
|
||
let i_next = alloc();
|
||
const_i64(&mut loop_step, one_const2, 1);
|
||
bin_add(&mut loop_step, i_next, i_param, one_const2);
|
||
|
||
loop_step.body.push(JoinInst::Call {
|
||
func: loop_id,
|
||
args: vec![i_next, sum_new, count_new],
|
||
k_next: None,
|
||
dst: None,
|
||
});
|
||
module.add_function(loop_step);
|
||
|
||
// k_exit(sum, count)
|
||
let sum_final = alloc();
|
||
let count_final = alloc();
|
||
let mut k_exit = JoinFunction::new(exit_id, "k_exit".to_string(), vec![sum_final, count_final]);
|
||
k_exit.body.push(JoinInst::Ret {
|
||
value: Some(sum_final),
|
||
});
|
||
module.add_function(k_exit);
|
||
|
||
module.entry = Some(main_id);
|
||
module.phase = crate::mir::join_ir::JoinIrPhase::Structured;
|
||
module
|
||
}
|
||
|
||
/// Phase 47-B: JsonParser if-sum mini を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_if_sum_min.program.json
|
||
pub fn build_pattern3_json_if_sum_min_structured_for_normalized_dev() -> JoinModule {
|
||
// 手書き JoinIR(i/sum の 2 キャリア、JsonParser 由来の簡約 if-sum)
|
||
let mut module = JoinModule::new();
|
||
let mut next_id = 0u32;
|
||
let mut alloc = || {
|
||
let id = ValueId(next_id);
|
||
next_id += 1;
|
||
id
|
||
};
|
||
|
||
let main_id = JoinFuncId::new(0);
|
||
let loop_id = JoinFuncId::new(1);
|
||
let exit_id = JoinFuncId::new(2);
|
||
|
||
// main: init i/sum = 0 → tail call loop_step
|
||
let i0 = alloc();
|
||
let sum0 = alloc();
|
||
let mut main = JoinFunction::new(main_id, "main".to_string(), vec![]);
|
||
main.body.push(JoinInst::Compute(MirLikeInst::Const {
|
||
dst: i0,
|
||
value: ConstValue::Integer(0),
|
||
}));
|
||
main.body.push(JoinInst::Compute(MirLikeInst::Const {
|
||
dst: sum0,
|
||
value: ConstValue::Integer(0),
|
||
}));
|
||
main.body.push(JoinInst::Call {
|
||
func: loop_id,
|
||
args: vec![i0, sum0],
|
||
k_next: None,
|
||
dst: None,
|
||
});
|
||
module.add_function(main);
|
||
|
||
// loop_step params: i, sum
|
||
let i_param = alloc();
|
||
let sum_param = alloc();
|
||
let mut loop_step = JoinFunction::new(loop_id, "loop_step".to_string(), vec![i_param, sum_param]);
|
||
|
||
// loop condition: i < 5
|
||
let limit_const = alloc();
|
||
let cmp_loop = alloc();
|
||
let exit_cond = alloc();
|
||
loop_step
|
||
.body
|
||
.push(JoinInst::Compute(MirLikeInst::Const {
|
||
dst: limit_const,
|
||
value: ConstValue::Integer(5),
|
||
}));
|
||
compare(
|
||
&mut loop_step,
|
||
cmp_loop,
|
||
CompareOp::Lt,
|
||
i_param,
|
||
limit_const,
|
||
);
|
||
unary_not(&mut loop_step, exit_cond, cmp_loop);
|
||
loop_step.body.push(JoinInst::Jump {
|
||
cont: exit_id.as_cont(),
|
||
args: vec![sum_param],
|
||
cond: Some(exit_cond),
|
||
});
|
||
|
||
// if condition: i > 0
|
||
let cond_cmp = alloc();
|
||
let zero_const = alloc();
|
||
const_i64(&mut loop_step, zero_const, 0);
|
||
compare(
|
||
&mut loop_step,
|
||
cond_cmp,
|
||
CompareOp::Gt,
|
||
i_param,
|
||
zero_const,
|
||
);
|
||
|
||
// then: sum = sum + i
|
||
let sum_then = alloc();
|
||
bin_add(&mut loop_step, sum_then, sum_param, i_param);
|
||
|
||
// else: identity sum
|
||
let sum_else = alloc();
|
||
bin_add(&mut loop_step, sum_else, sum_param, zero_const);
|
||
|
||
// select
|
||
let sum_new = alloc();
|
||
select(&mut loop_step, sum_new, cond_cmp, sum_then, sum_else);
|
||
|
||
// counter update: i = i + 1
|
||
let one_const = alloc();
|
||
let i_next = alloc();
|
||
const_i64(&mut loop_step, one_const, 1);
|
||
bin_add(&mut loop_step, i_next, i_param, one_const);
|
||
|
||
loop_step.body.push(JoinInst::Call {
|
||
func: loop_id,
|
||
args: vec![i_next, sum_new],
|
||
k_next: None,
|
||
dst: None,
|
||
});
|
||
module.add_function(loop_step);
|
||
|
||
// k_exit(sum)
|
||
let sum_final = alloc();
|
||
let mut k_exit = JoinFunction::new(exit_id, "k_exit".to_string(), vec![sum_final]);
|
||
k_exit.body.push(JoinInst::Ret {
|
||
value: Some(sum_final),
|
||
});
|
||
module.add_function(k_exit);
|
||
|
||
module.entry = Some(main_id);
|
||
module.phase = crate::mir::join_ir::JoinIrPhase::Structured;
|
||
module
|
||
}
|
||
|
||
/// selfhost if-sum P3 を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_if_sum_p3.program.json
|
||
pub fn build_selfhost_if_sum_p3_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_if_sum_p3.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value =
|
||
serde_json::from_str(FIXTURE).expect("selfhost if_sum P3 fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] selfhost_if_sum_p3 structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// selfhost if-sum P3(ext 拡張)を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_if_sum_p3_ext.program.json
|
||
pub fn build_selfhost_if_sum_p3_ext_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_if_sum_p3_ext.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value = serde_json::from_str(FIXTURE)
|
||
.expect("selfhost if_sum P3 ext fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] selfhost_if_sum_p3_ext structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// selfhost args-parse P2(Phase 53)を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_args_parse_p2.program.json
|
||
pub fn build_selfhost_args_parse_p2_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_args_parse_p2.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value = serde_json::from_str(FIXTURE)
|
||
.expect("selfhost args_parse P2 fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] selfhost_args_parse_p2 structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// selfhost stmt-count P3(Phase 53)を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_stmt_count_p3.program.json
|
||
pub fn build_selfhost_stmt_count_p3_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/selfhost_stmt_count_p3.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value = serde_json::from_str(FIXTURE)
|
||
.expect("selfhost stmt_count P3 fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] selfhost_stmt_count_p3 structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// 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 joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] jsonparser_atoi_mini structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// JsonParser _atoi 本体相当の P2 ループを Structured で組み立てるヘルパー。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_atoi_real.program.json
|
||
pub fn build_jsonparser_atoi_real_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_atoi_real.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value =
|
||
serde_json::from_str(FIXTURE).expect("jsonparser atoi real fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] jsonparser_atoi_real structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// Pattern3 if-sum minimal ループ(phase212_if_sum_min.hako 相当)を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Phase 47-A: P3 Normalized の最小ケース検証用(dev-only)。
|
||
pub fn build_pattern3_if_sum_min_structured_for_normalized_dev() -> JoinModule {
|
||
fn var(name: &str) -> ASTNode {
|
||
ASTNode::Variable {
|
||
name: name.to_string(),
|
||
span: Span::unknown(),
|
||
}
|
||
}
|
||
|
||
fn int_lit(value: i64) -> ASTNode {
|
||
ASTNode::Literal {
|
||
value: LiteralValue::Integer(value),
|
||
span: Span::unknown(),
|
||
}
|
||
}
|
||
|
||
fn bin(op: BinaryOperator, left: ASTNode, right: ASTNode) -> ASTNode {
|
||
ASTNode::BinaryOp {
|
||
operator: op,
|
||
left: Box::new(left),
|
||
right: Box::new(right),
|
||
span: Span::unknown(),
|
||
}
|
||
}
|
||
|
||
fn assignment(target: ASTNode, value: ASTNode) -> ASTNode {
|
||
ASTNode::Assignment {
|
||
target: Box::new(target),
|
||
value: Box::new(value),
|
||
span: Span::unknown(),
|
||
}
|
||
}
|
||
|
||
// Minimal if-sum pattern:
|
||
// loop(i < 3) {
|
||
// if (i > 0) { sum = sum + 1 } else { sum = sum + 0 }
|
||
// i = i + 1
|
||
// }
|
||
let loop_condition = bin(BinaryOperator::Less, var("i"), int_lit(3));
|
||
let if_condition = bin(BinaryOperator::Greater, var("i"), int_lit(0));
|
||
|
||
let then_update = assignment(
|
||
var("sum"),
|
||
bin(BinaryOperator::Add, var("sum"), int_lit(1)),
|
||
);
|
||
let else_update = assignment(
|
||
var("sum"),
|
||
bin(BinaryOperator::Add, var("sum"), int_lit(0)),
|
||
);
|
||
let counter_update = assignment(
|
||
var("i"),
|
||
bin(BinaryOperator::Add, var("i"), int_lit(1)),
|
||
);
|
||
|
||
let if_stmt = ASTNode::If {
|
||
condition: Box::new(if_condition),
|
||
then_body: vec![then_update],
|
||
else_body: Some(vec![else_update]),
|
||
span: Span::unknown(),
|
||
};
|
||
let body = vec![if_stmt.clone(), counter_update];
|
||
|
||
let mut join_value_space = JoinValueSpace::new();
|
||
let mut cond_env = ConditionEnv::new();
|
||
|
||
// Phase 220-D: ConditionEnv には少なくともループ変数 i を登録しておく。
|
||
let i_id = join_value_space.alloc_param();
|
||
cond_env.insert("i".to_string(), i_id);
|
||
|
||
let (module, _meta) =
|
||
lower_if_sum_pattern(&loop_condition, &if_stmt, &body, &cond_env, &mut join_value_space)
|
||
.expect("if-sum lowering should succeed for minimal pattern3");
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] pattern3_if_sum_min structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// Pattern4 continue minimal ループ(pattern4_continue_min 相当)を Structured で組み立てるヘルパー。
|
||
///
|
||
/// Phase 48-A: P4 Normalized の最小ケース検証用(dev-only)。
|
||
/// 単純な continue パターン(i == 2 でスキップ)。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/pattern4_continue_min.program.json
|
||
pub fn build_pattern4_continue_min_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/pattern4_continue_min.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value =
|
||
serde_json::from_str(FIXTURE).expect("pattern4_continue_min fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] pattern4_continue_min structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// JsonParser _parse_array の whitespace continue ループを Structured で組み立てるヘルパー(dev-only)。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_parse_array_continue_skip_ws.program.json
|
||
pub fn build_jsonparser_parse_array_continue_skip_ws_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_parse_array_continue_skip_ws.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value = serde_json::from_str(FIXTURE)
|
||
.expect("jsonparser_parse_array_continue_skip_ws fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] jsonparser_parse_array_continue_skip_ws structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// JsonParser _parse_object の whitespace continue ループを Structured で組み立てるヘルパー(dev-only)。
|
||
///
|
||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_parse_object_continue_skip_ws.program.json
|
||
pub fn build_jsonparser_parse_object_continue_skip_ws_structured_for_normalized_dev() -> JoinModule {
|
||
const FIXTURE: &str = include_str!(
|
||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/jsonparser_parse_object_continue_skip_ws.program.json"
|
||
);
|
||
|
||
let program_json: serde_json::Value = serde_json::from_str(FIXTURE)
|
||
.expect("jsonparser_parse_object_continue_skip_ws fixture should be valid JSON");
|
||
|
||
let mut lowerer = AstToJoinIrLowerer::new();
|
||
let module = lowerer.lower_program_json(&program_json);
|
||
|
||
if joinir_dev_enabled() && joinir_test_debug_enabled() {
|
||
eprintln!(
|
||
"[joinir/normalized-dev] jsonparser_parse_object_continue_skip_ws structured module: {:#?}",
|
||
module
|
||
);
|
||
}
|
||
|
||
module
|
||
}
|
||
|
||
/// まとめて import したいとき用のプレリュード。
|
||
pub mod prelude {
|
||
pub use super::{
|
||
build_jsonparser_atoi_real_structured_for_normalized_dev,
|
||
build_jsonparser_atoi_structured_for_normalized_dev,
|
||
build_jsonparser_parse_array_continue_skip_ws_structured_for_normalized_dev,
|
||
build_jsonparser_parse_number_real_structured_for_normalized_dev,
|
||
build_jsonparser_parse_object_continue_skip_ws_structured_for_normalized_dev,
|
||
build_jsonparser_skip_ws_real_structured_for_normalized_dev,
|
||
build_jsonparser_skip_ws_structured_for_normalized_dev,
|
||
build_pattern2_break_fixture_structured, build_pattern2_minimal_structured,
|
||
build_pattern3_if_sum_min_structured_for_normalized_dev,
|
||
build_pattern3_if_sum_multi_min_structured_for_normalized_dev,
|
||
build_pattern3_json_if_sum_min_structured_for_normalized_dev,
|
||
build_pattern4_continue_min_structured_for_normalized_dev,
|
||
build_selfhost_if_sum_p3_ext_structured_for_normalized_dev,
|
||
build_selfhost_if_sum_p3_structured_for_normalized_dev,
|
||
build_selfhost_token_scan_p2_accum_structured_for_normalized_dev,
|
||
build_selfhost_token_scan_p2_structured_for_normalized_dev,
|
||
};
|
||
}
|