Debugging
Debugging is an essential skill for developing robust Droe applications. This guide covers debugging techniques, common issues, and troubleshooting strategies for Droe programs.
Basic Debugging Techniques
Using Display Statements
The simplest debugging technique is adding display statements to trace program execution:
set user_age which is int to 25
display "Debug: user_age = [user_age]"
when user_age is greater than or equal to 18 then
display "Debug: User is adult, proceeding..."
display "Access granted"
otherwise
display "Debug: User is minor, access denied"
display "Access denied"
end when
Variable State Tracking
Track variable changes throughout program execution:
set counter which is int to 0
display "Debug: Initial counter = [counter]"
set numbers which are list of int to [1, 2, 3, 4, 5]
for each number in numbers
set counter to counter + number
display "Debug: Added [number], counter now = [counter]"
end for
display "Debug: Final counter = [counter]"
Conditional Debug Output
Use flags to control debug output:
set debug_mode which is flag to true
module debug_utils
action log_debug with message which is text
when debug_mode then
display "[DEBUG] [message]"
end when
end action
action log_error with message which is text
display "[ERROR] [message]"
end action
action log_info with message which is text
display "[INFO] [message]"
end action
end module
run debug_utils.log_info with "Starting application"
run debug_utils.log_debug with "Debug mode is enabled"
set user_input which is text to "alice"
run debug_utils.log_debug with "User input: [user_input]"
when user_input is equal to "" then
run debug_utils.log_error with "Empty user input"
otherwise
run debug_utils.log_info with "Processing user: [user_input]"
end when
CLI Debugging Tools
Verbose Compilation
Use verbose mode to see detailed compilation information:
# Compile with verbose output
droe compile src/main.droe --verbose
# This shows:
# - Parsing steps
# - Type checking results
# - Code generation phases
# - Output file information
Debug Mode Execution
Run programs with debug information:
# Run with debug output
droe run src/main.droe --debug
# Run with execution trace
droe run src/main.droe --trace
# Combine debug and trace
droe run src/main.droe --debug --trace
System Diagnostics
Check system setup and dependencies:
# Run system diagnostics
droe doctor
# Check specific components
droe doctor --component compiler
droe doctor --component runtime
droe doctor --component webassembly
# Verbose diagnostics
droe doctor --verbose
Common Issues and Solutions
Compilation Errors
Type Mismatch Errors
Problem:
set age which is int to "twenty-five" // Error: type mismatch
Error Message:
Error: Type mismatch at line 1:25
Expected: int
Got: text
Solution:
set age which is int to 25 // Correct: use integer literal
Variable Not Declared
Problem:
display username // Error: username not declared
Error Message:
Error: Undefined variable 'username' at line 1:9
Solution:
set username which is text to "alice"
display username // Correct: declare before use
Missing Type Declaration
Problem:
set count to 5 // Error: missing type declaration
Error Message:
Error: Missing type declaration at line 1:5
Expected: 'which is <type>'
Solution:
set count which is int to 5 // Correct: explicit type
Runtime Errors
Division by Zero
Problem:
set numerator which is int to 10
set denominator which is int to 0
set result to numerator / denominator // Runtime error
Debug with Protection:
set numerator which is int to 10
set denominator which is int to 0
display "Debug: numerator = [numerator], denominator = [denominator]"
when denominator is equal to 0 then
display "Error: Division by zero detected"
set result which is decimal to 0.0
otherwise
set result to numerator / denominator
display "Result: [result]"
end when
Array Index Errors (Future Feature)
Problem:
set numbers which are list of int to [1, 2, 3]
// Accessing invalid index would cause error
Debug Approach:
set numbers which are list of int to [1, 2, 3]
set count which is int to 0
for each number in numbers
set count to count + 1
display "Processing item [count]: [number]"
end for
display "Total items processed: [count]"
Logic Errors
Incorrect Conditional Logic
Problem:
set score which is int to 85
set passing_grade which is int to 80
// Logic error: using 'or' instead of 'and'
when score is greater than passing_grade or score is equal to passing_grade then
display "Passed"
end when
Debug with Explicit Checks:
set score which is int to 85
set passing_grade which is int to 80
display "Debug: score = [score], passing_grade = [passing_grade]"
display "Debug: score > passing_grade = " // Would show comparison result
when score is greater than or equal to passing_grade then
display "Debug: Condition met, student passed"
display "Passed"
otherwise
display "Debug: Condition not met, student failed"
display "Failed"
end when
Loop Logic Issues
Problem:
set total which is int to 0
set numbers which are list of int to [1, 2, 3, 4, 5]
for each number in numbers
set total to number // Bug: should be total + number
end for
display "Total: [total]" // Will only show last number
Debug Version:
set total which is int to 0
set numbers which are list of int to [1, 2, 3, 4, 5]
set iteration which is int to 0
display "Debug: Starting loop with total = [total]"
for each number in numbers
set iteration to iteration + 1
set previous_total to total
set total to total + number // Fixed: addition instead of assignment
display "Debug: Iteration [iteration]: [previous_total] + [number] = [total]"
end for
display "Final total: [total]"
Debugging Complex Programs
Module Debugging
Debug Module Actions:
module calculator
action add with a which is int, b which is int gives int
display "Debug: calculator.add called with a=[a], b=[b]"
set result to a + b
display "Debug: calculator.add returning [result]"
give result
end action
action multiply with x which is decimal, y which is decimal gives decimal
display "Debug: calculator.multiply called with x=[x], y=[y]"
set result to x * y
display "Debug: calculator.multiply returning [result]"
give result
end action
end module
set sum from run calculator.add with 10, 5
display "Sum result: [sum]"
set product from run calculator.multiply with 3.14, 2.0
display "Product result: [product]"
Data Flow Debugging
Track data flow through complex operations:
module data_processor
action validate_input with input which is text gives flag
display "Debug: Validating input: '[input]'"
when input is equal to "" then
display "Debug: Input is empty - invalid"
give false
otherwise
display "Debug: Input is not empty - valid"
give true
end when
end action
action process_data with data which is text gives text
display "Debug: Processing data: '[data]'"
set is_valid from run data_processor.validate_input with data
display "Debug: Validation result: [is_valid]"
when is_valid then
set result to "Processed: " + data
display "Debug: Generated result: '[result]'"
give result
otherwise
display "Debug: Invalid data, returning error message"
give "Error: Invalid input"
end when
end action
end module
set user_input which is text to "test data"
display "Debug: Starting processing with input: '[user_input]'"
set final_result from run data_processor.process_data with user_input
display "Final result: [final_result]"
Performance Debugging
Timing and Performance
Add timing information to identify bottlenecks:
module performance_monitor
action log_start with operation which is text
display "[PERF] Starting: [operation]"
end action
action log_end with operation which is text
display "[PERF] Completed: [operation]"
end action
action log_progress with operation which is text, current which is int, total which is int
set percent which is decimal to (current * 100) / total
display "[PERF] [operation]: [current]/[total] ([percent]%)"
end action
end module
run performance_monitor.log_start with "Data processing"
set large_dataset which are list of int to [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
set processed_count which is int to 0
set total_count which is int to 10
for each item in large_dataset
set processed_count to processed_count + 1
// Simulate work
set temp_result to item * 2
when processed_count % 3 is equal to 0 then
run performance_monitor.log_progress with "Processing", processed_count, total_count
end when
end for
run performance_monitor.log_end with "Data processing"
Memory Usage Debugging
Track memory-intensive operations:
module memory_monitor
action log_allocation with operation which is text, size which is int
display "[MEM] Allocating for [operation]: ~[size] items"
end action
action log_deallocation with operation which is text
display "[MEM] Deallocating: [operation]"
end action
end module
run memory_monitor.log_allocation with "Large number list", 1000
set large_numbers which are list of int to []
// In real implementation, would add 1000 items
run memory_monitor.log_deallocation with "Large number list"
WebAssembly Debugging
Inspecting Generated WebAssembly
# Compile to WebAssembly text format
droe compile src/main.droe --format wat
# View the generated .wat file
cat build/main.wat
# Validate WebAssembly module
wasm-validate build/main.wasm
# Disassemble binary WebAssembly
wasm-objdump -d build/main.wasm
Runtime Debugging
Add debug output to the WebAssembly runtime:
// Custom debug runtime (debug-run.js)
const fs = require('fs');
async function runWasmWithDebug(wasmFile) {
console.log(`[DEBUG] Loading WASM file: ${wasmFile}`);
const wasmBuffer = fs.readFileSync(wasmFile);
const imports = {
env: {
display: (offset, length) => {
console.log(`[DEBUG] Display called with offset=${offset}, length=${length}`);
const memory = wasmInstance.exports.memory;
const buffer = new Uint8Array(memory.buffer, offset, length);
const text = new TextDecoder().decode(buffer);
console.log(`[OUTPUT] ${text}`);
}
}
};
console.log('[DEBUG] Instantiating WASM module...');
const wasmModule = await WebAssembly.instantiate(wasmBuffer, imports);
const wasmInstance = wasmModule.instance;
console.log('[DEBUG] Calling main function...');
wasmInstance.exports.main();
console.log('[DEBUG] Execution completed');
}
// Usage: node debug-run.js build/main.wasm
runWasmWithDebug(process.argv[2]);
Debugging Best Practices
1. Use Descriptive Debug Messages
// Good: Descriptive debug messages
display "Debug: User authentication - checking credentials for [username]"
display "Debug: Database query returned [result_count] records"
display "Debug: Validation failed at step 3: email format check"
// Avoid: Vague messages
display "Debug: here"
display "Debug: value is [value]"
display "Debug: error"
2. Create Debug Utilities
module debug_helpers
action dump_variables with name which is text, age which is int, active which is flag
display "=== Variable Dump ==="
display "Name: [name]"
display "Age: [age]"
display "Active: [active]"
display "==================="
end action
action trace_function_entry with function_name which is text, param1 which is text, param2 which is text
display ">>> Entering [function_name]([param1], [param2])"
end action
action trace_function_exit with function_name which is text, result which is text
display "<<< Exiting [function_name] with result: [result]"
end action
end module
3. Progressive Debugging
Build complexity gradually:
// Step 1: Test basic functionality
display "Step 1: Basic display working"
// Step 2: Test variables
set test_var which is int to 42
display "Step 2: Variable test_var = [test_var]"
// Step 3: Test conditionals
when test_var is greater than 0 then
display "Step 3: Conditional logic working"
end when
// Step 4: Test loops
set test_numbers which are list of int to [1, 2, 3]
display "Step 4: Testing loop..."
for each num in test_numbers
display " Number: [num]"
end for
// Step 5: Test modules
module test_module
action test_action with input which is int gives int
display "Step 5: Module action called with [input]"
give input * 2
end action
end module
set result from run test_module.test_action with 5
display "Step 5: Module result = [result]"
4. Error Boundaries
Implement error boundaries in your code:
module safe_operations
action safe_divide with numerator which is decimal, denominator which is decimal gives decimal
when denominator is equal to 0.0 then
display "Warning: Division by zero, returning 0"
give 0.0
otherwise
give numerator / denominator
end when
end action
action safe_process_user with username which is text gives text
when username is equal to "" then
display "Error: Empty username provided"
give "Invalid user"
otherwise
give "Processed: " + username
end when
end action
end module
Troubleshooting Checklist
When encountering issues, follow this systematic approach:
1. Compilation Issues
- [ ] Check syntax for typos and missing keywords
- [ ] Verify all variables are declared with types
- [ ] Ensure all blocks have proper
end
statements - [ ] Check for reserved keyword usage
2. Runtime Issues
- [ ] Add debug output to trace execution flow
- [ ] Check variable values at key points
- [ ] Verify conditional logic with explicit tests
- [ ] Test edge cases (empty strings, zero values, etc.)
3. Logic Issues
- [ ] Break down complex operations into smaller steps
- [ ] Test each component independently
- [ ] Verify loop logic with simple examples
- [ ] Check module action parameters and return values
4. Performance Issues
- [ ] Add timing information to identify bottlenecks
- [ ] Monitor memory usage patterns
- [ ] Check for unnecessary operations in loops
- [ ] Profile WebAssembly execution
Advanced Debugging Techniques
State Machine Debugging
For complex state-based programs:
set current_state which is text to "idle"
set debug_enabled which is flag to true
module state_machine
action change_state with from_state which is text, to_state which is text, reason which is text
when debug_enabled then
display "[STATE] Changing from '[from_state]' to '[to_state]' - Reason: [reason]"
end when
set current_state to to_state
end action
action validate_transition with from_state which is text, to_state which is text gives flag
when debug_enabled then
display "[STATE] Validating transition: '[from_state]' -> '[to_state]'"
end when
// Add validation logic here
give true
end action
end module
run state_machine.change_state with current_state, "processing", "User initiated action"
Integration Testing
Test interactions between modules:
module integration_tests
action test_user_workflow
display "[TEST] Starting user workflow integration test"
// Test user creation
set user_created from run user_service.create_user with "testuser", "test@example.com"
display "[TEST] User creation result: [user_created]"
// Test authentication
set auth_result from run auth_service.authenticate with "testuser", "password"
display "[TEST] Authentication result: [auth_result]"
// Test data processing
set process_result from run data_service.process with "test data"
display "[TEST] Data processing result: [process_result]"
display "[TEST] Integration test completed"
end action
end module
run integration_tests.test_user_workflow
Next Steps
Now that you understand debugging in Droe:
- CLI Reference - Learn debugging command-line options
- WebAssembly - Debug WebAssembly output
- Performance - Optimize program performance
- Best Practices - Write maintainable code
Effective debugging is crucial for developing reliable Droe applications. Use these techniques to identify and resolve issues quickly, and build robust, maintainable programs.