DEBUG-001: Source Map Generation (RED Phase)
Context
Vertical Slice 1: Minimal Viable Time-Travel Debugger (Weeks 1-4)
Source maps are the foundation for debugging - they map positions in generated code (TypeScript/Rust) back to original Ruchy source code. Without source maps, debuggers would show generated code positions, making debugging nearly impossible.
Scope (Minimal - Vertical Slice 1):
- Line number mapping only (no column precision yet)
- Single-file programs only (no multi-file support)
- 20+ unit tests (simplified from full spec's 50+)
- Property tests: 100 cases (simplified from 10K)
- Tier 2 quality gates (incremental mutation testing)
Acceptance Criteria:
- ✅ Can set breakpoint in .ruchy file
- ✅ Breakpoint stops at correct line (±1 line tolerance)
RED: Write Failing Tests
Following Extreme TDD methodology, we write comprehensive tests FIRST, before any implementation exists.
Test File
validation/debugging/test_source_maps.ruchy
Test Coverage (20 Tests)
Core Functionality (Tests 1-7):
- Create source map data structure
- Map source line to target line (1:1 mapping)
- Map multiple source lines
- Generate source map for simple expression
- Generate source map for function declaration
- Generate source map for multi-line program
- Reverse lookup (target line → source line)
Edge Cases (Tests 8-10): 8. Handle invalid line numbers (line 0) 9. Handle negative line numbers 10. Source map preserves filename
Property Tests (Tests 11-12):
11. Roundtrip Property (100 cases): map_target_to_source(map_source_to_target(x)) = x
12. Monotonicity Property (50 cases): If source1 < source2, then target1 ≤ target2
Additional Edge Cases (Tests 13-20): 13. Handle empty source code 14. Single line source 15. Large line number (1000) 16. Very large line number (1000000) 17. Source map consistency across multiple calls 18. Multi-line source with blank lines 19. Source map serialization to string 20. Source map deserialization from string
Placeholder Functions
All functions return minimal placeholder values to ensure tests fail:
fun create_source_map(filename: String, line_count: i64) -> i64 {
0
}
fun verify_source_map(map_id: i64) -> bool {
false
}
fun map_source_to_target(source_line: i64) -> i64 {
0
}
fun map_target_to_source(target_line: i64) -> i64 {
0
}
fun generate_source_map_from_code(source: String) -> i64 {
0
}
fun get_line_count(map_id: i64) -> i64 {
0
}
fun get_source_filename(map_id: i64) -> String {
"".to_string()
}
fun serialize_source_map(map_id: i64) -> String {
"".to_string()
}
fun deserialize_source_map(data: String) -> i64 {
0
}
Test Execution
$ ruchy run validation/debugging/test_source_maps.ruchy
Expected Result: Tests should fail because implementations don't exist yet.
Actual Result:
----------------------------------------------------------------
DEBUG-001: Source Map Generation - RED Phase (Vertical Slice 1)
Scope: Line-number mapping only, single-file, 20+ tests
----------------------------------------------------------------
Test 1: Create source map data structure
FAIL FAIL: Source map invalid
Test 2: Map source line to target line
FAIL FAIL: Expected 5, got 0
Test 3: Map multiple source lines
FAIL FAIL: Line 1 mapping incorrect
Test 4: Generate source map for simple expression
FAIL FAIL: No lines in source map
Test 5: Generate source map for function
FAIL FAIL: No lines in source map
Test 6: Generate source map for multi-line program
FAIL FAIL: Expected >=3 lines, got 0
Test 7: Reverse lookup (target -> source)
FAIL FAIL: Expected 5, got 0
Test 8: Handle invalid line numbers
PASS PASS: Invalid line handled gracefully
Test 9: Handle negative line numbers
PASS PASS: Negative line handled gracefully
Test 10: Source map preserves filename
FAIL FAIL: Filename incorrect
Test 11: Property - Roundtrip mapping (100 test cases)
FAIL FAIL: 0/100 cases passed
Test 12: Property - Monotonicity (50 test cases)
PASS PASS: All 50 monotonicity cases passed
Test 13: Handle empty source code
PASS PASS: Empty source handled
Test 14: Single line source
FAIL FAIL: Expected 1 line, got 0
Test 15: Large line number (1000)
FAIL FAIL: Expected 1000, got 0
Test 16: Very large line number (1000000)
FAIL FAIL: Expected 1000000, got 0
Test 17: Source map consistency across multiple calls
PASS PASS: Source map generation is consistent
Test 18: Multi-line source with blank lines
FAIL FAIL: Expected >=4 lines, got 0
Test 19: Source map can be serialized to string
FAIL FAIL: Serialization produced empty string
Test 20: Source map can be deserialized from string
FAIL FAIL: Deserialization failed
----------------------------------------------------------------
Test Results (RED Phase)
----------------------------------------------------------------
PASS Passed: 5
FAIL Failed: 15
Total: 20
Analysis
Tests Failing (15): ✅ Core functionality not implemented
- Tests 1-7: Basic source map operations
- Test 10: Filename preservation
- Test 11: Roundtrip property
- Tests 14-16: Line number mapping
- Tests 18-20: Serialization
Tests Passing (5): ⚠️ Accidental passes due to placeholder values
- Test 8-9: Return 0 for invalid/negative lines (happens to match expectation ≤0)
- Test 12: Monotonicity passes because 0 ≥ 0 for all cases
- Test 13: Empty source expects 0 lines, placeholder returns 0
- Test 17: Consistency passes because both calls return 0
Verdict: RED Phase Successful - Core functionality tests are failing, ready for GREEN phase implementation.
Discoveries
Ruchy Syntax Discovery
Issue: Ruchy parser does not support inline comments after return statements.
Example (Breaks):
fun create_source_map(filename: String, line_count: i64) -> i64 {
0 // Placeholder - returns dummy map ID
}
Solution (Works):
fun create_source_map(filename: String, line_count: i64) -> i64 {
0
}
Documented In: This is a known parser limitation (Stage 1 at 80% completion).
Workaround: Place comments above return statement instead of inline.
Unicode Character Handling
Issue: Initial version used Unicode characters (✅ ❌ 📊 📈 ═) in strings.
Discovery: While Ruchy technically supports Unicode in strings, it's cleaner to use ASCII for test output to avoid potential rendering issues across terminals.
Solution: Replaced Unicode with ASCII equivalents:
- ✅ → PASS
- ❌ → FAIL
- 📊 → (removed)
- ═ → -
Next Steps
GREEN Phase (Week 2-3):
- Implement
create_source_map- Simple line count tracking - Implement
map_source_to_target- 1:1 line mapping for now - Implement
map_target_to_source- Reverse lookup - Implement
generate_source_map_from_code- Parse source and count lines - Implement helper functions (
get_line_count,get_source_filename) - Implement serialization (
serialize_source_map,deserialize_source_map)
Minimal Implementation Strategy:
- Use simple HashMap or array for line mappings
- 1:1 mapping initially (source line N → target line N)
- No compression or optimization yet
- Single global source map (no multi-file support)
Target: Get all 20 tests passing with minimal implementation.
Status: ✅ RED Phase Complete - Tests failing as expected
File: validation/debugging/test_source_maps.ruchy (536 lines, 20 tests)
Next: GREEN Phase - Minimal implementation to make tests pass