feat(joinir): Phase 90 P0 - ParseStringComposite pattern
## Composite Pattern - Continue(escape i+=2) + EarlyReturn(close quote) - parse_string_composite_pattern.rs (50行、continue_return 再利用) - 89% コード削減(450行→50行) ## Shape Detection - BinOp Add const 2 検出(escape 特徴) - LoopStepInspector 活用(Phase 89 リファクタ成果) ## SSOT Integration - dev_fixtures.rs に登録 - StepCalculator 再利用(Phase 89-2 成果) ## Tests - +2 tests (vm_bridge + 期待値 n=10→acc=5) - normalized_dev: 61→63 passed - lib: 993 passed (回帰なし) Impact: - Reuse over Duplication 実践 - Phase 89 リファクタ成果の完全活用 - 箱化原則 5/5 遵守 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -19,6 +19,8 @@ pub enum NormalizedDevFixture {
|
||||
Pattern4JsonParserParseObjectContinueSkipWs,
|
||||
/// Pattern Continue + Early Return minimal (Phase 89 P1)
|
||||
PatternContinueReturnMin,
|
||||
/// Parse String Composite minimal (Phase 90 P0)
|
||||
ParseStringCompositeMin,
|
||||
}
|
||||
|
||||
impl NormalizedDevFixture {
|
||||
@ -33,6 +35,7 @@ impl NormalizedDevFixture {
|
||||
"jsonparser_parse_object_continue_skip_ws"
|
||||
}
|
||||
Self::PatternContinueReturnMin => "pattern_continue_return_minimal",
|
||||
Self::ParseStringCompositeMin => "parse_string_composite_minimal",
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,6 +54,9 @@ impl NormalizedDevFixture {
|
||||
Self::PatternContinueReturnMin => {
|
||||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/pattern_continue_return_min.program.json"
|
||||
}
|
||||
Self::ParseStringCompositeMin => {
|
||||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/parse_string_composite_min.program.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +67,8 @@ impl NormalizedDevFixture {
|
||||
Self::Pattern4ContinueMinimal
|
||||
| Self::Pattern4JsonParserParseArrayContinueSkipWs
|
||||
| Self::Pattern4JsonParserParseObjectContinueSkipWs
|
||||
| Self::PatternContinueReturnMin => FunctionRoute::LoopFrontend,
|
||||
| Self::PatternContinueReturnMin
|
||||
| Self::ParseStringCompositeMin => FunctionRoute::LoopFrontend,
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +90,9 @@ impl NormalizedDevFixture {
|
||||
Self::PatternContinueReturnMin => include_str!(
|
||||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/pattern_continue_return_min.program.json"
|
||||
),
|
||||
Self::ParseStringCompositeMin => include_str!(
|
||||
"../../../../docs/private/roadmap2/phases/normalized_dev/fixtures/parse_string_composite_min.program.json"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,6 +121,7 @@ pub const ALL_DEV_FIXTURES: &[NormalizedDevFixture] = &[
|
||||
NormalizedDevFixture::Pattern4JsonParserParseArrayContinueSkipWs,
|
||||
NormalizedDevFixture::Pattern4JsonParserParseObjectContinueSkipWs,
|
||||
NormalizedDevFixture::PatternContinueReturnMin,
|
||||
NormalizedDevFixture::ParseStringCompositeMin,
|
||||
];
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -783,6 +783,14 @@ pub fn build_pattern_continue_return_min_structured_for_normalized_dev() -> Join
|
||||
NormalizedDevFixture::PatternContinueReturnMin.load_and_lower()
|
||||
}
|
||||
|
||||
/// Parse String Composite minimal を Structured で組み立てるヘルパー
|
||||
///
|
||||
/// Fixture: docs/private/roadmap2/phases/normalized_dev/fixtures/parse_string_composite_min.program.json
|
||||
pub fn build_parse_string_composite_min_structured_for_normalized_dev() -> JoinModule {
|
||||
use super::dev_fixtures::NormalizedDevFixture;
|
||||
NormalizedDevFixture::ParseStringCompositeMin.load_and_lower()
|
||||
}
|
||||
|
||||
/// まとめて import したいとき用のプレリュード。
|
||||
pub mod prelude {
|
||||
pub use super::{
|
||||
@ -800,6 +808,7 @@ pub mod prelude {
|
||||
build_pattern3_json_if_sum_min_structured_for_normalized_dev,
|
||||
build_pattern4_continue_min_structured_for_normalized_dev,
|
||||
build_pattern_continue_return_min_structured_for_normalized_dev,
|
||||
build_parse_string_composite_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,
|
||||
|
||||
@ -29,6 +29,9 @@ pub enum ShapeCapabilityKind {
|
||||
/// P4 Continue + Early Return family (Phase 89)
|
||||
P4ContinueEarlyReturn,
|
||||
|
||||
/// Composite Parse String (continue + early return + variable step) (Phase 90)
|
||||
CompositeParseString,
|
||||
|
||||
/// Selfhost P2 core (token scan)
|
||||
SelfhostP2Core,
|
||||
|
||||
@ -90,6 +93,8 @@ pub enum NormalizedDevShape {
|
||||
SelfhostDetectFormatP3,
|
||||
// Phase 89: Continue + Early Return pattern (dev-only)
|
||||
PatternContinueReturnMinimal,
|
||||
// Phase 90: Parse String Composite pattern (dev-only: continue + early return + variable step)
|
||||
ParseStringCompositeMinimal,
|
||||
}
|
||||
|
||||
type Detector = fn(&JoinModule) -> bool;
|
||||
@ -182,6 +187,11 @@ const SHAPE_DETECTORS: &[(NormalizedDevShape, Detector)] = &[
|
||||
NormalizedDevShape::PatternContinueReturnMinimal,
|
||||
detectors::is_pattern_continue_return_minimal,
|
||||
),
|
||||
// Phase 90: Parse String Composite pattern
|
||||
(
|
||||
NormalizedDevShape::ParseStringCompositeMinimal,
|
||||
detectors::is_parse_string_composite_minimal,
|
||||
),
|
||||
];
|
||||
|
||||
/// direct ブリッジで扱う shape(dev 限定)。
|
||||
@ -226,6 +236,8 @@ pub fn capability_for_shape(shape: &NormalizedDevShape) -> ShapeCapability {
|
||||
SelfhostDetectFormatP3 => SelfhostP3IfSum,
|
||||
// Phase 89: Continue + Early Return pattern (dev-only, dedicated capability)
|
||||
PatternContinueReturnMinimal => P4ContinueEarlyReturn,
|
||||
// Phase 90: Parse String Composite pattern (dev-only, dedicated capability)
|
||||
ParseStringCompositeMinimal => CompositeParseString,
|
||||
};
|
||||
|
||||
ShapeCapability::new(kind)
|
||||
@ -276,6 +288,7 @@ pub fn is_p2_core_capability(cap: &ShapeCapability) -> bool {
|
||||
| P3IfSum
|
||||
| P4ContinueSkipWs
|
||||
| P4ContinueEarlyReturn
|
||||
| CompositeParseString
|
||||
| SelfhostP2Core
|
||||
| SelfhostP3IfSum
|
||||
)
|
||||
@ -942,6 +955,58 @@ mod detectors {
|
||||
&& k_exit_jumps_count >= 2 // At least 2: loop break + early return
|
||||
}
|
||||
|
||||
/// Phase 90: Check if module matches Parse String Composite pattern
|
||||
///
|
||||
/// Structural characteristics:
|
||||
/// - 3 functions (main, loop_step, k_exit)
|
||||
/// - Has Select instruction (continue's core)
|
||||
/// - Has TWO or more conditional Jumps to k_exit (loop break + early return)
|
||||
/// - Has Compare instruction
|
||||
/// - Has tail call (loop back)
|
||||
/// - Has variable step increment (distinguishing feature from ContinueReturn)
|
||||
///
|
||||
/// Distinguishing from ContinueReturn:
|
||||
/// - ParseStringComposite has i+=2 in continue branch (escape character handling)
|
||||
/// - ContinueReturn has i+=1 in continue branch
|
||||
/// - Detection: Check for BinOp Add with const value 2 in loop body
|
||||
pub(crate) fn is_parse_string_composite_minimal(module: &JoinModule) -> bool {
|
||||
// Must match basic Continue + Return structure first
|
||||
if !is_pattern_continue_return_minimal(module) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find loop_step function
|
||||
let loop_step = match find_loop_step(module) {
|
||||
Some(f) => f,
|
||||
None => return false,
|
||||
};
|
||||
|
||||
// Additional check: Must have BinOp Add with const value 2 (escape handling)
|
||||
// This distinguishes ParseStringComposite from generic ContinueReturn
|
||||
let has_variable_step = loop_step.body.iter().any(|inst| match inst {
|
||||
JoinInst::Compute(mir_inst) => match mir_inst {
|
||||
crate::mir::join_ir::MirLikeInst::BinOp { op, rhs, .. } => {
|
||||
// Check if it's Add operation
|
||||
if *op != crate::mir::join_ir::BinOpKind::Add {
|
||||
return false;
|
||||
}
|
||||
// Check if rhs is a const value 2 (indicating i+=2 for escape)
|
||||
// We need to check if rhs points to a Const instruction with value 2
|
||||
loop_step.body.iter().any(|other_inst| match other_inst {
|
||||
JoinInst::Compute(crate::mir::join_ir::MirLikeInst::Const { dst, value }) => {
|
||||
dst == rhs && matches!(value, crate::mir::join_ir::ConstValue::Integer(2))
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
});
|
||||
|
||||
has_variable_step
|
||||
}
|
||||
|
||||
pub(super) fn find_loop_step(module: &JoinModule) -> Option<&JoinFunction> {
|
||||
module
|
||||
.functions
|
||||
|
||||
Reference in New Issue
Block a user