Files
hakorune/src/mir/join_ir/normalized/shape_guard.rs

441 lines
14 KiB
Rust
Raw Normal View History

#![cfg(feature = "normalized_dev")]
use crate::config::env::joinir_dev_enabled;
use crate::mir::join_ir::normalized::dev_env;
use crate::mir::join_ir::{JoinFuncId, JoinFunction, JoinInst, JoinModule};
/// Phase 44: Shape capability kinds (capability-based routing)
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ShapeCapabilityKind {
/// P2 Core: Simple mini patterns (i/acc/n etc)
P2CoreSimple,
/// P2 Core: skip_whitespace mini/real
P2CoreSkipWs,
/// P2 Core: _atoi mini/real
P2CoreAtoi,
/// P2 Mid: _parse_number real (p + num_str + result)
P2MidParseNumber,
// Future: Other P2 patterns
// P2MidAtOfLoop,
// P2HeavyString,
}
/// Phase 44: Shape capability descriptor
#[derive(Debug, Clone)]
pub struct ShapeCapability {
pub kind: ShapeCapabilityKind,
// Future extensibility fields (not all used yet):
// pub pattern_kind: LoopPatternKind,
// pub loop_param_count: usize,
// pub carrier_roles: Vec<CarrierRole>,
// pub method_calls: Vec<MethodCallSignature>,
}
impl ShapeCapability {
pub fn new(kind: ShapeCapabilityKind) -> Self {
Self { kind }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NormalizedDevShape {
Pattern1Mini,
Pattern2Mini,
JsonparserSkipWsMini,
JsonparserSkipWsReal,
JsonparserAtoiMini,
JsonparserAtoiReal,
JsonparserParseNumberReal,
feat(joinir): Phase 47-A-IMPL - P3 Normalized infrastructure Implement Pattern3 (if-sum) Normalized infrastructure, extending existing P2 StepSchedule and ShapeGuard systems. Key changes: 1. StepSchedule generalization (P2 → P2/P3): - Renamed: pattern2_step_schedule.rs → step_schedule.rs - Extended StepKind enum with P3 variants: - IfCond (if condition in body) - ThenUpdates (carrier updates in then branch) - ElseUpdates (carrier updates in else branch) - Added pattern3_if_sum_schedule() function - Added unit test: test_pattern3_if_sum_schedule() - Updated module references (mod.rs, loop_with_break_minimal.rs) 2. ShapeGuard extension: - Added Pattern3IfSumMinimal variant to NormalizedDevShape - Added is_pattern3_if_sum_minimal() detector (placeholder) - Updated shape detector table - Extended capability_for_shape() mapping 3. Bridge integration: - bridge.rs: Added P3 shape handling in normalize_for_shape() - normalized.rs: Added P3 roundtrip match (uses P2 temporarily) 4. P2/P3 separation: - loop_with_break_minimal.rs: Added panic for P3 steps in P2 lowering - Clear boundary enforcement (P2 lowerer rejects P3 steps) 5. Documentation: - CURRENT_TASK.md: Phase 47-A-IMPL status - phase47-norm-p3-design.md: Implementation status section Benefits: - Reuses 90% of P2 infrastructure (ConditionEnv, CarrierInfo, ExitLine) - Clean P2/P3 separation via StepKind - Pure additive changes (no P2 behavioral changes) - Ready for Phase 47-A-LOWERING (full P3 Normalized implementation) Tests: 938/938 PASS (+1 from step_schedule unit test) - All existing P1/P2 tests pass (no regressions) - P3 test uses Structured path temporarily (proper lowering in next phase) Next phase: Implement full P3 Normalized→MIR(direct) lowering
2025-12-12 05:23:18 +09:00
// Phase 47-A: Pattern3 (if-sum) minimal
Pattern3IfSumMinimal,
}
type Detector = fn(&JoinModule) -> bool;
const SHAPE_DETECTORS: &[(NormalizedDevShape, Detector)] = &[
(NormalizedDevShape::Pattern1Mini, detectors::is_pattern1_mini),
(NormalizedDevShape::Pattern2Mini, detectors::is_pattern2_mini),
(
NormalizedDevShape::JsonparserSkipWsMini,
detectors::is_jsonparser_skip_ws_mini,
),
(
NormalizedDevShape::JsonparserSkipWsReal,
detectors::is_jsonparser_skip_ws_real,
),
(
NormalizedDevShape::JsonparserAtoiMini,
detectors::is_jsonparser_atoi_mini,
),
(
NormalizedDevShape::JsonparserAtoiReal,
detectors::is_jsonparser_atoi_real,
),
(
NormalizedDevShape::JsonparserParseNumberReal,
detectors::is_jsonparser_parse_number_real,
),
feat(joinir): Phase 47-A-IMPL - P3 Normalized infrastructure Implement Pattern3 (if-sum) Normalized infrastructure, extending existing P2 StepSchedule and ShapeGuard systems. Key changes: 1. StepSchedule generalization (P2 → P2/P3): - Renamed: pattern2_step_schedule.rs → step_schedule.rs - Extended StepKind enum with P3 variants: - IfCond (if condition in body) - ThenUpdates (carrier updates in then branch) - ElseUpdates (carrier updates in else branch) - Added pattern3_if_sum_schedule() function - Added unit test: test_pattern3_if_sum_schedule() - Updated module references (mod.rs, loop_with_break_minimal.rs) 2. ShapeGuard extension: - Added Pattern3IfSumMinimal variant to NormalizedDevShape - Added is_pattern3_if_sum_minimal() detector (placeholder) - Updated shape detector table - Extended capability_for_shape() mapping 3. Bridge integration: - bridge.rs: Added P3 shape handling in normalize_for_shape() - normalized.rs: Added P3 roundtrip match (uses P2 temporarily) 4. P2/P3 separation: - loop_with_break_minimal.rs: Added panic for P3 steps in P2 lowering - Clear boundary enforcement (P2 lowerer rejects P3 steps) 5. Documentation: - CURRENT_TASK.md: Phase 47-A-IMPL status - phase47-norm-p3-design.md: Implementation status section Benefits: - Reuses 90% of P2 infrastructure (ConditionEnv, CarrierInfo, ExitLine) - Clean P2/P3 separation via StepKind - Pure additive changes (no P2 behavioral changes) - Ready for Phase 47-A-LOWERING (full P3 Normalized implementation) Tests: 938/938 PASS (+1 from step_schedule unit test) - All existing P1/P2 tests pass (no regressions) - P3 test uses Structured path temporarily (proper lowering in next phase) Next phase: Implement full P3 Normalized→MIR(direct) lowering
2025-12-12 05:23:18 +09:00
// Phase 47-A: Pattern3 if-sum minimal
(
NormalizedDevShape::Pattern3IfSumMinimal,
detectors::is_pattern3_if_sum_minimal,
),
];
/// direct ブリッジで扱う shapedev 限定)。
pub(crate) fn direct_shapes(module: &JoinModule) -> Vec<NormalizedDevShape> {
let shapes = detect_shapes(module);
log_shapes("direct", &shapes);
shapes
}
/// Structured→Normalized の対象 shapedev 限定)。
pub(crate) fn supported_shapes(module: &JoinModule) -> Vec<NormalizedDevShape> {
let shapes = detect_shapes(module);
log_shapes("roundtrip", &shapes);
shapes
}
/// Phase 44: Map NormalizedDevShape to ShapeCapability
pub fn capability_for_shape(shape: &NormalizedDevShape) -> ShapeCapability {
use NormalizedDevShape::*;
use ShapeCapabilityKind::*;
let kind = match shape {
Pattern2Mini => P2CoreSimple,
JsonparserSkipWsMini | JsonparserSkipWsReal => P2CoreSkipWs,
JsonparserAtoiMini | JsonparserAtoiReal => P2CoreAtoi,
JsonparserParseNumberReal => P2MidParseNumber,
Pattern1Mini => P2CoreSimple, // Also core simple pattern
feat(joinir): Phase 47-A-IMPL - P3 Normalized infrastructure Implement Pattern3 (if-sum) Normalized infrastructure, extending existing P2 StepSchedule and ShapeGuard systems. Key changes: 1. StepSchedule generalization (P2 → P2/P3): - Renamed: pattern2_step_schedule.rs → step_schedule.rs - Extended StepKind enum with P3 variants: - IfCond (if condition in body) - ThenUpdates (carrier updates in then branch) - ElseUpdates (carrier updates in else branch) - Added pattern3_if_sum_schedule() function - Added unit test: test_pattern3_if_sum_schedule() - Updated module references (mod.rs, loop_with_break_minimal.rs) 2. ShapeGuard extension: - Added Pattern3IfSumMinimal variant to NormalizedDevShape - Added is_pattern3_if_sum_minimal() detector (placeholder) - Updated shape detector table - Extended capability_for_shape() mapping 3. Bridge integration: - bridge.rs: Added P3 shape handling in normalize_for_shape() - normalized.rs: Added P3 roundtrip match (uses P2 temporarily) 4. P2/P3 separation: - loop_with_break_minimal.rs: Added panic for P3 steps in P2 lowering - Clear boundary enforcement (P2 lowerer rejects P3 steps) 5. Documentation: - CURRENT_TASK.md: Phase 47-A-IMPL status - phase47-norm-p3-design.md: Implementation status section Benefits: - Reuses 90% of P2 infrastructure (ConditionEnv, CarrierInfo, ExitLine) - Clean P2/P3 separation via StepKind - Pure additive changes (no P2 behavioral changes) - Ready for Phase 47-A-LOWERING (full P3 Normalized implementation) Tests: 938/938 PASS (+1 from step_schedule unit test) - All existing P1/P2 tests pass (no regressions) - P3 test uses Structured path temporarily (proper lowering in next phase) Next phase: Implement full P3 Normalized→MIR(direct) lowering
2025-12-12 05:23:18 +09:00
// Phase 47-A: P3 minimal maps to P2CoreSimple for now (future: P3CoreSimple)
Pattern3IfSumMinimal => P2CoreSimple,
};
ShapeCapability::new(kind)
}
/// Phase 46: Canonical shapes that ALWAYS use Normalized→MIR(direct)
/// regardless of feature flags or mode.
///
/// Canonical set (Phase 46):
/// - P2-Core: Pattern2Mini, JsonparserSkipWsMini, JsonparserSkipWsReal, JsonparserAtoiMini
/// - P2-Mid: JsonparserAtoiReal, JsonparserParseNumberReal
///
/// P3/P4 patterns are NOT canonical (deferred to NORM-P3/NORM-P4 phases).
pub fn is_canonical_shape(shape: &NormalizedDevShape) -> bool {
use NormalizedDevShape::*;
matches!(
shape,
Pattern2Mini
| JsonparserSkipWsMini
| JsonparserSkipWsReal
| JsonparserAtoiMini
// Phase 46: Add P2-Mid patterns
| JsonparserAtoiReal
| JsonparserParseNumberReal
)
}
/// Phase 44: Check if capability kind is in P2-Core family
///
/// This checks capability-level membership, not granular canonical status.
/// Use `is_canonical_shape()` for exact canonical filtering.
pub fn is_p2_core_capability(cap: &ShapeCapability) -> bool {
use ShapeCapabilityKind::*;
matches!(cap.kind, P2CoreSimple | P2CoreSkipWs | P2CoreAtoi | P2MidParseNumber)
}
/// Phase 44: Check if capability is supported by Normalized dev
pub fn is_supported_by_normalized(cap: &ShapeCapability) -> bool {
// Currently same as P2-Core family
is_p2_core_capability(cap)
}
/// canonical常時 Normalized 経路を通す)対象。
/// Phase 46: Extract canonical shapes from JoinModule.
///
/// Canonical set (P2-Core + P2-Mid):
/// - Pattern2Mini, skip_ws mini/real, atoi mini/real, parse_number real
///
/// These shapes ALWAYS use Normalized→MIR(direct) regardless of mode.
/// P3/P4 patterns are NOT canonical (future NORM-P3/NORM-P4 phases).
pub(crate) fn canonical_shapes(module: &JoinModule) -> Vec<NormalizedDevShape> {
let shapes: Vec<_> = detect_shapes(module)
.into_iter()
.filter(|s| is_canonical_shape(s))
.collect();
log_shapes("canonical", &shapes);
shapes
}
#[allow(dead_code)]
pub(crate) fn is_direct_supported(module: &JoinModule) -> bool {
!detect_shapes(module).is_empty()
}
fn detect_shapes(module: &JoinModule) -> Vec<NormalizedDevShape> {
let mut shapes: Vec<_> = SHAPE_DETECTORS
.iter()
.filter_map(|(shape, detector)| if detector(module) { Some(*shape) } else { None })
.collect();
// Pattern1 は「最小の後方互換」なので、より具体的な shape が見つかった場合は外しておく。
if shapes.len() > 1 {
shapes.retain(|s| *s != NormalizedDevShape::Pattern1Mini);
}
shapes
}
// --- 判定ロジック(共通) ---
mod detectors {
use super::*;
pub(super) fn is_pattern1_mini(module: &JoinModule) -> bool {
module.is_structured() && find_loop_step(module).is_some()
}
pub(super) fn is_pattern2_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 !(1..=3).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
}
pub(super) fn is_jsonparser_skip_ws_mini(module: &JoinModule) -> bool {
is_pattern2_mini(module)
&& module
.functions
.values()
.any(|f| f.name == "jsonparser_skip_ws_mini")
}
pub(crate) fn is_jsonparser_skip_ws_real(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 !(2..=6).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 == "jsonparser_skip_ws_real")
}
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 == "jsonparser_atoi_mini")
}
pub(crate) fn is_jsonparser_atoi_real(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..=10).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 == "jsonparser_atoi_real")
}
pub(crate) fn is_jsonparser_parse_number_real(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..=12).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 == "jsonparser_parse_number_real")
}
feat(joinir): Phase 47-A-IMPL - P3 Normalized infrastructure Implement Pattern3 (if-sum) Normalized infrastructure, extending existing P2 StepSchedule and ShapeGuard systems. Key changes: 1. StepSchedule generalization (P2 → P2/P3): - Renamed: pattern2_step_schedule.rs → step_schedule.rs - Extended StepKind enum with P3 variants: - IfCond (if condition in body) - ThenUpdates (carrier updates in then branch) - ElseUpdates (carrier updates in else branch) - Added pattern3_if_sum_schedule() function - Added unit test: test_pattern3_if_sum_schedule() - Updated module references (mod.rs, loop_with_break_minimal.rs) 2. ShapeGuard extension: - Added Pattern3IfSumMinimal variant to NormalizedDevShape - Added is_pattern3_if_sum_minimal() detector (placeholder) - Updated shape detector table - Extended capability_for_shape() mapping 3. Bridge integration: - bridge.rs: Added P3 shape handling in normalize_for_shape() - normalized.rs: Added P3 roundtrip match (uses P2 temporarily) 4. P2/P3 separation: - loop_with_break_minimal.rs: Added panic for P3 steps in P2 lowering - Clear boundary enforcement (P2 lowerer rejects P3 steps) 5. Documentation: - CURRENT_TASK.md: Phase 47-A-IMPL status - phase47-norm-p3-design.md: Implementation status section Benefits: - Reuses 90% of P2 infrastructure (ConditionEnv, CarrierInfo, ExitLine) - Clean P2/P3 separation via StepKind - Pure additive changes (no P2 behavioral changes) - Ready for Phase 47-A-LOWERING (full P3 Normalized implementation) Tests: 938/938 PASS (+1 from step_schedule unit test) - All existing P1/P2 tests pass (no regressions) - P3 test uses Structured path temporarily (proper lowering in next phase) Next phase: Implement full P3 Normalized→MIR(direct) lowering
2025-12-12 05:23:18 +09:00
/// Phase 47-A: Check if module matches Pattern3 if-sum minimal shape
pub(crate) fn is_pattern3_if_sum_minimal(module: &JoinModule) -> bool {
feat(joinir): Phase 47-A-LOWERING - P3 Normalized→MIR(direct) Implement full Pattern3 (if-sum) Normalized→MIR(direct) support, completing the P3 minimal implementation. Key changes: 1. P3 Shape Detection (shape_guard.rs): - Implemented is_pattern3_if_sum_minimal() with structure-based detection - Detects P3 characteristics: - Has Compare instruction (loop condition) - Has Select instruction (conditional carrier update) - Has tail call (Call with k_next: None) - Reasonable param count (2-4 for i, sum carriers) - Handles both JoinInst::Select and Compute(MirLikeInst::Select) - Added unit test: test_detect_pattern3_if_sum_minimal_shape ✅ 2. P3 Normalization Function (normalized.rs): - Implemented normalize_pattern3_if_sum_minimal() - Guards: Validates Structured JoinIR + P3 shape detection - Phase 47-A minimal: Delegates to P2 normalization (works for simple cases) - Updated normalized_dev_roundtrip_structured() integration - Returns Result<NormalizedModule, String> for proper error handling 3. Bridge Integration (bridge.rs): - Updated normalize_for_shape() to call P3 normalization - No changes needed to direct.rs (already handles P3 instructions) 4. Integration Tests (normalized_joinir_min.rs): - Added test_phase47a_pattern3_if_sum_minimal_normalization - Tests Structured→Normalized transformation - Verifies shape detection + normalization succeeds - Validates function count and phase correctness - Added test_phase47a_pattern3_if_sum_minimal_runner - Basic smoke test for P3 fixture validity - Verifies 3-function structure and entry point Benefits: - P3 now uses Normalized→MIR(direct) pipeline (same as P1/P2) - Structure-based detection (no name-based heuristics) - Minimal implementation (delegates to P2 for simplicity) - Pure additive (no P1/P2 behavioral changes) Tests: 938/938 PASS (lib), shape_guard P3 test PASS - test_detect_pattern3_if_sum_minimal_shape ✅ - test_phase47a_pattern3_if_sum_minimal_normalization ✅ - test_phase47a_pattern3_if_sum_minimal_runner ✅ Next phase: Phase 47-B (proper P3-specific normalization, array_filter, multi-carrier) Design note: This minimal implementation reuses P2 normalization for simplicity. Proper P3-specific normalization (IfCond, ThenUpdates, ElseUpdates step sequence) will be implemented in Phase 47-B when needed for more complex P3 patterns.
2025-12-12 05:53:23 +09:00
// Structure-based detection (avoid name-based heuristics)
// Must have exactly 3 functions: main, loop_step, k_exit
if !module.is_structured() || module.functions.len() != 3 {
return false;
}
// Find loop_step function
let loop_step = match find_loop_step(module) {
Some(f) => f,
None => return false,
};
// P3 characteristics:
// - Has Compare instruction (loop condition)
// - Has Select instruction (conditional carrier update: if-then-else)
// - Has tail call (Call with k_next: None)
let has_compare = loop_step.body.iter().any(|inst| {
matches!(
inst,
JoinInst::Compute(crate::mir::join_ir::MirLikeInst::Compare { .. })
)
});
// Phase 220: Select can be either JoinInst::Select or Compute(MirLikeInst::Select)
let has_select = loop_step.body.iter().any(|inst| match inst {
JoinInst::Select { .. } => true,
JoinInst::Compute(mir_inst) => matches!(
mir_inst,
crate::mir::join_ir::MirLikeInst::Select { .. }
),
_ => false,
});
let has_tail_call = loop_step
.body
.iter()
.any(|inst| matches!(inst, JoinInst::Call { k_next: None, .. }));
// P3 minimal has 2-4 params (i, sum, possibly n)
let reasonable_param_count = (2..=4).contains(&loop_step.params.len());
has_compare && has_select && has_tail_call && reasonable_param_count
feat(joinir): Phase 47-A-IMPL - P3 Normalized infrastructure Implement Pattern3 (if-sum) Normalized infrastructure, extending existing P2 StepSchedule and ShapeGuard systems. Key changes: 1. StepSchedule generalization (P2 → P2/P3): - Renamed: pattern2_step_schedule.rs → step_schedule.rs - Extended StepKind enum with P3 variants: - IfCond (if condition in body) - ThenUpdates (carrier updates in then branch) - ElseUpdates (carrier updates in else branch) - Added pattern3_if_sum_schedule() function - Added unit test: test_pattern3_if_sum_schedule() - Updated module references (mod.rs, loop_with_break_minimal.rs) 2. ShapeGuard extension: - Added Pattern3IfSumMinimal variant to NormalizedDevShape - Added is_pattern3_if_sum_minimal() detector (placeholder) - Updated shape detector table - Extended capability_for_shape() mapping 3. Bridge integration: - bridge.rs: Added P3 shape handling in normalize_for_shape() - normalized.rs: Added P3 roundtrip match (uses P2 temporarily) 4. P2/P3 separation: - loop_with_break_minimal.rs: Added panic for P3 steps in P2 lowering - Clear boundary enforcement (P2 lowerer rejects P3 steps) 5. Documentation: - CURRENT_TASK.md: Phase 47-A-IMPL status - phase47-norm-p3-design.md: Implementation status section Benefits: - Reuses 90% of P2 infrastructure (ConditionEnv, CarrierInfo, ExitLine) - Clean P2/P3 separation via StepKind - Pure additive changes (no P2 behavioral changes) - Ready for Phase 47-A-LOWERING (full P3 Normalized implementation) Tests: 938/938 PASS (+1 from step_schedule unit test) - All existing P1/P2 tests pass (no regressions) - P3 test uses Structured path temporarily (proper lowering in next phase) Next phase: Implement full P3 Normalized→MIR(direct) lowering
2025-12-12 05:23:18 +09:00
}
pub(super) fn find_loop_step(module: &JoinModule) -> Option<&JoinFunction> {
module
.functions
.values()
.find(|f| f.name == "loop_step")
.or_else(|| module.functions.get(&JoinFuncId::new(1)))
}
}
fn log_shapes(tag: &str, shapes: &[NormalizedDevShape]) {
if shapes.is_empty() {
return;
}
if dev_env::normalized_dev_logs_enabled() && joinir_dev_enabled() {
eprintln!("[joinir/normalized-dev/shape] {}: {:?}", tag, shapes);
}
}
feat(joinir): Phase 47-A-LOWERING - P3 Normalized→MIR(direct) Implement full Pattern3 (if-sum) Normalized→MIR(direct) support, completing the P3 minimal implementation. Key changes: 1. P3 Shape Detection (shape_guard.rs): - Implemented is_pattern3_if_sum_minimal() with structure-based detection - Detects P3 characteristics: - Has Compare instruction (loop condition) - Has Select instruction (conditional carrier update) - Has tail call (Call with k_next: None) - Reasonable param count (2-4 for i, sum carriers) - Handles both JoinInst::Select and Compute(MirLikeInst::Select) - Added unit test: test_detect_pattern3_if_sum_minimal_shape ✅ 2. P3 Normalization Function (normalized.rs): - Implemented normalize_pattern3_if_sum_minimal() - Guards: Validates Structured JoinIR + P3 shape detection - Phase 47-A minimal: Delegates to P2 normalization (works for simple cases) - Updated normalized_dev_roundtrip_structured() integration - Returns Result<NormalizedModule, String> for proper error handling 3. Bridge Integration (bridge.rs): - Updated normalize_for_shape() to call P3 normalization - No changes needed to direct.rs (already handles P3 instructions) 4. Integration Tests (normalized_joinir_min.rs): - Added test_phase47a_pattern3_if_sum_minimal_normalization - Tests Structured→Normalized transformation - Verifies shape detection + normalization succeeds - Validates function count and phase correctness - Added test_phase47a_pattern3_if_sum_minimal_runner - Basic smoke test for P3 fixture validity - Verifies 3-function structure and entry point Benefits: - P3 now uses Normalized→MIR(direct) pipeline (same as P1/P2) - Structure-based detection (no name-based heuristics) - Minimal implementation (delegates to P2 for simplicity) - Pure additive (no P1/P2 behavioral changes) Tests: 938/938 PASS (lib), shape_guard P3 test PASS - test_detect_pattern3_if_sum_minimal_shape ✅ - test_phase47a_pattern3_if_sum_minimal_normalization ✅ - test_phase47a_pattern3_if_sum_minimal_runner ✅ Next phase: Phase 47-B (proper P3-specific normalization, array_filter, multi-carrier) Design note: This minimal implementation reuses P2 normalization for simplicity. Proper P3-specific normalization (IfCond, ThenUpdates, ElseUpdates step sequence) will be implemented in Phase 47-B when needed for more complex P3 patterns.
2025-12-12 05:53:23 +09:00
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "normalized_dev")]
#[test]
fn test_detect_pattern3_if_sum_minimal_shape() {
use crate::mir::join_ir::normalized::fixtures::build_pattern3_if_sum_min_structured_for_normalized_dev;
let module = build_pattern3_if_sum_min_structured_for_normalized_dev();
// Should detect Pattern3IfSumMinimal shape
assert!(
detectors::is_pattern3_if_sum_minimal(&module),
"pattern3_if_sum_minimal fixture should be detected"
);
let shapes = detect_shapes(&module);
assert!(
shapes.contains(&NormalizedDevShape::Pattern3IfSumMinimal),
"detect_shapes() should include Pattern3IfSumMinimal, got: {:?}",
shapes
);
}
}