# Syntax and semantics

The core metalanguage is fairly small. It has only these four types of expressions:

* `ML99_call(F, ...)` invokes `F` with provided arguments. `F` must be either a functional macro identifier or an expression that evaluates to a functional macro identifier; `...` must comprise a non-empty sequence of comma-separated expressions.
* `v(...)` merely evaluates to its arguments, e.g. `v(123)` evaluates to `123`.
* `ML99_abort(...)` evaluates a non-empty sequence of comma-separated expressions and immediately aborts interpretation.
* `ML99_fatal(F, ...)` aborts interpretation with an appropriate error message.

(Indeed, expressions do nothing unless interpreted -- i.e., they are lazy.)

All metaprograms in Metalang99 represent a sequence of these syntactic forms. The interpreter itself is called via `ML99_EVAL(...)`.

Let's move on to examples. Consider this:

```c
ML99_EVAL(v(123), v(~), v(***))
```

It simply evaluates to `123 ~ ***` as expected. Now consider the mechanics of a functional macro (aka "metafunction"):

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

ML99_EVAL(ML99_call(F, v(1), v(2), v(3)))
```

It evaluates to `1 + 2 + 3`. Here, `v(1), v(2), v(3)` is a sequence of comma-separated expressions provided to `F`: Metalang99 evaluates each one and applies them to `F` like this: `F_IMPL(1, 2, 3)`. Notice that if we write `ML99_call(F, v(1, 2, 3))`, we achieve the same result because `v(1, 2, 3)` evaluates to `1, 2, 3` -- exactly the same arguments.

As you can see, the syntax `ML99_call(F, ...)` is a bit inconvenient. For the sake of proper code formatting and IDE support, the convention used by the Metalang99 standard library is to define a wrapper macro that expands to a Metalang99 call:

```c
/// The documentation string.
#define FOO(a, b, c) ML99_call(FOO, a, b, c)
#define FOO_IMPL(a, b, c) // The implementation.
```

This way `FOO` can be conveniently called as `FOO(v(1), v(2), v(3))`.

### Recursion

Why do we need custom syntax for invoking functional macros? Because it lets you express recursion with no hassle! Consider the following demonstrative example:

```c
#define X_IMPL(op)        ML99_call(op, v(123))
#define CALL_X_IMPL(_123) ML99_call(X, v(ID))
#define ID_IMPL(x)        v(x)

ML99_EVAL(ML99_call(X, v(CALL_X)))
```

It evaluates to `123`, as expected. However, without Metalang99, the expansion gets blocked:

```c
#define X(op)        op(123)
#define CALL_X(_123) X(ID)
#define ID(x)        x

// X(ID)
X(CALL_X)
```

It happens because `X(CALL_X)` expands to `CALL_X(123)`, which, in turn, expands to `X(ID)` -- the recursive macro call which is blocked by the preprocessor (see the [Cloak wiki](https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms#recursion)).

General macro recursion allows expressing things that were inexpressible using vanilla preprocessor macros. For example, you can leverage [Cons-lists](https://metalang99.readthedocs.io/en/latest/list.html) to do pretty much anything with unbounded sequences of arguments, as we shall see later. Internally, such metafunctions as [`ML99_listReplicate`](https://metalang99.readthedocs.io/en/latest/list.html#c.ML99_listReplicate), [`ML99_listReverse`](https://metalang99.readthedocs.io/en/latest/list.html#c.ML99_listReverse), or [`ML99_listFilter`](https://metalang99.readthedocs.io/en/latest/list.html#c.ML99_listFilter) are implemented by structural recursion, which would be impossible without Metalang99.

### Appendix: The use of \`v\`

Throughout the examples, you might have noticed the extensive use of the `v(...)` expression. Although it may be a bit confusing for newcomers, the purpose of `v(...)` is pretty simple: just say the Metalang99 interpreter to evaluate your stuff inside the parentheses as-is.

Take a look at this *erroneous* metafunction:

```c
#define POW2_IMPL(x) x * x
```

If we try to use it like this: `ML99_EVAL(ML99_call(POW2, v(3)))`, Metalang99 would complain at us:

```
test.c:5:1: error: static assertion failed: "invalid term `3 * 3`"
    5 | ML99_EVAL(ML99_call(POW2, v(3)))
      | ^~~~~~~~~
```

The reason for this is that every single metafunction called by `ML99_call` (`ML99_callUneval`, `ML99_appl`) must emit a proper Metalang99 term;  `3 * 3` is not a proper term according to the core language syntax. To fix the problem, just wrap `x * x` into `v`:

```c
#define POW2_IMPL(x) v(x * x)
```

You can think of `v` as of a literal expression, like `"abc"` or `42` in most programming languages. However, if you want Metalang99 to evaluate an expression according to its semantics, you need **not** use `v(...)` but instead provide a computable term:

```c
#define GEN_IMPL(n) ML99_repeat(v(n), ML99_appl(v(ML99_cat), v(_)))

// _0 _1 _2 _3 _4
ML99_EVAL(ML99_call(GEN, v(5)))
```

The same holds for metafunction arguments.
