# Error Handling Statements

Magma has facilities for both reporting and handling errors. Errors can arise in a variety of circumstances within Magma’s internal code (due to, for instance, incorrect usage of a function, or the unexpected failure of an algorithm). Magma allows the user to raise errors in their own code, as well as catch many kinds of errors.

## The Error Objects

All errors in Magma are of type `Err`. Error objects not only include a description of the error, but also information relating to the location at which the error was raised, and whether the error was a user error, or a system error.

### `Error(x): Any -> Err`

Constructs an error object with user information given by $x$, which can be of any type. The object $x$ is stored in the `Object` attributed of the constructed error object, and the `Type` attribute of the object is set to “ErrUser”. The remaining attributes are uninitialized until the error is raised by an `error` statement; at that point they are initialized with the appropriate positional information.

### `e`Position: Err -> MonStgElt`

Stores the position at which the error object $e$ was raised. If the error object has not yet been raised, the attribute is undefined.

### `e`Traceback: Err -> MonStgElt`

Stores the stack traceback giving the position at which the error object $e$ was raised. If the error object has not yet been raised, the attribute is undefined.

### `e`Object: Err -> Any`

Stores the user defined error information for the error. If the error is a system error, then this will be a string giving a textual description of the error.

### `e`Type: Err -> MonStgElt`

Stores the type of the error. Currently, there are only two types of errors in Magma: “Err” denotes a system error, and “ErrUser” denotes an error raised by the user.

## Error Checking and Assertions

### `error expression, ..., expression;`

Raises an error, with the error information being the printed value of the expressions. This statement is useful, for example, when an illegal value of an argument is passed to a function.

### `error if Boolean expression, expression, ..., expression;`

If the given boolean expression evaluates to `true`, then raises an error, with the error information being the printed value of the expressions. This statement is designed for checking that certain conditions must be met, etc.

### `assert Boolean expression;`

### `assert2 Boolean expression;`

### `assert3 Boolean expression;`

These assertion statements are useful to check that certain conditions are satisfied. There is an underlying `Assertions` flag, which is set to 1 by default.

For each statement, if the `Assertions` flag is less than the level specified by the statement (respectively 1, 2, 3 for the above statements), then nothing is done. Otherwise, the given boolean expression is evaluated and if the result is `false`, an error is raised, with the error information being an appropriate message.

It is recommended that when developing package code, `assert` is used for important tests (always to be tested in any mode), while `assert2` is used for more expensive tests, only to be checked in the debug mode, while `assert3` is be used for extremely stringent tests which are very expensive.

Thus the `Assertions` flag can be set to 0 for no checking at all, 1 for normal checks, 2 for debug checks and 3 for extremely stringent checking.

## Catching Errors

### `try statements catch e statements end try`

The `try`/`catch` statement lets users handle raised errors. The semantics of a `try`/`catch` statement are as follows: the block of statements $statements_1$ is executed. If no error is raised during its execution, then the block of statements $statements_2$ is not executed; if an error is raised at any point in $statements_1$, execution *immediately* transfers to $statements_2$ (the remainder of $statements_1$ is not executed). When transfer is controlled to the `catch` block, the variable named $e$ is initialized to the error that was raised by $statements_1$; this variable remains in scope until the end of the `catch` block, and can be both read from and written to. The catch block can, if necessary, reraise $e$, or any other error object, using an `error` statement.

### `Example: while (ex-33665a)`

The following example demonstrates the use of error objects, and `try`/`catch` statements.

```magma
> procedure always_fails(x)
>     error Error(x);
> end procedure;
>
> try
>     always_fails(1);
>     always_fails(2);  // we never get here
> catch e
>     print "In catch handler";
>     error "Error calling procedure with parameter: ", e`Object;
> end try;
In catch handler
Error calling procedure with parameter:  1

```
