307 lines
8.0 KiB
Markdown
307 lines
8.0 KiB
Markdown
|
|
# Phase 142 P0: Before/After Comparison
|
||
|
|
|
||
|
|
## Pattern Recognition Capability
|
||
|
|
|
||
|
|
### Before Phase 142
|
||
|
|
|
||
|
|
**Recognized Patterns**: 1 pattern
|
||
|
|
- skip_whitespace: `p = p + 1` (Add operator only)
|
||
|
|
|
||
|
|
**Code**:
|
||
|
|
```rust
|
||
|
|
// Value must be: target + const
|
||
|
|
match value.as_ref() {
|
||
|
|
ASTNode::BinaryOp {
|
||
|
|
operator: BinaryOperator::Add, // ← Only Add operator
|
||
|
|
left,
|
||
|
|
right,
|
||
|
|
..
|
||
|
|
} => {
|
||
|
|
// ... extraction logic
|
||
|
|
let delta = *n; // ← Always positive
|
||
|
|
}
|
||
|
|
_ => return None,
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Limitation**:
|
||
|
|
- Rejected all Subtract operators
|
||
|
|
- Could not recognize `end = end - 1` patterns
|
||
|
|
- No support for trim_trailing use cases
|
||
|
|
|
||
|
|
### After Phase 142 P0
|
||
|
|
|
||
|
|
**Recognized Patterns**: 3 patterns
|
||
|
|
- skip_whitespace: `p = p + 1` (Add operator)
|
||
|
|
- trim_leading: `start = start + 1` (Add operator)
|
||
|
|
- trim_trailing: `end = end - 1` (Subtract operator)
|
||
|
|
|
||
|
|
**Code**:
|
||
|
|
```rust
|
||
|
|
// Value must be: target (+|-) const
|
||
|
|
match value.as_ref() {
|
||
|
|
ASTNode::BinaryOp {
|
||
|
|
operator, // ← Both Add and Subtract
|
||
|
|
left,
|
||
|
|
right,
|
||
|
|
..
|
||
|
|
} => {
|
||
|
|
// Phase 142 P0: Accept both Add (+1) and Subtract (-1)
|
||
|
|
let op_multiplier = match operator {
|
||
|
|
BinaryOperator::Add => 1,
|
||
|
|
BinaryOperator::Subtract => -1,
|
||
|
|
_ => return None,
|
||
|
|
};
|
||
|
|
|
||
|
|
let delta = const_val * op_multiplier; // ← Can be negative
|
||
|
|
}
|
||
|
|
_ => return None,
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Improvement**:
|
||
|
|
- Accepts both Add and Subtract operators
|
||
|
|
- Supports negative deltas (e.g., -1)
|
||
|
|
- Enables trim_trailing and similar patterns
|
||
|
|
|
||
|
|
## Test Coverage
|
||
|
|
|
||
|
|
### Before Phase 142
|
||
|
|
|
||
|
|
**Unit Tests**: 5 tests
|
||
|
|
- `test_canonicalize_rejects_non_loop`
|
||
|
|
- `test_skip_whitespace_pattern_recognition`
|
||
|
|
- `test_skip_whitespace_with_body_statements`
|
||
|
|
- `test_skip_whitespace_fails_without_else`
|
||
|
|
- `test_skip_whitespace_fails_with_wrong_delta` (tested Subtract as failure case)
|
||
|
|
|
||
|
|
**Manual Tests**: 0 tests for trim patterns
|
||
|
|
|
||
|
|
### After Phase 142 P0
|
||
|
|
|
||
|
|
**Unit Tests**: 7 tests (+2 new)
|
||
|
|
- `test_canonicalize_rejects_non_loop`
|
||
|
|
- `test_skip_whitespace_pattern_recognition`
|
||
|
|
- `test_skip_whitespace_with_body_statements`
|
||
|
|
- `test_skip_whitespace_fails_without_else`
|
||
|
|
- `test_skip_whitespace_fails_with_wrong_delta` (now tests Multiply as failure)
|
||
|
|
- **`test_trim_leading_pattern_recognized`** (NEW)
|
||
|
|
- **`test_trim_trailing_pattern_recognized`** (NEW)
|
||
|
|
|
||
|
|
**Manual Tests**: 2 test files
|
||
|
|
- `tools/selfhost/test_pattern3_trim_leading.hako`
|
||
|
|
- `tools/selfhost/test_pattern3_trim_trailing.hako`
|
||
|
|
|
||
|
|
## Parity Verification
|
||
|
|
|
||
|
|
### Before Phase 142
|
||
|
|
|
||
|
|
**trim_leading.hako**:
|
||
|
|
```
|
||
|
|
[loop_canonicalizer] Decision: FAIL_FAST
|
||
|
|
[loop_canonicalizer] Missing caps: [ConstStep]
|
||
|
|
❌ No parity check (pattern not recognized)
|
||
|
|
```
|
||
|
|
|
||
|
|
**trim_trailing.hako**:
|
||
|
|
```
|
||
|
|
[loop_canonicalizer] Decision: FAIL_FAST
|
||
|
|
[loop_canonicalizer] Missing caps: [ConstStep]
|
||
|
|
❌ No parity check (pattern not recognized)
|
||
|
|
```
|
||
|
|
|
||
|
|
### After Phase 142 P0
|
||
|
|
|
||
|
|
**trim_leading.hako**:
|
||
|
|
```
|
||
|
|
[loop_canonicalizer] Decision: SUCCESS
|
||
|
|
[loop_canonicalizer] Chosen pattern: Pattern2Break
|
||
|
|
[loop_canonicalizer] Missing caps: []
|
||
|
|
[choose_pattern_kind/PARITY] ✅ OK: canonical and actual agree on Pattern2Break
|
||
|
|
[loop_canonicalizer/PARITY] ✅ OK in function 'main': canonical and actual agree on Pattern2Break
|
||
|
|
```
|
||
|
|
|
||
|
|
**trim_trailing.hako**:
|
||
|
|
```
|
||
|
|
[loop_canonicalizer] Decision: SUCCESS
|
||
|
|
[loop_canonicalizer] Chosen pattern: Pattern2Break
|
||
|
|
[loop_canonicalizer] Missing caps: []
|
||
|
|
[choose_pattern_kind/PARITY] ✅ OK: canonical and actual agree on Pattern2Break
|
||
|
|
[loop_canonicalizer/PARITY] ✅ OK in function 'main': canonical and actual agree on Pattern2Break
|
||
|
|
```
|
||
|
|
|
||
|
|
## Skeleton Generation
|
||
|
|
|
||
|
|
### Before Phase 142
|
||
|
|
|
||
|
|
**trim_leading pattern**:
|
||
|
|
```rust
|
||
|
|
// Pattern NOT recognized
|
||
|
|
// Returns: RoutingDecision::fail_fast(...)
|
||
|
|
❌ No skeleton generated
|
||
|
|
```
|
||
|
|
|
||
|
|
### After Phase 142 P0
|
||
|
|
|
||
|
|
**trim_leading pattern**:
|
||
|
|
```rust
|
||
|
|
// Pattern recognized!
|
||
|
|
LoopSkeleton {
|
||
|
|
steps: [
|
||
|
|
SkeletonStep::HeaderCond { expr: start < end },
|
||
|
|
SkeletonStep::Body { stmts: [/* body statements */] },
|
||
|
|
SkeletonStep::Update {
|
||
|
|
carrier_name: "start",
|
||
|
|
update_kind: UpdateKind::ConstStep { delta: 1 } // ← Positive
|
||
|
|
}
|
||
|
|
],
|
||
|
|
carriers: [
|
||
|
|
CarrierSlot {
|
||
|
|
name: "start",
|
||
|
|
role: CarrierRole::Counter,
|
||
|
|
update_kind: UpdateKind::ConstStep { delta: 1 }
|
||
|
|
}
|
||
|
|
],
|
||
|
|
exits: ExitContract {
|
||
|
|
has_break: true,
|
||
|
|
has_continue: false,
|
||
|
|
has_return: false,
|
||
|
|
break_has_value: false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**trim_trailing pattern**:
|
||
|
|
```rust
|
||
|
|
// Pattern recognized!
|
||
|
|
LoopSkeleton {
|
||
|
|
steps: [
|
||
|
|
SkeletonStep::HeaderCond { expr: end > start },
|
||
|
|
SkeletonStep::Body { stmts: [/* body statements */] },
|
||
|
|
SkeletonStep::Update {
|
||
|
|
carrier_name: "end",
|
||
|
|
update_kind: UpdateKind::ConstStep { delta: -1 } // ← Negative!
|
||
|
|
}
|
||
|
|
],
|
||
|
|
carriers: [
|
||
|
|
CarrierSlot {
|
||
|
|
name: "end",
|
||
|
|
role: CarrierRole::Counter,
|
||
|
|
update_kind: UpdateKind::ConstStep { delta: -1 } // ← Negative!
|
||
|
|
}
|
||
|
|
],
|
||
|
|
exits: ExitContract {
|
||
|
|
has_break: true,
|
||
|
|
has_continue: false,
|
||
|
|
has_return: false,
|
||
|
|
break_has_value: false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Routing Decision
|
||
|
|
|
||
|
|
### Before Phase 142
|
||
|
|
|
||
|
|
**All patterns**:
|
||
|
|
```
|
||
|
|
if skip_whitespace (+1 only) → Pattern2Break
|
||
|
|
else → FAIL_FAST
|
||
|
|
```
|
||
|
|
|
||
|
|
### After Phase 142 P0
|
||
|
|
|
||
|
|
**All patterns**:
|
||
|
|
```
|
||
|
|
if skip_whitespace (+1) → Pattern2Break
|
||
|
|
if trim_leading (+1) → Pattern2Break
|
||
|
|
if trim_trailing (-1) → Pattern2Break
|
||
|
|
else → FAIL_FAST
|
||
|
|
```
|
||
|
|
|
||
|
|
## Documentation
|
||
|
|
|
||
|
|
### Before Phase 142
|
||
|
|
- No Phase 142 documentation
|
||
|
|
- ast_feature_extractor.rs comments: "skip_whitespace pattern only"
|
||
|
|
|
||
|
|
### After Phase 142 P0
|
||
|
|
- `docs/development/current/main/phases/phase-142/README.md` (complete specification)
|
||
|
|
- `docs/development/current/main/phases/phase-142/IMPLEMENTATION_SUMMARY.md` (detailed summary)
|
||
|
|
- `docs/development/current/main/phases/phase-142/BEFORE_AFTER.md` (this file)
|
||
|
|
- Updated comments in ast_feature_extractor.rs to reflect generalization
|
||
|
|
|
||
|
|
## Impact Summary
|
||
|
|
|
||
|
|
### Functionality
|
||
|
|
- ✅ Pattern recognition: 1 → 3 patterns (+200%)
|
||
|
|
- ✅ Operator support: Add only → Add + Subtract
|
||
|
|
- ✅ Delta range: Positive only → Positive and Negative
|
||
|
|
|
||
|
|
### Testing
|
||
|
|
- ✅ Unit tests: 5 → 7 tests (+40%)
|
||
|
|
- ✅ Manual tests: 0 → 2 test files
|
||
|
|
- ✅ Parity checks: None → 2 passing
|
||
|
|
|
||
|
|
### Code Quality
|
||
|
|
- ✅ Lines of code: +206 lines (91% tests)
|
||
|
|
- ✅ Warnings: 0 new warnings
|
||
|
|
- ✅ Documentation: 3 new documents
|
||
|
|
|
||
|
|
### Compatibility
|
||
|
|
- ✅ Backward compatible: All existing patterns still work
|
||
|
|
- ✅ No breaking changes: Default behavior unchanged
|
||
|
|
- ✅ SSOT maintained: Single source of truth preserved
|
||
|
|
|
||
|
|
## Verification
|
||
|
|
|
||
|
|
### Quick Test
|
||
|
|
```bash
|
||
|
|
# Before Phase 142 (would fail)
|
||
|
|
NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1 ./target/release/hakorune \
|
||
|
|
tools/selfhost/test_pattern3_trim_trailing.hako
|
||
|
|
# Expected: FAIL_FAST (pattern not recognized)
|
||
|
|
|
||
|
|
# After Phase 142 P0 (succeeds)
|
||
|
|
NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1 ./target/release/hakorune \
|
||
|
|
tools/selfhost/test_pattern3_trim_trailing.hako
|
||
|
|
# Expected: [loop_canonicalizer/PARITY] OK: canonical and actual agree on Pattern2Break
|
||
|
|
```
|
||
|
|
|
||
|
|
### Full Verification
|
||
|
|
```bash
|
||
|
|
# Build
|
||
|
|
cargo build --release --lib
|
||
|
|
|
||
|
|
# Unit tests
|
||
|
|
cargo test --release --lib loop_canonicalizer::canonicalizer::tests
|
||
|
|
# Expected: 7 passed
|
||
|
|
|
||
|
|
# Manual tests
|
||
|
|
NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1 ./target/release/hakorune \
|
||
|
|
tools/selfhost/test_pattern3_trim_leading.hako
|
||
|
|
# Expected: PARITY OK
|
||
|
|
|
||
|
|
NYASH_JOINIR_DEV=1 HAKO_JOINIR_STRICT=1 ./target/release/hakorune \
|
||
|
|
tools/selfhost/test_pattern3_trim_trailing.hako
|
||
|
|
# Expected: PARITY OK
|
||
|
|
```
|
||
|
|
|
||
|
|
## Conclusion
|
||
|
|
|
||
|
|
Phase 142 P0 successfully extends the Canonicalizer to handle trim patterns by:
|
||
|
|
1. Generalizing operator support (Add + Subtract)
|
||
|
|
2. Supporting negative deltas (-1)
|
||
|
|
3. Maintaining backward compatibility
|
||
|
|
4. Adding comprehensive tests
|
||
|
|
5. Achieving strict parity green
|
||
|
|
|
||
|
|
The implementation is minimal, focused, and sets a solid foundation for future pattern extensions.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Status**: ✅ Complete
|
||
|
|
**Impact**: High (enables new pattern class)
|
||
|
|
**Risk**: Low (backward compatible, well-tested)
|
||
|
|
**Next**: Phase 142 P1 (A-3 Trim promotion)
|