Neutron Error Handling System¶
Overview¶
Neutron now features a comprehensive, cross-platform error handling system that provides meaningful error messages with context, suggestions, and stack traces to help developers quickly identify and fix issues.
Features¶
1. Categorized Error Types¶
SyntaxError- Parsing and grammar errorsRuntimeError- Execution errorsTypeError- Type mismatch errorsReferenceError- Undefined variable/function errorsRangeError- Index out of bounds errorsArgumentError- Wrong number of argumentsDivisionError- Division or modulo by zeroStackError- Stack overflow/underflowModuleError- Module loading errorsIOError- File operation errorsLexicalError- Tokenization errors
2. Rich Error Information¶
Each error displays: - Error type and category (color-coded on supported terminals) - File name and location (line and column numbers) - The actual source code line where the error occurred - Visual indicator (^) pointing to the error position - Helpful suggestion for fixing the error - Stack trace showing the call chain (for runtime errors)
3. Cross-Platform Compatibility¶
The error handler works seamlessly across: - Linux (with ANSI color support) - macOS (with ANSI color support) - Windows (with ANSI escape sequence support on Windows 10+)
Color output is automatically detected and disabled on terminals that don't support it.
4. Contextual Suggestions¶
The error handler provides helpful suggestions based on the error type:
- Undefined variables: "Did you forget to declare the variable with 'var'? Or maybe you need to import a module with 'use'?"
- Missing semicolons: "Every statement in Neutron must end with a semicolon."
- Type errors: "Mathematical operations require numeric values. Use type conversion if needed."
- Array index errors: "Array indices must be within bounds (0 to length-1)."
- Division by zero: "Check that the divisor is not zero before performing division or modulo operations."
- Stack overflow: "This usually indicates infinite recursion. Check your recursive function calls."
Example Error Output¶
Syntax Error¶
SyntaxError in test.nt at line 12, column 15:
Expect ';' after expression.
12 | var x = 10 + 5
| ^
Suggestion: Every statement in Neutron must end with a semicolon.
Runtime Error with Stack Trace¶
RuntimeError in test.nt at line 25:
Undefined variable 'count'
25 | var total = count + 1;
| ^
Suggestion: Did you forget to declare the variable with 'var'? Or maybe you need to import a module with 'use'?
Stack trace:
at calculateTotal (test.nt:25)
at processData (test.nt:18)
at main (test.nt:10)
Type Error¶
TypeError in test.nt at line 8:
Expected numbers but got other type
8 | var result = "hello" * 2;
| ^
Suggestion: Mathematical operations require numeric values. Use type conversion if needed.
Argument Error¶
ArgumentError in test.nt at line 15:
Function 'greet' expects 2 arguments but got 1
15 | greet("Alice");
| ^
Suggestion: Check the function definition to see how many arguments it expects.
Division Error¶
DivisionError in test.nt at line 20:
Division by zero is not allowed
20 | var result = 10 / 0;
| ^
Suggestion: Check that the divisor is not zero before performing division or modulo operations.
Configuration¶
Enabling/Disabling Colors¶
ErrorHandler::setColorEnabled(true); // Enable colors
ErrorHandler::setColorEnabled(false); // Disable colors
Enabling/Disabling Stack Traces¶
ErrorHandler::setStackTraceEnabled(true); // Show stack traces
ErrorHandler::setStackTraceEnabled(false); // Hide stack traces
Setting Source File Context¶
Implementation Details¶
Error Handler Class¶
The ErrorHandler class in include/runtime/error_handler.h provides static methods for reporting different types of errors:
// Report a syntax error
ErrorHandler::reportSyntaxError(message, token);
// Report a runtime error with stack trace
ErrorHandler::reportRuntimeError(message, fileName, line, stackTrace);
// Report specific error types
ErrorHandler::typeError(expected, got, fileName, line);
ErrorHandler::referenceError(name, fileName, line);
ErrorHandler::rangeError(message, fileName, line);
ErrorHandler::argumentError(expected, got, functionName, fileName, line);
ErrorHandler::divisionError(fileName, line);
ErrorHandler::stackOverflowError(fileName, line);
ErrorHandler::moduleError(moduleName, reason, fileName, line);
Stack Frame Tracking¶
The VM now tracks stack frames with file and line information for accurate error reporting:
struct CallFrame {
Function* function;
uint8_t* ip;
size_t slot_offset;
std::string fileName; // Source file name
int currentLine; // Current line number
};
Integration Points¶
- Scanner (Lexer): Reports lexical errors with character position
- Parser: Reports syntax errors with token information
- Compiler: Reports semantic errors during compilation
- VM: Reports runtime errors with stack traces
Best Practices¶
- Always set the current file when executing code from a file
- Provide source lines to the error handler for better context
- Enable colors for interactive development
- Keep stack traces enabled during development
- Catch and handle NeutronException for recoverable errors in REPL mode
Migration Guide¶
For Existing Code¶
Replace old error reporting:
// Old
std::cerr << "Error: " << message << std::endl;
exit(1);
// New
ErrorHandler::fatal(message, ErrorType::RUNTIME_ERROR);
Replace old runtime errors:
Update parser errors:
// Old
error(token, "Expect ';' after expression.");
// New
ErrorHandler::reportSyntaxError("Expect ';' after expression.", token);
Testing¶
Test the error handling system with:
This test file contains various error scenarios to demonstrate the improved error messages.
Exception Handling¶
Neutron now supports structured exception handling with try, catch, finally, and throw statements. This allows developers to handle errors gracefully and implement proper error recovery mechanisms.
Basic Exception Handling¶
try {
// Code that might throw an exception
var result = riskyOperation();
say("Success: " + result);
} catch (error) {
// Handle the exception
say("Error caught: " + error);
}
Try-Catch-Finally¶
try {
// Risky operation
var file = openFile("data.txt");
processFile(file);
} catch (error) {
// Handle specific error
say("Processing failed: " + error);
} finally {
// Always execute cleanup
closeFile(file); // Ensures resource cleanup regardless of errors
}
Throwing Exceptions¶
fun validateInput(input) {
if (input == nil) {
throw "Input cannot be nil";
}
if (input.length < 3) {
throw "Input too short: " + input;
}
return true;
}
try {
validateInput("");
} catch (validationError) {
say("Validation error: " + validationError);
}
Exception Value Types¶
Neutron supports throwing any value as an exception:
throw "Simple error message"; // String
throw 404; // Number
throw true; // Boolean
throw [1, 2, 3]; // Array
throw {"error": "code", "msg": "desc"}; // Object
Nested Exception Handling¶
try {
try {
riskyInnerOperation();
} catch (innerError) {
say("Inner error handled: " + innerError);
// Optionally re-throw or handle differently
}
safeOuterOperation();
} catch (outerError) {
say("Outer error: " + outerError);
} finally {
cleanup();
}
Exception Flow¶
When an exception occurs:
1. The runtime searches for the nearest catch block in the current scope
2. If found, execution jumps to the catch block with the exception value
3. The finally block executes regardless of whether an exception occurred
4. If no catch block is found, the exception propagates up the call stack
5. Unhandled exceptions cause program termination with a runtime error
Future Enhancements¶
- Error recovery in parser for multiple error reporting
- Warning system for potential issues
- Custom error types for user-defined errors
- Error filtering and suppression options
- Integration with IDE language servers for inline errors
- JSON output format for tool integration