phase29ao(p2): composer coreplan via normalizer (unconnected)

This commit is contained in:
2025-12-30 04:25:24 +09:00
parent 5f965f9f80
commit 5318cec972
5 changed files with 122 additions and 10 deletions

View File

@ -18,12 +18,9 @@ Scope: Repo root の旧リンク互換。現行の入口は `docs/development/cu
**CorePlan migration 道筋 SSOT**
`docs/development/current/main/design/coreplan-migration-roadmap-ssot.md` が移行タスクの Done 判定の入口。
**Next implementation (CorePlan composition, P2 planned)**
**Next implementation (CorePlan composition, P3 planned)**
`docs/development/current/main/phases/phase-29ao/README.md`
**Next implementation (Phase 29ao P2)**
`docs/development/current/main/phases/phase-29ao/P2-COREPLAN-COMPOSER-VIA-NORMALIZER-INSTRUCTIONS.md`
**2025-12-29: Phase 29am P0 COMPLETE (CorePlan If/Exit lowerer/verifier)**
CorePlan の If/Exit を lowerer/verifier で扱えるようにして、CorePlan 移行の土台を作った。

View File

@ -2,7 +2,7 @@
## Current Focus: Phase 29aoCorePlan composition
Next: Phase 29ao P2CoreLoop skeleton → CorePlan
Next: Phase 29ao P3CoreLoop skeleton → CorePlan
運用ルール: integration filter で phase143_* は回さないJoinIR 回帰は phase29ae pack のみ)
運用ルール: phase286_pattern9_* は legacy pack (SKIP) を使う
移行道筋 SSOT: `docs/development/current/main/design/coreplan-migration-roadmap-ssot.md`
@ -17,6 +17,11 @@ Next: Phase 29ao P2CoreLoop skeleton → CorePlan
- 変更: `src/mir/builder/control_flow/plan/composer/mod.rs` / `docs/development/current/main/phases/phase-29ao/README.md` / `docs/development/current/main/10-Now.md` / `docs/development/current/main/30-Backlog.md` / `CURRENT_TASK.md`
- 検証: `cargo build --release` / `./tools/smokes/v2/run.sh --profile quick` / `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh`
**2025-12-30: Phase 29ao P2 完了**
- 目的: `CanonicalLoopFacts → DomainPlan → PlanNormalizer → CorePlan` の bridge を未接続で固定
- 変更: `src/mir/builder/control_flow/plan/composer/mod.rs` / `docs/development/current/main/phases/phase-29ao/README.md` / `docs/development/current/main/10-Now.md` / `docs/development/current/main/30-Backlog.md` / `CURRENT_TASK.md`
- 検証: `cargo build --release` / `./tools/smokes/v2/run.sh --profile quick` / `./tools/smokes/v2/profiles/integration/joinir/phase29ae_regression_pack_vm.sh`
**2025-12-29: Phase 29an P15 完了**
- 目的: P0P14 の成果を closeout 形式でまとめ、次フェーズPhase 29ao入口を固定
- 変更: `docs/development/current/main/phases/phase-29an/README.md` / `docs/development/current/main/10-Now.md` / `docs/development/current/main/30-Backlog.md` / `CURRENT_TASK.md`

View File

@ -15,7 +15,7 @@ Related:
- **Phase 29aoactive: CorePlan composition from Skeleton/Feature**
- 入口: `docs/development/current/main/phases/phase-29ao/README.md`
- 状況: P0/P1 ✅ 完了 / Next: P2
- 状況: P0/P1/P2 ✅ 完了 / Next: P3
- **Phase 29af✅ COMPLETE: Boundary hygiene / regression entrypoint / carrier layout SSOT**
- 入口: `docs/development/current/main/phases/phase-29af/README.md`

View File

@ -28,10 +28,13 @@ GateSSOT:
- `CorePlan``BasicBlockId/ValueId/Frag` を要求するため、Facts→合成の段階で **どこが allocation を持つか**を SSOT として固定する
- まずは “bridge” として、composer が `CanonicalLoopFacts` から `DomainPlan`(既存語彙)を構築して `PlanNormalizer` を呼べる形まで整える(未接続のまま)
## P2: Composer→Normalizer bridge未接続・仕様不変
- 指示書: `docs/development/current/main/phases/phase-29ao/P2-COREPLAN-COMPOSER-VIA-NORMALIZER-INSTRUCTIONS.md`
- ねらい: `CanonicalLoopFacts → DomainPlan → PlanNormalizer → CorePlan` の橋渡しを未接続で固定
## Nextplanned
- P2: Composer→Normalizer bridge未接続のまま `CanonicalLoopFacts→DomainPlan→CorePlan` を固定)
- 指示書: `docs/development/current/main/phases/phase-29ao/P2-COREPLAN-COMPOSER-VIA-NORMALIZER-INSTRUCTIONS.md`
- P3: CoreLoop skeletonpreheader/header/body/exit`CorePlan` 語彙で直接生成effects/phis/frag は “最小で正しい”)
- P4: ExitMap presence を `Frag/ExitMap` と結ぶbreak/continue/return を feature 合成へ寄せる)
- P5: Cleanup presence を ExitKind 単位で wireeffect/cleanup SSOT に従う、観測差分なし)

View File

@ -1,9 +1,11 @@
//! Phase 29ao P0: CorePlan composer scaffold (CanonicalLoopFacts -> CorePlan)
use super::{CorePlan, DomainPlan, Pattern1SimpleWhilePlan};
use super::{normalizer::PlanNormalizer, CorePlan, DomainPlan, Pattern1SimpleWhilePlan};
use crate::mir::builder::control_flow::plan::facts::skeleton_facts::SkeletonKind;
use crate::mir::builder::control_flow::joinir::patterns::router::LoopPatternContext;
use crate::mir::builder::control_flow::plan::normalize::CanonicalLoopFacts;
use crate::mir::builder::control_flow::plan::planner::Freeze;
use crate::mir::builder::MirBuilder;
#[allow(dead_code)]
pub(in crate::mir::builder) fn try_compose_domain_plan_from_canonical_facts(
@ -24,6 +26,21 @@ pub(in crate::mir::builder) fn try_compose_domain_plan_from_canonical_facts(
)))
}
#[allow(dead_code)]
pub(in crate::mir::builder) fn try_compose_core_plan_via_normalizer(
builder: &mut MirBuilder,
facts: &CanonicalLoopFacts,
ctx: &LoopPatternContext,
) -> Result<Option<CorePlan>, String> {
let domain = match try_compose_domain_plan_from_canonical_facts(facts) {
Ok(Some(domain)) => domain,
Ok(None) => return Ok(None),
Err(freeze) => return Err(freeze.to_string()),
};
let core = PlanNormalizer::normalize(builder, domain, ctx)?;
Ok(Some(core))
}
#[allow(dead_code)]
pub(in crate::mir::builder) fn try_compose_core_plan_from_canonical_facts(
facts: &CanonicalLoopFacts,
@ -38,7 +55,9 @@ pub(in crate::mir::builder) fn try_compose_core_plan_from_canonical_facts(
#[cfg(test)]
mod tests {
use super::{
try_compose_core_plan_from_canonical_facts, try_compose_domain_plan_from_canonical_facts,
try_compose_core_plan_from_canonical_facts,
try_compose_core_plan_via_normalizer,
try_compose_domain_plan_from_canonical_facts,
};
use crate::ast::{ASTNode, BinaryOperator, LiteralValue, Span};
use crate::mir::builder::control_flow::plan::facts::feature_facts::LoopFeatureFacts;
@ -52,6 +71,9 @@ mod tests {
};
use crate::mir::builder::control_flow::plan::normalize::canonicalize_loop_facts;
use crate::mir::builder::control_flow::plan::DomainPlan;
use crate::mir::builder::control_flow::joinir::patterns::router::LoopPatternContext;
use crate::mir::builder::MirBuilder;
use crate::mir::MirType;
fn v(name: &str) -> ASTNode {
ASTNode::Variable {
@ -162,4 +184,89 @@ mod tests {
try_compose_domain_plan_from_canonical_facts(&canonical).expect("Ok");
assert!(plan.is_none());
}
#[test]
fn composer_bridge_normalizes_to_coreplan_for_pattern1() {
let pattern1 = Pattern1SimpleWhileFacts {
loop_var: "i".to_string(),
condition: ASTNode::BinaryOp {
operator: BinaryOperator::Less,
left: Box::new(v("i")),
right: Box::new(lit_int(3)),
span: Span::unknown(),
},
loop_increment: ASTNode::BinaryOp {
operator: BinaryOperator::Add,
left: Box::new(v("i")),
right: Box::new(lit_int(1)),
span: Span::unknown(),
},
};
let facts = LoopFacts {
condition_shape: ConditionShape::Unknown,
step_shape: StepShape::Unknown,
skeleton: SkeletonFacts {
kind: SkeletonKind::Loop,
},
features: LoopFeatureFacts::default(),
scan_with_init: None,
split_scan: None,
pattern1_simplewhile: Some(pattern1),
pattern3_ifphi: None,
pattern4_continue: None,
pattern5_infinite_early_exit: None,
pattern8_bool_predicate_scan: None,
pattern9_accum_const_loop: None,
pattern2_break: None,
pattern2_loopbodylocal: None,
};
let canonical = canonicalize_loop_facts(facts);
let condition = canonical.facts.pattern1_simplewhile.as_ref().unwrap().condition.clone();
let ctx = LoopPatternContext::new(&condition, &[], "composer_test", false, false);
let mut builder = MirBuilder::new();
let loop_var_init = builder.alloc_typed(MirType::Integer);
builder
.variable_ctx
.variable_map
.insert("i".to_string(), loop_var_init);
let plan =
try_compose_core_plan_via_normalizer(&mut builder, &canonical, &ctx)
.expect("Ok");
assert!(matches!(plan, Some(super::CorePlan::Loop(_))));
}
#[test]
fn composer_bridge_normalizes_none_without_pattern1() {
let facts = LoopFacts {
condition_shape: ConditionShape::Unknown,
step_shape: StepShape::Unknown,
skeleton: SkeletonFacts {
kind: SkeletonKind::Loop,
},
features: LoopFeatureFacts::default(),
scan_with_init: None,
split_scan: None,
pattern1_simplewhile: None,
pattern3_ifphi: None,
pattern4_continue: None,
pattern5_infinite_early_exit: None,
pattern8_bool_predicate_scan: None,
pattern9_accum_const_loop: None,
pattern2_break: None,
pattern2_loopbodylocal: None,
};
let canonical = canonicalize_loop_facts(facts);
let condition = ASTNode::BinaryOp {
operator: BinaryOperator::Less,
left: Box::new(v("i")),
right: Box::new(lit_int(3)),
span: Span::unknown(),
};
let ctx = LoopPatternContext::new(&condition, &[], "composer_test", false, false);
let mut builder = MirBuilder::new();
let plan =
try_compose_core_plan_via_normalizer(&mut builder, &canonical, &ctx)
.expect("Ok");
assert!(plan.is_none());
}
}