feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
//! Loop Canonicalizer - AST Level Loop Preprocessing
|
|
|
|
|
//!
|
|
|
|
|
//! ## Purpose
|
|
|
|
|
//!
|
|
|
|
|
//! Decomposes AST-level loops into a normalized "skeleton" representation
|
|
|
|
|
//! to prevent combinatorial explosion in pattern detection and lowering.
|
|
|
|
|
//!
|
|
|
|
|
//! ## Design Principle
|
|
|
|
|
//!
|
|
|
|
|
//! - **Input**: AST (LoopExpr)
|
|
|
|
|
//! - **Output**: LoopSkeleton only (no JoinIR generation)
|
|
|
|
|
//! - **Boundary**: No JoinIR-specific information (BlockId, ValueId, etc.)
|
|
|
|
|
//!
|
|
|
|
|
//! ## Architecture
|
|
|
|
|
//!
|
|
|
|
|
//! ```
|
|
|
|
|
//! AST → LoopSkeleton → Capability Guard → RoutingDecision → Pattern Lowerer
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
2025-12-16 06:41:46 +09:00
|
|
|
//! ## Module Structure (Phase 138 Refactoring)
|
|
|
|
|
//!
|
|
|
|
|
//! - `skeleton_types` - Core data structures (LoopSkeleton, SkeletonStep, etc.)
|
|
|
|
|
//! - `capability_guard` - Routing decisions and capability tags
|
|
|
|
|
//! - `pattern_recognizer` - Pattern detection logic (skip_whitespace, etc.)
|
|
|
|
|
//! - `canonicalizer` - Main canonicalization entry point
|
|
|
|
|
//!
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
//! ## References
|
|
|
|
|
//!
|
|
|
|
|
//! - Design SSOT: `docs/development/current/main/design/loop-canonicalizer.md`
|
|
|
|
|
//! - JoinIR Architecture: `docs/development/current/main/joinir-architecture-overview.md`
|
|
|
|
|
//! - Pattern Space: `docs/development/current/main/loop_pattern_space.md`
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
2025-12-16 06:41:46 +09:00
|
|
|
// Module Declarations
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
// ============================================================================
|
|
|
|
|
|
2025-12-16 06:41:46 +09:00
|
|
|
mod skeleton_types;
|
|
|
|
|
mod capability_guard;
|
|
|
|
|
mod pattern_recognizer;
|
|
|
|
|
mod canonicalizer;
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
|
|
|
|
|
// ============================================================================
|
2025-12-16 06:41:46 +09:00
|
|
|
// Public Re-exports
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
// ============================================================================
|
|
|
|
|
|
2025-12-16 06:41:46 +09:00
|
|
|
// Skeleton Types
|
|
|
|
|
pub use skeleton_types::{
|
|
|
|
|
CarrierRole,
|
|
|
|
|
CarrierSlot,
|
|
|
|
|
CapturedSlot,
|
|
|
|
|
ExitContract,
|
|
|
|
|
LoopSkeleton,
|
|
|
|
|
SkeletonStep,
|
|
|
|
|
UpdateKind,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Capability Guard
|
|
|
|
|
pub use capability_guard::{
|
|
|
|
|
capability_tags,
|
|
|
|
|
RoutingDecision,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Canonicalization Entry Point
|
|
|
|
|
pub use canonicalizer::canonicalize_loop_expr;
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
|
|
|
|
|
// ============================================================================
|
2025-12-16 06:41:46 +09:00
|
|
|
// Tests
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
2025-12-16 06:41:46 +09:00
|
|
|
use crate::ast::Span;
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_skeleton_creation() {
|
|
|
|
|
let skeleton = LoopSkeleton::new(Span::unknown());
|
|
|
|
|
assert_eq!(skeleton.steps.len(), 0);
|
|
|
|
|
assert_eq!(skeleton.carriers.len(), 0);
|
|
|
|
|
assert!(!skeleton.exits.has_any_exit());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_exit_contract() {
|
|
|
|
|
let mut contract = ExitContract::none();
|
|
|
|
|
assert!(!contract.has_any_exit());
|
|
|
|
|
|
|
|
|
|
contract.has_break = true;
|
|
|
|
|
assert!(contract.has_any_exit());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_routing_decision() {
|
2025-12-16 06:41:46 +09:00
|
|
|
use crate::mir::loop_pattern_detection::LoopPatternKind;
|
|
|
|
|
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
let success = RoutingDecision::success(LoopPatternKind::Pattern1SimpleWhile);
|
|
|
|
|
assert!(success.is_success());
|
|
|
|
|
assert!(!success.is_fail_fast());
|
|
|
|
|
|
|
|
|
|
let fail = RoutingDecision::fail_fast(
|
|
|
|
|
vec![capability_tags::CAP_MISSING_CONST_STEP],
|
|
|
|
|
"Test failure".to_string(),
|
|
|
|
|
);
|
|
|
|
|
assert!(!fail.is_success());
|
|
|
|
|
assert!(fail.is_fail_fast());
|
|
|
|
|
assert_eq!(fail.missing_caps.len(), 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_carrier_role_display() {
|
|
|
|
|
assert_eq!(CarrierRole::Counter.to_string(), "Counter");
|
|
|
|
|
assert_eq!(CarrierRole::Accumulator.to_string(), "Accumulator");
|
|
|
|
|
assert_eq!(CarrierRole::ConditionVar.to_string(), "ConditionVar");
|
|
|
|
|
assert_eq!(CarrierRole::Derived.to_string(), "Derived");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_skeleton_count_helpers() {
|
2025-12-16 06:41:46 +09:00
|
|
|
use crate::ast::{ASTNode, LiteralValue};
|
feat(mir): Phase 1 - Loop Canonicalizer type definitions
Implements the foundation for loop canonicalization - a preprocessing
layer that decomposes AST loops into normalized skeleton representation
to prevent combinatorial explosion in pattern detection.
## Implementation (Phase 1)
Created `src/mir/loop_canonicalizer/mod.rs` with:
1. **Core Types**:
- `LoopSkeleton`: Canonical loop representation
- `SkeletonStep`: Step kinds (HeaderCond, BreakCheck, ContinueCheck, Update, Body)
- `UpdateKind`: Carrier update classification (ConstStep, Conditional, Arbitrary)
- `ExitContract`: Exit presence tracking (break/continue/return)
- `CarrierSlot`: Loop variables with roles and update rules
- `CarrierRole`: Semantic roles (Counter, Accumulator, ConditionVar, Derived)
- `CapturedSlot`: Outer scope variable capture
2. **Capability Guard**:
- `RoutingDecision`: Pattern selection with diagnostics
- `capability_tags` module: Standardized Fail-Fast vocabulary
(CAP_MISSING_CONST_STEP, CAP_MISSING_SINGLE_BREAK, etc.)
3. **Helper Methods**:
- Skeleton counting (break_checks, continue_checks)
- Carrier name extraction
- Exit contract queries
- Display implementations for debugging
4. **Unit Tests**: 6 tests covering all basic functionality
## Design Principles
- **Input**: AST only (no JoinIR dependencies)
- **Output**: LoopSkeleton only (no BlockId/ValueId)
- **Boundary**: Clear separation from lowering concerns
- **Fail-Fast**: Capability-based rejection with clear reasons
## Next Steps (Not in this commit)
- Phase 2: `LoopCanonicalizer::canonicalize(ast) -> Result<LoopSkeleton>`
- Phase 3: Test with skip_whitespace fixture
- Phase 4: Integration with existing JoinIR lowering
## Acceptance Criteria
✅ `cargo build --release` succeeds
✅ `cargo test --release --lib` passes (1039 tests)
✅ 6 new unit tests for loop_canonicalizer pass
✅ No regressions in existing tests
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-16 04:59:26 +09:00
|
|
|
|
|
|
|
|
let mut skeleton = LoopSkeleton::new(Span::unknown());
|
|
|
|
|
|
|
|
|
|
skeleton.steps.push(SkeletonStep::BreakCheck {
|
|
|
|
|
cond: Box::new(ASTNode::Literal {
|
|
|
|
|
value: LiteralValue::Bool(true),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
}),
|
|
|
|
|
has_value: false,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
skeleton.steps.push(SkeletonStep::ContinueCheck {
|
|
|
|
|
cond: Box::new(ASTNode::Literal {
|
|
|
|
|
value: LiteralValue::Bool(true),
|
|
|
|
|
span: Span::unknown(),
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
assert_eq!(skeleton.count_break_checks(), 1);
|
|
|
|
|
assert_eq!(skeleton.count_continue_checks(), 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_skeleton_carrier_names() {
|
|
|
|
|
let mut skeleton = LoopSkeleton::new(Span::unknown());
|
|
|
|
|
|
|
|
|
|
skeleton.carriers.push(CarrierSlot {
|
|
|
|
|
name: "i".to_string(),
|
|
|
|
|
role: CarrierRole::Counter,
|
|
|
|
|
update_kind: UpdateKind::ConstStep { delta: 1 },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
skeleton.carriers.push(CarrierSlot {
|
|
|
|
|
name: "sum".to_string(),
|
|
|
|
|
role: CarrierRole::Accumulator,
|
|
|
|
|
update_kind: UpdateKind::Arbitrary,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let names = skeleton.carrier_names();
|
|
|
|
|
assert_eq!(names, vec!["i", "sum"]);
|
|
|
|
|
}
|
|
|
|
|
}
|