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:
@ -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