Error Handling
The Alia language provides the try, catch, and throw keywords for error handling.
1. Basic Syntax
The try-catch Statement
try <Stack tryStack> catch <Key e> <Stack catchStack>
Errors thrown in the try block are caught by catch, and the error value is bound to the variable e, whose scope is limited to the catch block. Alia has no finally clause.
The throw Statement
throw <Value error>
throw is a built-in alias that throws a ThrownError signal; its argument can be any value and is bound as-is when caught by catch. Throwing without an enclosing try terminates the program.
2. Basic Usage
Throwing Errors
throw new Error ['An error occurred']
throw new Error ['An error occurred', 'CustomError']
Catching Errors
try {
print 'Trying to execute'
throw new Error ['An error occurred']
print 'This line will not execute'
} catch e {
print 'Caught error: ' .. e
}
3. The Error Type
Error is the built-in error class, constructed as new Error ['message', 'name', 'cause'] with arguments passed positionally:
message: the error description, default''name: the error name, default'Error'cause: the original cause, defaultNullstack: stack information, taken fromcause;Nullwhen there is nocause
Instance methods:
toString/valueOf: string representation / message contenttoDescription/toColoredDescription: description text / colored descriptiontoCode/toColoredCode: code representation / colored code representation
const error = new Error ['Error message', 'CustomError']
print typeOf error ~ outputs 'Error'
print error.message ~ outputs 'Error message'
print error.name ~ outputs 'CustomError'
typeOf returns 'Error' for Error instances; use error.name to distinguish custom errors.
4. Example Code
4.1 Basic Error Handling
~ basic error handling
try {
print 'Starting execution'
const result = 10 / 0
print 'Result: ' .. result
} catch e {
print 'Caught error: ' .. e
}
print 'Continuing execution'
4.2 Custom Errors
~ custom errors: distinguish error kinds by name
try {
print 'Starting execution'
throw new Error ['Custom error', 'CustomError']
} catch e {
print 'Error message: ' .. e.message
print 'Error name: ' .. e.name
}
4.3 Nested Error Handling
~ nested error handling
try {
print 'Outer try starts'
try {
print 'Inner try starts'
throw new Error ['Inner error']
} catch innerError {
print 'Caught inner error: ' .. innerError
throw new Error ['Outer error']
}
} catch outerError {
print 'Caught outer error: ' .. outerError
}
4.4 Error Handling and Functions
~ error handling and functions
alias divide <Number a> <Number b> -> Number {
if b == 0 {
throw new Error ['Divisor cannot be zero', 'DivisionByZero']
}
return a / b
}
try {
const result = call divide [10, 0]
print 'Result: ' .. result
} catch e {
print 'Error: ' .. e
}
try {
const result = call divide [10, 2]
print 'Result: ' .. result
} catch e {
print 'Error: ' .. e
}
5. Error Handling Best Practices
5.1 Distinguish Error Kinds by name
alias validateUser <Object user> -> Boolean {
if user.name == '' {
throw new Error ['Username cannot be empty', 'ValidationError']
}
if user.email == '' {
throw new Error ['Email cannot be empty', 'ValidationError']
}
return true
}
try {
const user = *[ name: '', email: 'user@example.com' ]
validateUser user
} catch e {
if e.name == 'ValidationError' {
print 'Validation error: ' .. e.message
} else {
print 'Unknown error: ' .. e
}
}
5.2 Error Propagation
Catch errors in a function and re-throw them with additional context:
alias readFile <String path> -> {
try {
~ attempt to read the file
throw new Error ['File not found', 'FileError']
} catch e {
throw new Error ['Failed to read file: ' .. e.message .. ' (path: ' .. path .. ')', 'ReadError']
}
}
try {
readFile 'nonexistent.txt'
} catch e {
print 'Error: ' .. e.message
}
5.3 Error Recovery
Recover after catching an error and continue execution:
alias getUser <Number id> -> Object {
try {
~ attempt to fetch the user from the database
throw new Error ['User not found', 'NotFound']
} catch e {
~ return a default user
return *[ id: id, name: 'Unknown user' ]
}
}
const user = getUser 999
print 'User: ' .. user.name
6. Comparison with Other Languages
Compared with JavaScript
// JavaScript
try {
throw new Error('Error message');
} catch e {
console.log('Caught error:', e.message);
}
~ Alia
try {
throw new Error ['Error message']
} catch e {
print 'Caught error: ' .. e
}
Compared with Python
# Python
try:
raise Exception('Error message')
except Exception as e:
print('Caught error:', str(e))
~ Alia
try {
throw new Error ['Error message']
} catch e {
print 'Caught error: ' .. e
}
7. Error Diagnostics System
Alia implements a structured error diagnostics system that provides unified diagnostic output for the parsing, type checking, running, and compilation phases.
7.1 Diagnostic Output Format
Each diagnostic is rendered in a rounded rectangle box (plain text lines when not attached to a TTY) and contains the following fields:
- Type:
Error/Warn, with box colors red / yellow respectively. - Title: the top border shows
Error: <cause>/Warn: <cause>. - Direct location:
At <file-relative-location> line:column:(labels follow the locale). - Error code: the code line with a background and line numbers, with a squiggly mark under the error position.
- Error type:
Type: <category>:<specific code>, e.g.Type: TypeError:Mismatch. - Reason:
Reason: description of the corresponding cause. - Fix:
Fix: description of the suggested fix. - Fixed code: same format as the error code, with additions highlighted in green.
- Reference chain:
From: previous call location(if any).
7.2 Error Type Codes
Error type codes consist of <category>:<specific code>; the categories include:
ParseError: parsing errorsTypeError: type errorsRuntimeError: runtime errorsCompilerError: compilation errorsFFIError: FFI errors