Files
hakorune/src/mir/join_ir/normalized.rs
tomoaki 86dfa30abe chore(joinir): Phase 286C-5 Step 3 - Remove unused imports
Ran `cargo fix --allow-dirty --lib` to automatically remove unused imports
across the codebase. This cleanup is standard maintenance and improves code
hygiene.

**Files Modified**:
- instruction_rewriter.rs: Removed 6 unused imports
  - block_remapper::remap_block_id
  - LoweringDecision
  - ParameterBindingBox
  - propagate_value_type_for_inst (2 occurrences)
  - apply_remapped_terminator
  - PhiAdjustment, ParameterBinding from scan_box
- Other files: Minor unused import cleanup (12 files total)

**No Functional Changes**: Pure cleanup, all tests expected to pass.

Phase 286C-5 progress: 3/4 steps complete

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:18:06 +09:00

564 lines
21 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! Minimal Normalized JoinIR model (Phase 26-H.B).
//!
//! テスト専用の極小サブセット。Pattern1 の while だけを Structured → Normalized に
//! 変換して遊ぶための足場だよ。本線の Structured→MIR 経路には影響しない。
use std::collections::BTreeMap;
use crate::mir::join_ir::{
BinOpKind, CompareOp, ConstValue, JoinIrPhase,
JoinModule, UnaryOp,
};
use crate::mir::ValueId;
#[cfg(feature = "normalized_dev")]
use std::collections::HashMap;
#[cfg(feature = "normalized_dev")]
use std::panic::{catch_unwind, AssertUnwindSafe};
#[cfg(feature = "normalized_dev")]
pub mod dev_env;
#[cfg(feature = "normalized_dev")]
pub mod dev_fixtures;
#[cfg(feature = "normalized_dev")]
pub mod fixtures;
#[cfg(feature = "normalized_dev")]
pub mod loop_step_inspector;
#[cfg(feature = "normalized_dev")]
pub mod shape_guard;
// Phase 286C: Box modularization - core normalization boxes
pub mod pattern1_normalizer;
pub mod pattern2_normalizer;
pub mod env_layout_builder;
#[cfg(feature = "normalized_dev")]
use crate::mir::join_ir::normalized::shape_guard::NormalizedDevShape;
/// 環境レイアウト(最小)。
#[derive(Debug, Clone)]
pub struct EnvLayout {
pub id: u32,
pub fields: Vec<EnvField>,
}
#[derive(Debug, Clone)]
pub struct EnvField {
pub name: String,
pub ty: Option<crate::mir::MirType>,
pub value_id: Option<ValueId>,
}
/// 正規化済み関数 ID
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct JpFuncId(pub u32);
/// 正規化済み関数Kont 兼用、is_kont で区別)。
#[derive(Debug, Clone)]
pub struct JpFunction {
pub id: JpFuncId,
pub name: String,
pub env_layout: Option<u32>,
pub body: Vec<JpInst>,
pub is_kont: bool,
}
/// 正規化済み命令(最小セット)。
#[derive(Debug, Clone)]
pub enum JpInst {
Let {
dst: ValueId,
op: JpOp,
args: Vec<ValueId>,
},
EnvLoad {
dst: ValueId,
env: ValueId,
field: usize,
},
EnvStore {
env: ValueId,
field: usize,
src: ValueId,
},
TailCallFn {
target: JpFuncId,
env: Vec<ValueId>,
},
TailCallKont {
target: JpFuncId,
env: Vec<ValueId>,
},
If {
cond: ValueId,
then_target: JpFuncId,
else_target: JpFuncId,
env: Vec<ValueId>,
},
}
/// 演算Let 用の最小サブセット)。
#[derive(Debug, Clone)]
pub enum JpOp {
Const(ConstValue),
BinOp(BinOpKind),
Unary(UnaryOp),
Compare(CompareOp),
BoxCall {
box_name: String,
method: String,
},
/// 三項演算子cond ? then : else
Select,
}
/// Normalized JoinIR モジュール(テスト専用)。
#[derive(Debug, Clone)]
pub struct NormalizedModule {
pub functions: BTreeMap<JpFuncId, JpFunction>,
pub entry: Option<JpFuncId>,
pub env_layouts: Vec<EnvLayout>,
pub phase: JoinIrPhase,
/// Structured に戻すためのスナップショット(テスト専用)。
pub structured_backup: Option<JoinModule>,
}
impl NormalizedModule {
pub fn to_structured(&self) -> Option<JoinModule> {
self.structured_backup.clone()
}
}
// Phase 286C: Re-export from pattern1_normalizer box
#[cfg(feature = "normalized_dev")]
fn verify_normalized_pattern1(module: &NormalizedModule) -> Result<(), String> {
pattern1_normalizer::Pattern1Normalizer::verify(module)
}
// Phase 286C: Re-export from pattern1_normalizer box
/// Pattern1 専用: Normalized → Structured への簡易逆変換。
pub fn normalized_pattern1_to_structured(norm: &NormalizedModule) -> JoinModule {
pattern1_normalizer::Pattern1Normalizer::to_structured(norm)
}
// Phase 286C: Re-export from pattern2_normalizer box
/// Pattern2 専用のミニ変換(最小サブセット: ループ変数1つ + break、acc などの LoopState を 1 個まで+ホスト 1 個まで)。
///
/// 制約:
/// - structured.phase は Structured であること
/// - main/loop_step/k_exit の 3 関数構成joinir_min_loop 相当)
pub fn normalize_pattern2_minimal(structured: &JoinModule) -> NormalizedModule {
pattern2_normalizer::Pattern2Normalizer::normalize(structured)
}
#[cfg(feature = "normalized_dev")]
fn normalize_pattern2_shape(
structured: &JoinModule,
target_shape: NormalizedDevShape,
) -> Result<NormalizedModule, String> {
if !structured.is_structured() {
return Err("[normalize_p2] Not structured JoinIR".to_string());
}
let shapes = shape_guard::supported_shapes(structured);
if !shapes.contains(&target_shape) {
return Err(format!(
"[normalize_p2] shape mismatch: expected {:?}, got {:?}",
target_shape, shapes
));
}
Ok(normalize_pattern2_minimal(structured))
}
/// Phase 50: selfhost token-scan P2 を Normalized に載せるdev-only
#[cfg(feature = "normalized_dev")]
pub fn normalize_selfhost_token_scan_p2(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern2_shape(structured, NormalizedDevShape::SelfhostTokenScanP2)
}
/// Phase 51: selfhost token-scan P2accum 拡張)を Normalized に載せるdev-only
#[cfg(feature = "normalized_dev")]
pub fn normalize_selfhost_token_scan_p2_accum(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern2_shape(structured, NormalizedDevShape::SelfhostTokenScanP2Accum)
}
/// Phase 47-A/B: Normalize Pattern3 if-sum shapes to Normalized JoinIR
#[cfg(feature = "normalized_dev")]
pub fn normalize_pattern3_if_sum_minimal(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern3_if_sum_shape(structured, NormalizedDevShape::Pattern3IfSumMinimal)
}
/// Phase 47-B: Normalize Pattern3 if-sum multi-carrier (sum+count) shape.
#[cfg(feature = "normalized_dev")]
pub fn normalize_pattern3_if_sum_multi_minimal(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern3_if_sum_shape(structured, NormalizedDevShape::Pattern3IfSumMulti)
}
/// Phase 47-B: Normalize JsonParser if-sum (mini) shape.
#[cfg(feature = "normalized_dev")]
pub fn normalize_pattern3_if_sum_json_minimal(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern3_if_sum_shape(structured, NormalizedDevShape::Pattern3IfSumJson)
}
/// Phase 50: selfhost if-sum P3 を Normalized に載せるdev-only
#[cfg(feature = "normalized_dev")]
pub fn normalize_selfhost_if_sum_p3(structured: &JoinModule) -> Result<NormalizedModule, String> {
normalize_pattern3_if_sum_shape(structured, NormalizedDevShape::SelfhostIfSumP3)
}
/// Phase 51: selfhost if-sum P3ext 拡張)を Normalized に載せるdev-only
#[cfg(feature = "normalized_dev")]
pub fn normalize_selfhost_if_sum_p3_ext(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern3_if_sum_shape(structured, NormalizedDevShape::SelfhostIfSumP3Ext)
}
#[cfg(feature = "normalized_dev")]
fn normalize_pattern3_if_sum_shape(
structured: &JoinModule,
target_shape: NormalizedDevShape,
) -> Result<NormalizedModule, String> {
if !structured.is_structured() {
return Err("[normalize_p3] Not structured JoinIR".to_string());
}
let shapes = shape_guard::supported_shapes(structured);
if !shapes.contains(&target_shape) {
return Err(format!(
"[normalize_p3] shape mismatch: expected {:?}, got {:?}",
target_shape, shapes
));
}
// Phase 47-B: P3 if-sum は既存の P2 ミニ正規化器で十分に表現できる
// Select/If/Compare/BinOp をそのまま JpInst に写す)。
Ok(normalize_pattern2_minimal(structured))
}
/// Phase 48-A: Pattern4 (continue) minimal ループの正規化。
///
/// ガード:
/// - structured.phase は Structured であること
/// - 対象は Pattern4ContinueMinimal のシンプル continue パターン
///
/// 実装方針:
/// - Phase 48-A minimal: P2 正規化に委譲P4 は P2 の逆制御フローなので同じインフラ利用可)
/// - TODO (Phase 48-B): P4 固有の正規化実装
/// - EnvLayout for i, count carriers
/// - HeaderCond → ContinueCheck → Updates → Tail step sequence
/// - continue = early TailCallFn (skip Updates)
#[cfg(feature = "normalized_dev")]
pub fn normalize_pattern4_continue_minimal(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern4_continue_shape(structured, NormalizedDevShape::Pattern4ContinueMinimal)
}
/// Phase 48-B: JsonParser _parse_array continue skip_ws を Normalized に載せるdev-only
#[cfg(feature = "normalized_dev")]
pub fn normalize_jsonparser_parse_array_continue_skip_ws(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern4_continue_shape(
structured,
NormalizedDevShape::JsonparserParseArrayContinueSkipWs,
)
}
/// Phase 48-B: JsonParser _parse_object continue skip_ws を Normalized に載せるdev-only
#[cfg(feature = "normalized_dev")]
pub fn normalize_jsonparser_parse_object_continue_skip_ws(
structured: &JoinModule,
) -> Result<NormalizedModule, String> {
normalize_pattern4_continue_shape(
structured,
NormalizedDevShape::JsonparserParseObjectContinueSkipWs,
)
}
#[cfg(feature = "normalized_dev")]
fn normalize_pattern4_continue_shape(
structured: &JoinModule,
target_shape: NormalizedDevShape,
) -> Result<NormalizedModule, String> {
if !structured.is_structured() {
return Err("[normalize_p4] Not structured JoinIR".to_string());
}
// Use shape detection to verify P4 shape
let shapes = shape_guard::supported_shapes(structured);
if !shapes.contains(&target_shape) {
return Err(format!(
"[normalize_p4] shape mismatch: expected {:?}, got {:?}",
target_shape, shapes
));
}
// Phase 48-B: reuse Pattern2 minimal normalizer (continue is early tail-call).
Ok(normalize_pattern2_minimal(structured))
}
// Phase 286C: Re-export from pattern2_normalizer box
/// Pattern2 専用: Normalized → Structured への簡易逆変換。
pub fn normalized_pattern2_to_structured(norm: &NormalizedModule) -> JoinModule {
pattern2_normalizer::Pattern2Normalizer::to_structured(norm)
}
// Phase 286C: Re-export from pattern2_normalizer box
#[cfg(feature = "normalized_dev")]
fn verify_normalized_pattern2(
module: &NormalizedModule,
max_env_fields: usize,
) -> Result<(), String> {
pattern2_normalizer::Pattern2Normalizer::verify(module, max_env_fields)
}
// Phase 286C: Re-export from pattern1_normalizer box
/// Pattern1 専用のミニ変換。
///
/// 制約:
/// - structured.phase は Structured であること
/// - 対象は Pattern1 のシンプル whilebreak/continue なし)
pub fn normalize_pattern1_minimal(structured: &JoinModule) -> NormalizedModule {
pattern1_normalizer::Pattern1Normalizer::normalize(structured)
}
/// Dev helper: Structured → Normalized → Structured roundtrip (Pattern1/2 minis only).
#[cfg(feature = "normalized_dev")]
pub(crate) fn normalized_dev_roundtrip_structured(
module: &JoinModule,
) -> Result<JoinModule, String> {
if !module.is_structured() {
return Err("[joinir/normalized-dev] expected Structured JoinModule".to_string());
}
let shapes = shape_guard::supported_shapes(module);
if shapes.is_empty() {
return Err(
"[joinir/normalized-dev] module shape is not supported by normalized_dev".into(),
);
}
let debug = dev_env::normalized_dev_logs_enabled() && crate::config::env::joinir_dev_enabled();
for shape in shapes {
if debug {
eprintln!(
"[joinir/normalized-dev/roundtrip] attempting {:?} normalization",
shape
);
}
let attempt = match shape {
NormalizedDevShape::Pattern1Mini => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_pattern1_minimal(module);
normalized_pattern1_to_structured(&norm)
})),
NormalizedDevShape::Pattern2Mini
| NormalizedDevShape::JsonparserSkipWsMini
| NormalizedDevShape::JsonparserSkipWsReal
| NormalizedDevShape::JsonparserAtoiMini
| NormalizedDevShape::JsonparserAtoiReal
| NormalizedDevShape::JsonparserParseNumberReal => {
catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_pattern2_minimal(module);
normalized_pattern2_to_structured(&norm)
}))
}
NormalizedDevShape::SelfhostTokenScanP2 => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_selfhost_token_scan_p2(module)
.expect("selfhost P2 normalization failed");
normalized_pattern2_to_structured(&norm)
})),
NormalizedDevShape::SelfhostTokenScanP2Accum => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_selfhost_token_scan_p2_accum(module)
.expect("selfhost P2 accum normalization failed");
normalized_pattern2_to_structured(&norm)
})),
// Phase 47-A: P3 minimal (delegates to P2 for now, but uses proper guard)
NormalizedDevShape::Pattern3IfSumMinimal => catch_unwind(AssertUnwindSafe(|| {
let norm =
normalize_pattern3_if_sum_minimal(module).expect("P3 normalization failed");
normalized_pattern2_to_structured(&norm)
})),
NormalizedDevShape::Pattern3IfSumMulti => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_pattern3_if_sum_multi_minimal(module)
.expect("P3 multi normalization failed");
normalized_pattern2_to_structured(&norm)
})),
NormalizedDevShape::Pattern3IfSumJson => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_pattern3_if_sum_json_minimal(module)
.expect("P3 json normalization failed");
normalized_pattern2_to_structured(&norm)
})),
NormalizedDevShape::SelfhostIfSumP3 => catch_unwind(AssertUnwindSafe(|| {
let norm =
normalize_selfhost_if_sum_p3(module).expect("selfhost P3 normalization failed");
normalized_pattern2_to_structured(&norm)
})),
NormalizedDevShape::SelfhostIfSumP3Ext => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_selfhost_if_sum_p3_ext(module)
.expect("selfhost P3 ext normalization failed");
normalized_pattern2_to_structured(&norm)
})),
// Phase 53: selfhost P2/P3 practical variations (delegate to existing normalizers)
NormalizedDevShape::SelfhostArgsParseP2 => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_pattern2_minimal(module);
normalized_pattern2_to_structured(&norm)
})),
NormalizedDevShape::SelfhostStmtCountP3 => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_selfhost_if_sum_p3_ext(module)
.expect("selfhost stmt_count P3 normalization failed");
normalized_pattern2_to_structured(&norm)
})),
// Phase 54: selfhost P2/P3 shape growth (delegate to existing normalizers)
NormalizedDevShape::SelfhostVerifySchemaP2 => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_pattern2_minimal(module);
normalized_pattern2_to_structured(&norm)
})),
NormalizedDevShape::SelfhostDetectFormatP3 => catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_selfhost_if_sum_p3_ext(module)
.expect("selfhost detect_format P3 normalization failed");
normalized_pattern2_to_structured(&norm)
})),
// Phase 48-A: P4 minimal (delegates to P2 for now, but uses proper guard)
NormalizedDevShape::Pattern4ContinueMinimal => catch_unwind(AssertUnwindSafe(|| {
let norm =
normalize_pattern4_continue_minimal(module).expect("P4 normalization failed");
normalized_pattern2_to_structured(&norm)
})),
NormalizedDevShape::JsonparserParseArrayContinueSkipWs => {
catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_jsonparser_parse_array_continue_skip_ws(module)
.expect("P4 array normalization failed");
normalized_pattern2_to_structured(&norm)
}))
}
NormalizedDevShape::JsonparserParseObjectContinueSkipWs => {
catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_jsonparser_parse_object_continue_skip_ws(module)
.expect("P4 object normalization failed");
normalized_pattern2_to_structured(&norm)
}))
}
// Phase 89: Continue + Early Return pattern (dev-only, delegates to P2 for now)
NormalizedDevShape::PatternContinueReturnMinimal => {
catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_pattern2_minimal(module);
normalized_pattern2_to_structured(&norm)
}))
}
// Phase 90: Parse String Composite pattern (dev-only, delegates to P2 for now)
NormalizedDevShape::ParseStringCompositeMinimal => {
catch_unwind(AssertUnwindSafe(|| {
let norm = normalize_pattern2_minimal(module);
normalized_pattern2_to_structured(&norm)
}))
}
};
match attempt {
Ok(structured) => {
if debug {
eprintln!(
"[joinir/normalized-dev/roundtrip] {:?} normalization succeeded (functions={})",
shape,
structured.functions.len()
);
}
return Ok(structured);
}
Err(_) => {
if debug {
eprintln!(
"[joinir/normalized-dev/roundtrip] {:?} normalization failed (unsupported)",
shape
);
}
}
}
}
Err("[joinir/normalized-dev] all normalization attempts failed".into())
}
#[cfg(test)]
mod tests {
use super::*;
fn build_structured_pattern1() -> JoinModule {
let mut module = JoinModule::new();
let mut loop_fn = JoinFunction::new(
JoinFuncId::new(1),
"loop_step".to_string(),
vec![ValueId(10)],
);
loop_fn.body.push(JoinInst::Compute(MirLikeInst::Const {
dst: ValueId(11),
value: ConstValue::Integer(0),
}));
loop_fn.body.push(JoinInst::Compute(MirLikeInst::BinOp {
dst: ValueId(12),
op: BinOpKind::Add,
lhs: ValueId(10),
rhs: ValueId(11),
}));
loop_fn.body.push(JoinInst::Jump {
cont: JoinContId(2),
args: vec![ValueId(12)],
cond: Some(ValueId(12)), // dummy
});
let mut k_exit =
JoinFunction::new(JoinFuncId::new(2), "k_exit".to_string(), vec![ValueId(12)]);
k_exit.body.push(JoinInst::Ret {
value: Some(ValueId(12)),
});
module.entry = Some(loop_fn.id);
module.add_function(loop_fn);
module.add_function(k_exit);
module
}
#[test]
fn normalized_pattern1_minimal_smoke() {
let structured = build_structured_pattern1();
let normalized = normalize_pattern1_minimal(&structured);
assert_eq!(normalized.phase, JoinIrPhase::Normalized);
assert!(!normalized.env_layouts.is_empty());
assert!(!normalized.functions.is_empty());
#[cfg(feature = "normalized_dev")]
{
verify_normalized_pattern1(&normalized).expect("verifier should pass");
}
let restored = normalized.to_structured().expect("backup");
assert!(restored.is_structured());
assert_eq!(restored.functions.len(), structured.functions.len());
}
#[test]
fn normalized_pattern1_roundtrip_structured_equivalent() {
let structured = build_structured_pattern1();
let normalized = normalize_pattern1_minimal(&structured);
let reconstructed = normalized_pattern1_to_structured(&normalized);
assert!(reconstructed.is_structured());
assert_eq!(reconstructed.functions.len(), structured.functions.len());
}
}