Exceptions
raise and the Exception module are not final (PRC-08, PRC-09).Library Design
The exception module belongs to the standard library: it is imported by default. It is written in Eve. A process that cannot continue raises an error; the workflow jumps into the recover region, where the developer reads $error. A warning does not interrupt the process: it is added to $trace and the process goes on. Warnings are reported in the final exit status of the driver.
Types
| Type | Members | Role |
|---|---|---|
| exception.Error | code: Integer, message: String, module: String, line: Integer, job: String, errors: ()Error | An error that interrupts a process. The base class of every error class; errors lists the errors of the aspects of a failed parallel group. |
| exception.Warning | code: Integer, message: String, module: String, line: Integer | A condition that is reported but does not interrupt the process. |
| exception.Call | line: String, method: String | One entry of the call stack. |
The class Error in the module Exception:
** system exception type
module exception is
export (Error, raise, expect, assert, warn);
** an error: its class and its code identify it; the exit code of the process is separate
class Error = {code: Integer, message: String, module: String, line: Integer, job: String} <: Object is
constructor(code = 4, message = "" :String) => (@self) is
let self := Object();
let self.code := code;
let self.message := message;
return;
end Error;
end exception;
System Variables and Objects
| Name | Type | Meaning |
|---|---|---|
| $error | Error | The last error of the process. |
| $stack | ()Call | The list of calls that led to the error. |
| $trace | ()Error | The list of errors and warnings of the process. |
The other system variables are listed in System Variables.
Signatures
Only the signatures are given. A declaration with the keyword external keeps only the signature: it is implemented in Zig by the virtual machine. The source of the module is evevm/lib/exception.eve. An exception is an object {code: x, message: y}; raise is overloaded and accepts a constructor call, a code constant with a message, a code with a message, an exception object, or only a message (code 4).
** raise an exception object
external raise(e: Error);
** raise an error with a code and a message
external raise(code: Integer, message: String);
** raise an error with the default code 4
external raise(message: String);
** raise $err_expect when the condition is false
external expect(condition: Logic, message := "");
** raise $err_assert when the condition is false
external assert(condition: Logic, message := "");
** report a warning and go on
external warn(code: Integer, message: String);
Predefined Constants
Every standard error and warning has a predefined constant: $err_name for an exception and $wrn_name for a warning. The constant is the integer code. In the recover region you compare it with the code of the error:
recover
if $error.code == $err_file do
print "Skip the missing file: " / $error.message;
resume;
else
abort;
done;
The constants are read only. An error is not an exit code: a driver that ends with an unhandled error ends with the exit code 4, and reports the code and the message of the error (see Exit Codes).
Error Classes
Every standard error is an object of a class derived from Error, and every class has its code (table Standard Exceptions). In the recover region you can test the class with is and read its fields, or compare the code with a constant:
recover
if $error is IoError do
retry; ** a transient error: try the job again
else if $error.code == $err_file do
resume; ** a missing file: go on
else
abort;
done;
A project defines its own errors as classes derived from Error, with codes from the project range: class HttpError = {status: Integer} <: Error;.
Code Ranges
| Codes | Use |
|---|---|
| 1 to 9 | The statements of the language: panic 1, expect 2, assert 3, raise 4 by default, then warnings. These are error codes, not exit codes. |
| 10 to 127 | Standard errors of the virtual machine and the library. |
| 128 to 255 | Errors defined by a project. Keep the codes of a project unique. |
Standard Exceptions
A message pattern is the message of the error. A name in braces is replaced with the value that caused the error. When a new exception is needed, add it to this table with the next free code of its range, then use its constant.
| Code | Class | Constant | Message pattern | Raised by |
|---|---|---|---|---|
| 1 | Panic | $err_panic | the message given to panic, or "Panic in line {line}" | panic |
| 2 | ExpectError | $err_expect | "Unexpected error in line {line}", or the custom message | expect |
| 3 | AssertError | $err_assert | "Assertion failed in line {line}", or the custom message | assert |
| 4 | Error | $err_raise | the message given to raise | raise without a code |
| 10 | IndexError | $err_index | "Index {index} is out of range {first}..{last}" | collections, strings |
| 11 | KeyError | $err_key | "Key {key} not found" | DataMap, DataSet |
| 12 | DivideError | $err_divide | "Division by zero" | arithmetic |
| 13 | OverflowError | $err_overflow | "Overflow in {operation}" | arithmetic |
| 14 | ConvertError | $err_convert | "Cannot convert {value} to {type}" | type conversion |
| 15 | ParseError | $err_parse | "Cannot parse {text} as {type}" | parse, literals read at run time |
| 16 | NullError | $err_null | "null value used as {type}" | any use of null |
| 17 | ArgumentError | $err_argument | "Invalid argument {name}: {reason}" | functions, methods, processes |
| 20 | FileError | $err_file | "File not found: {path}" | file and folder classes |
| 21 | AccessError | $err_access | "Access denied: {path}" | file and folder classes |
| 22 | IoError | $err_io | "Input/output error on {path}: {reason}" | streams, files |
| 30 | ModuleError | $err_module | "Module {name} not found in {library}" | from … use |
| 31 | ProcessError | $err_process | "Aspect {name} not found, or it has no process main" | apply, start |
| 40 | MemoryError | $err_memory | "Out of memory while allocating {size}" | virtual machine |
| 41 | TimeoutError | $err_timeout | "Time-out after {time}" | channels, parallel groups |
| 42 | DeadlockError | $err_deadlock | "Deadlock: every task of the group waits on a channel" | parallel groups |
| 43 | OutputError | $err_output | "Output {name} is given to two tasks of the group" | start |
| 44 | RecursionError | $err_recursion | "Recursion limit reached at depth {depth}" | virtual machine |
| 45 | ParallelError | $err_parallel | "{count} aspects of the group failed"; the list is $error.errors | parallel groups |
| 50 | DatabaseError | $err_database | "Database error {sqlstate} on {table}: {reason}" | databases (level 5) |
| 51 | ConnectionError | $err_connection | "Cannot reach {host}: {reason}"; transient | databases |
| 52 | ConstraintError | $err_constraint | "Constraint {constraint} violated by {key}" | databases |
| 53 | ConflictError | $err_conflict | "Row {key} was changed by someone else (version {version})" | databases, optimistic lock |
| 54 | MappingError | $err_mapping | "Mapping of {table} does not match the database: {differences}"; fatal, exit code 4 | databases, first use of a connection |
| 55 | CommitError | $err_commit | "Commit failed after {committed}"; fatal when partial | databases, two connections in a job |
| 56 | FormatError | $err_format | "Bad {format} at line {line}, column {column}: {reason}" | data files (level 5) |
| 57 | HttpError | $err_http | "HTTP {status} from {url}" | HTTP client |
Standard Warnings
The same rule applies: list every new warning in this table.
| Code | Constant | Message pattern | Reported by |
|---|---|---|---|
| 5 | $wrn_deprecated | "{name} is deprecated, use {other}" | library members marked deprecated |
| 6 | $wrn_truncate | "Value {value} truncated to {type}" | type conversion |
| 7 | $wrn_unused | "{name} is declared but never used" | compiler |
Exit Codes
The exit code of a process is a small number. It tells a shell or a scheduler how the process ended; the error itself is in the message.
| Exit code | Meaning |
|---|---|
| 0 | normal end: return, over, or the normal end of the recover region |
| 1 | panic |
| 2 | failed expect, not recovered |
| 3 | failed assert, not recovered |
| 4 | unhandled error: raise or a run-time error, not recovered |
| 5 | unexpected stop: Ctrl+C in the interpreter; a halt breakpoint in debug mode that the user ends with Ctrl+C or stop instead of resuming; recursion too deep; out of memory; hard time-out |
Read next: Databases