> For the complete documentation index, see [llms.txt](https://hirrolot.gitbook.io/metalang99/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hirrolot.gitbook.io/metalang99/testing-debugging-and-error-reporting.md).

# Testing, debugging, and error reporting

There is a handy macro for debugging a metaprogram. It is called `ML99_abort`:

```c
#define F_IMPL(x, y, z) v(x + y + z)

// abc
ML99_EVAL(ML99_call(F, v(1), v(2), ML99_abort(v(abc))))
```

`ML99_abort` evaluates a provided sequence of expressions and immediately aborts the interpretation. Despite that we call `F`, the result of the interpretation is `abc`. Here is how Metalang99 evaluates the aforementioned expression:

* `v(1)` => `1`
* `v(2)` => `2`
* `ML99_abort(v(abc))` => `abc`, then halt.

`ML99_abort` is very handy when you need to figure out what is wrong with your metaprogram. I often use the bottom-up approach: first, I ensure that all lower-level macros work as expected, then move on to more general macros, and so on, till I find the problem. To test a specific macro, I call it inside `ML99_EVAL(...)` separately from the rest of a metaprogram. With `ML99_abort`, I usually trace macro parameters as well as any other interesting terms. You can see the result of interpretation with `-E` (GCC/Clang flag; preprocess only).

Secondly, errors need to be somehow emitted. For example, if we try to pop the head of the empty list, we obtain the following compilation error:

```
playground.c:3:1: error: static assertion failed: "ML99_listHead: expected a non-empty list"
    3 | ML99_EVAL(ML99_listHead(ML99_nil()))
      | ^~~~~~~~~
```

To emit such an error, call `ML99_fatal` like this:

\[`playground.c`]

```c
ML99_EVAL(ML99_fatal(F, the description of your error))
```

\[`/bin/sh`]

```
playground.c:3:1: error: static assertion failed: "F: the description of your error"
    3 | ML99_EVAL(ML99_fatal(F, the description of your error))
      | ^~~~~~~~~
```

Metalang99 also features the macros `ML99_todo` and `ML99_unimplemented` as well as their `*WithMsg` versions. Using them, you can indicate a not yet implemented and unimplemented functionality, respectively. The difference is that `ML99_todo`/`ML99_todoWithMsg` convey an intent that some piece of code is to be implemented later, while `ML99_unimplemented`/`ML99_unimplementedWithMsg` do not make such claims. Consider this code:

```c
#define FOO(...) \
    ML99_EVAL(ML99_IF( \
        ML99_VARIADICS_IS_SINGLE(__VA_ARGS__), \
        v(123), \
        ML99_todoWithMsg(v(FOO), v("Multiple arguments are not yet supported"))))

// 123
FOO(1)

// A not-yet-implemented error.
FOO(1, 2, 3)
```

Here, `FOO(1)` works just fine but we are not yet to handle multiple arguments. No problem, just insert `ML99_todoWithMsg` and implement it later.

And eventually, if you want to test your macro on certain input values, you can use assertions:

```c
#define F_IMPL(x, y, z) v(x + y + z)
#define CAT_IMPL(x, y)  v(x##y)

ML99_ASSERT(v(1 == 1));
ML99_ASSERT_EQ(ML99_call(F, v(1, 2, 3)), v(1 + 2 + 3));
ML99_ASSERT_EMPTY(ML99_call(CAT, v(), v()));
```

Learn more about assertions [here](https://metalang99.readthedocs.io/en/latest/assert.html).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://hirrolot.gitbook.io/metalang99/testing-debugging-and-error-reporting.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
