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
This commit is contained in:
@ -87,6 +87,13 @@
|
||||
- JsonParser P2 ライン(_skip_whitespace/_atoi/_parse_number)全て canonical Normalized 化完了。
|
||||
- P3/P4 Normalized 対応は NORM-P3/NORM-P4 フェーズで実施(今回スコープ外)。
|
||||
- 937/937 tests PASS。
|
||||
- **Phase 47-A-IMPL(実装中 2025-12-12)**:
|
||||
- StepScheduleBox 汎用化: pattern2_step_schedule.rs → step_schedule.rs リネーム
|
||||
- P3 StepKind 追加: IfCond, ThenUpdates, ElseUpdates(P2 lowering との分離完了)
|
||||
- ShapeGuard: Pattern3IfSumMinimal 検出追加(placeholder stub実装)
|
||||
- Normalized bridge: P3 shape handling 追加(P2 normalization 使用)
|
||||
- 938/938 tests PASS(regression なし)
|
||||
- 次ステップ: Phase 47-A-LOWERING で full P3 Normalized lowering 実装
|
||||
- **Phase 45-NORM-MODE(実装済み✅ 2025-12-12)**:
|
||||
- JoinIR モード一本化: バラバラだったフラグ/feature を `JoinIrMode` enum に集約(StructuredOnly / NormalizedDev / NormalizedCanonical)。
|
||||
- `current_joinir_mode()` でモード取得、bridge/runner で `normalized_dev_enabled()` → mode pattern matching に移行。
|
||||
|
||||
@ -155,6 +155,27 @@ loop(i < arr.length()) {
|
||||
|
||||
Complex P3 patterns from selfhost compiler (deferred to later phase).
|
||||
|
||||
## Implementation Status
|
||||
|
||||
**Phase 47-A-PREP** (✅ Complete, commit 42ecd7a7):
|
||||
- Fixture added: `pattern3_if_sum_minimal` in `normalized/fixtures.rs`
|
||||
- Test stub added: `test_normalized_pattern3_if_sum_minimal_runner_dev_switch_matches_structured`
|
||||
- Basic infrastructure for P3 development mode testing
|
||||
|
||||
**Phase 47-A-IMPL** (✅ Complete, 2025-12-12):
|
||||
- ✅ StepSchedule renamed and extended: `pattern2_step_schedule.rs` → `step_schedule.rs`
|
||||
- ✅ P3 StepKind added: `IfCond`, `ThenUpdates`, `ElseUpdates`
|
||||
- ✅ Pattern2 lowering separation: P3 steps panic in P2 lowering (clean boundary)
|
||||
- ✅ ShapeGuard: `Pattern3IfSumMinimal` detection added (placeholder stub)
|
||||
- ✅ Normalized bridge: P3 shape handling in `normalize_for_shape()` and roundtrip
|
||||
- ✅ 938/938 tests PASS (no regressions)
|
||||
- ⏳ TODO: Full P3 Normalized lowering (Phase 47-A-LOWERING)
|
||||
|
||||
**Next Phase** (Phase 47-A-LOWERING):
|
||||
- Implement `lower_pattern3_if_sum_minimal()` fully
|
||||
- Generate Normalized JpInst for P3 structure (If branching, conditional updates)
|
||||
- Test VM output comparison (Normalized vs Structured)
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### Phase 47-A: Minimal sum_count (dev-only)
|
||||
|
||||
@ -70,7 +70,7 @@ use crate::mir::join_ir::lowering::join_value_space::JoinValueSpace;
|
||||
use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv;
|
||||
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::pattern2_step_schedule::{
|
||||
use crate::mir::join_ir::lowering::step_schedule::{
|
||||
build_pattern2_schedule, Pattern2ScheduleContext, Pattern2StepKind,
|
||||
};
|
||||
use crate::mir::join_ir::lowering::update_env::UpdateEnv;
|
||||
@ -667,6 +667,10 @@ pub(crate) fn lower_loop_with_break_minimal(
|
||||
Pattern2StepKind::BreakCheck => loop_step_func.body.append(&mut break_block),
|
||||
Pattern2StepKind::Updates => loop_step_func.body.append(&mut carrier_update_block),
|
||||
Pattern2StepKind::Tail => loop_step_func.body.append(&mut tail_block),
|
||||
// Phase 47-A: P3 steps not used in P2 lowering (handled in Pattern3 lowerer)
|
||||
Pattern2StepKind::IfCond | Pattern2StepKind::ThenUpdates | Pattern2StepKind::ElseUpdates => {
|
||||
panic!("Pattern3 step kinds should not appear in Pattern2 lowering");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ pub(crate) mod loop_view_builder; // Phase 33-23: Loop lowering dispatch
|
||||
pub mod loop_with_break_minimal; // Phase 188-Impl-2: Pattern 2 minimal lowerer
|
||||
pub mod loop_with_continue_minimal;
|
||||
pub mod method_call_lowerer; // Phase 224-B: MethodCall lowering (metadata-driven)
|
||||
pub(crate) mod pattern2_step_schedule; // Phase 39: Pattern2 evaluation order scheduler
|
||||
pub(crate) mod step_schedule; // Phase 47-A: Generic step scheduler for P2/P3 (renamed from pattern2_step_schedule)
|
||||
pub mod method_return_hint; // Phase 83: P3-D 既知メソッド戻り値型推論箱
|
||||
pub mod scope_manager; // Phase 231: Unified variable scope management // Phase 195: Pattern 4 minimal lowerer
|
||||
// Phase 242-EX-A: loop_with_if_phi_minimal removed - replaced by loop_with_if_phi_if_sum
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
//! Pattern 2 step scheduler (StepScheduleBox).
|
||||
//! Phase 47-A: Generic step scheduling for Pattern2/Pattern3 loops
|
||||
//!
|
||||
//! Decides the evaluation order for Pattern 2 lowering without hardcoding it
|
||||
//! inside the lowerer. This keeps the lowerer focused on emitting fragments,
|
||||
//! while this box decides how to interleave them (e.g., body-local init before
|
||||
//! break checks when the break depends on body-local values).
|
||||
//! Determines evaluation order for loop steps (header cond, body init, break check, etc).
|
||||
//! Used by both P2 (break) and P3 (if-sum) patterns.
|
||||
//!
|
||||
//! This keeps the lowerer focused on emitting fragments, while this box decides
|
||||
//! how to interleave them (e.g., body-local init before break checks when the
|
||||
//! break depends on body-local values).
|
||||
|
||||
use crate::config::env;
|
||||
use crate::config::env::joinir_dev::joinir_test_debug_enabled;
|
||||
@ -13,11 +15,17 @@ use crate::mir::join_ir::lowering::loop_body_local_env::LoopBodyLocalEnv;
|
||||
/// Steps that can be reordered by the scheduler.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum Pattern2StepKind {
|
||||
HeaderCond,
|
||||
BodyInit,
|
||||
BreakCheck,
|
||||
Updates,
|
||||
Tail,
|
||||
// P2 (Pattern2 Break) steps
|
||||
HeaderCond, // loop(cond)
|
||||
BodyInit, // local ch = ...
|
||||
BreakCheck, // if (cond) break
|
||||
Updates, // sum = sum + 1
|
||||
Tail, // i = i + 1
|
||||
|
||||
// Phase 47-A: P3 (Pattern3 If-Sum) steps
|
||||
IfCond, // if (cond) in body
|
||||
ThenUpdates, // carrier updates in then branch
|
||||
ElseUpdates, // carrier updates in else branch (if any)
|
||||
}
|
||||
|
||||
impl Pattern2StepKind {
|
||||
@ -28,6 +36,10 @@ impl Pattern2StepKind {
|
||||
Pattern2StepKind::BreakCheck => "break",
|
||||
Pattern2StepKind::Updates => "updates",
|
||||
Pattern2StepKind::Tail => "tail",
|
||||
// Phase 47-A: P3 steps
|
||||
Pattern2StepKind::IfCond => "if-cond",
|
||||
Pattern2StepKind::ThenUpdates => "then-updates",
|
||||
Pattern2StepKind::ElseUpdates => "else-updates",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,6 +148,17 @@ fn log_schedule(ctx: &Pattern2ScheduleContext, schedule: &Pattern2StepSchedule)
|
||||
);
|
||||
}
|
||||
|
||||
/// Phase 47-A: Generate step schedule for Pattern3 (if-sum) loops
|
||||
pub(crate) fn pattern3_if_sum_schedule() -> Vec<Pattern2StepKind> {
|
||||
vec![
|
||||
Pattern2StepKind::HeaderCond, // loop(i < n)
|
||||
Pattern2StepKind::IfCond, // if (i > 0)
|
||||
Pattern2StepKind::ThenUpdates, // sum = sum + i
|
||||
// ElseUpdates omitted for minimal (no else branch)
|
||||
Pattern2StepKind::Tail, // i = i + 1
|
||||
]
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@ -221,4 +244,14 @@ mod tests {
|
||||
);
|
||||
assert_eq!(schedule.reason(), "body-local break dependency");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pattern3_if_sum_schedule() {
|
||||
let schedule = pattern3_if_sum_schedule();
|
||||
assert_eq!(schedule.len(), 4);
|
||||
assert_eq!(schedule[0], Pattern2StepKind::HeaderCond);
|
||||
assert_eq!(schedule[1], Pattern2StepKind::IfCond);
|
||||
assert_eq!(schedule[2], Pattern2StepKind::ThenUpdates);
|
||||
assert_eq!(schedule[3], Pattern2StepKind::Tail);
|
||||
}
|
||||
}
|
||||
@ -905,6 +905,11 @@ pub(crate) fn normalized_dev_roundtrip_structured(
|
||||
let norm = normalize_pattern2_minimal(module);
|
||||
normalized_pattern2_to_structured(&norm)
|
||||
})),
|
||||
// Phase 47-A: P3 minimal uses P2 normalization for now
|
||||
NormalizedDevShape::Pattern3IfSumMinimal => catch_unwind(AssertUnwindSafe(|| {
|
||||
let norm = normalize_pattern2_minimal(module);
|
||||
normalized_pattern2_to_structured(&norm)
|
||||
})),
|
||||
};
|
||||
|
||||
match attempt {
|
||||
|
||||
@ -50,6 +50,8 @@ pub enum NormalizedDevShape {
|
||||
JsonparserAtoiMini,
|
||||
JsonparserAtoiReal,
|
||||
JsonparserParseNumberReal,
|
||||
// Phase 47-A: Pattern3 (if-sum) minimal
|
||||
Pattern3IfSumMinimal,
|
||||
}
|
||||
|
||||
type Detector = fn(&JoinModule) -> bool;
|
||||
@ -77,6 +79,11 @@ const SHAPE_DETECTORS: &[(NormalizedDevShape, Detector)] = &[
|
||||
NormalizedDevShape::JsonparserParseNumberReal,
|
||||
detectors::is_jsonparser_parse_number_real,
|
||||
),
|
||||
// Phase 47-A: Pattern3 if-sum minimal
|
||||
(
|
||||
NormalizedDevShape::Pattern3IfSumMinimal,
|
||||
detectors::is_pattern3_if_sum_minimal,
|
||||
),
|
||||
];
|
||||
|
||||
/// direct ブリッジで扱う shape(dev 限定)。
|
||||
@ -104,6 +111,8 @@ pub fn capability_for_shape(shape: &NormalizedDevShape) -> ShapeCapability {
|
||||
JsonparserAtoiMini | JsonparserAtoiReal => P2CoreAtoi,
|
||||
JsonparserParseNumberReal => P2MidParseNumber,
|
||||
Pattern1Mini => P2CoreSimple, // Also core simple pattern
|
||||
// Phase 47-A: P3 minimal maps to P2CoreSimple for now (future: P3CoreSimple)
|
||||
Pattern3IfSumMinimal => P2CoreSimple,
|
||||
};
|
||||
|
||||
ShapeCapability::new(kind)
|
||||
@ -338,6 +347,18 @@ mod detectors {
|
||||
.any(|f| f.name == "jsonparser_parse_number_real")
|
||||
}
|
||||
|
||||
/// Phase 47-A: Check if module matches Pattern3 if-sum minimal shape
|
||||
pub(crate) fn is_pattern3_if_sum_minimal(module: &JoinModule) -> bool {
|
||||
// For now, simple heuristic:
|
||||
// - Has Pattern3 structure (if-sum)
|
||||
// - Single carrier (sum)
|
||||
// - Simple loop condition
|
||||
|
||||
// TODO: Implement proper detection based on fixture
|
||||
// For Phase 47-A, this will be called explicitly in tests
|
||||
false // Placeholder - will be refined in later commits
|
||||
}
|
||||
|
||||
pub(super) fn find_loop_step(module: &JoinModule) -> Option<&JoinFunction> {
|
||||
module
|
||||
.functions
|
||||
|
||||
@ -72,6 +72,10 @@ fn normalize_for_shape(
|
||||
| NormalizedDevShape::JsonparserParseNumberReal => {
|
||||
catch_unwind(AssertUnwindSafe(|| normalize_pattern2_minimal(module)))
|
||||
}
|
||||
// Phase 47-A: P3 minimal normalization (stub - will use P2 for now)
|
||||
NormalizedDevShape::Pattern3IfSumMinimal => {
|
||||
catch_unwind(AssertUnwindSafe(|| normalize_pattern2_minimal(module)))
|
||||
}
|
||||
};
|
||||
|
||||
match result {
|
||||
|
||||
Reference in New Issue
Block a user