Loading...
Searching...
No Matches
lang.h File Reference

The core metalanguage. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

## Macros

#define | ML99_EVAL(...) ML99_PRIV_EVAL(__VA_ARGS__)
| Evaluates a metaprogram.
#define | ML99_call(op, ...) (ML99_PRIV_IF(ML99_PRIV_IS_UNTUPLE_FAST(op), 0args, 0op), op, __VA_ARGS__)
| Invokes a metafunction with arguments.
#define | ML99_callUneval(ident, ...) (0callUneval, ident, __VA_ARGS__)
| Invokes a metafunction `ident` with unevaluated arguments.
#define | ML99_appl(f, ...) ML99_call(ML99_appl, f, __VA_ARGS__)
| Applies arguments to `f`.
#define | ML99_appl2(f, a, b) ML99_call(ML99_appl2, f, a, b)
| Applies `a` and `b` to `f`.
#define | ML99_appl3(f, a, b, c) ML99_call(ML99_appl3, f, a, b, c)
| Applies `a`, `b`, and `c` to `f`.
#define | ML99_appl4(f, a, b, c, d) ML99_call(ML99_appl4, f, a, b, c, d)
| Applies `a`, `b`, `c`, and `d` to `f`.
#define | ML99_compose(f, g) ML99_call(ML99_compose, f, g)
| Functional composition of `f` and `g`.
#define | v(...) (0v, __VA_ARGS__)
| A value that is pasted as-is; no evaluation occurs on provided arguments.
#define | ML99_fatal(f, ...) (0fatal, f, #__VA_ARGS__)
| Emits a fatal error.
#define | ML99_abort(...) (0abort, __VA_ARGS__)
| Immediately aborts the interpretation with evaluated arguments.
#define | ML99_TERMS(...) __VA_ARGS__
| A convenience macro to emphasize that your metafunction expands to more than one term.
#define | ML99_QUOTE(...) v(__VA_ARGS__)
| Delays evaluation for provided terms.

## Detailed Description

The core metalanguage.

## Macro Definition Documentation

## ML99_abort

#define ML99_abort | ( |  | ... | ) | (0abort, __VA_ARGS__)

Immediately aborts the interpretation with evaluated arguments.

# Examples

#include <metalang99/lang.h>
#define F_IMPL(x) v(~)
// 123
ML99_call(F, ML99_abort(v(123)))
lang.h
The core metalanguage.
ML99_call
#define ML99_call(op,...)
Invokes a metafunction with arguments.
Definition lang.h:33
ML99_abort
#define ML99_abort(...)
Immediately aborts the interpretation with evaluated arguments.
Definition lang.h:191
v
#define v(...)
A value that is pasted as-is; no evaluation occurs on provided arguments.
Definition lang.h:145

## ML99_appl

#define ML99_appl | ( |  | f,
|  |  | ...
| ) |  | ML99_call(ML99_appl, f, __VA_ARGS__)

Applies arguments to `f`.

This function implements partial application: instead of invoking a metafunction with all arguments at once, you specify each argument separately. This concept allows better re-use of metafunctions by specifying some arguments immediately, and the other arguments later, even in different execution contexts (for example, see this SO answer).

`f` must be either a term reducing to a macro name or a term obtained via another call to ML99_appl. If `f` is a macro name, then a macro named `<f>_ARITY` (its arity specifier) must denote how many times `f` will be applied to its arguments. (In Metalang99, an arity is an intentionally more flexible concept than just a number of parameters, see below.) Each time ML99_appl is invoked, it accumulates provided variadic arguments and decrements the arity of `f`; when the arity of `f` is already 1, it eventually calls the initial `f` with all the accumulated arguments and provided variadic arguments.

Most often, an arity specifier denotes a count of all named parameters plus 1 if a macro is variadic (all the functions in the standard library follow this pattern). However, feel free to specify arities as you wish, with regard to the aforementioned semantics; for example, you can have a macro accepting `x, y, z` with an arity specifier `2`, then you must invoke ML99_appl exactly 2 times (either `x` + `y, z` or `x, y` + `z`). One common pattern is to match a head and a tail of variadic arguments:

#include <metalang99/lang.h>
#define F_IMPL(x, y, z, head, ...) // ...
#define F_ARITY 4

In this case, `x`, `y`, and `z` can be specified separately but other arguments all at once.

# Examples

#include <metalang99/lang.h>
#define F_IMPL(x, y) v(x##y)
#define F_ARITY 2
// ab
ML99_appl(ML99_appl(v(F), v(a)), v(b))
ML99_appl
#define ML99_appl(f,...)
Applies arguments to f.
Definition lang.h:93

Note
  Currently, the maximum arity is ML99_NAT_MAX. However, some compilers might not support more than 127 macro parameters.

## ML99_appl2

#define ML99_appl2 | ( |  | f,
|  |  | a,
|  |  | b
| ) |  | ML99_call(ML99_appl2, f, a, b)

Applies `a` and `b` to `f`.

# Examples

#include <metalang99/lang.h>
#define F_IMPL(x, y) v(x##y)
#define F_ARITY 2
// ab
ML99_appl2(v(F), v(a), v(b))
ML99_appl2
#define ML99_appl2(f, a, b)
Applies a and b to f.
Definition lang.h:110

## ML99_callUneval

#define ML99_callUneval | ( |  | ident,
|  |  | ...
| ) |  | (0callUneval, ident, __VA_ARGS__)

Invokes a metafunction `ident` with unevaluated arguments.

It is semantically the same as `ML99_call(ident, v(...))` but performs one less reduction steps.

## ML99_compose

#define ML99_compose | ( |  | f,
|  |  | g
| ) |  | ML99_call(ML99_compose, f, g)

Functional composition of `f` and `g`.

# Examples

#include <metalang99/lang.h>
#define F_IMPL(x) v((x + 1))
#define G_IMPL(x) v((x * 8))
#define F_ARITY 1
#define G_ARITY 1
// ((3 * 8) + 1)
ML99_appl(ML99_compose(v(F), v(G)), v(3))
ML99_compose
#define ML99_compose(f, g)
Functional composition of f and g.
Definition lang.h:140

## ML99_EVAL

#define ML99_EVAL | ( |  | ... | ) | ML99_PRIV_EVAL(__VA_ARGS__)

Evaluates a metaprogram.

# Examples

#include <metalang99/lang.h>
#define F_IMPL(x, y) v(x + y)
ML99_EVAL(v(abc ~ 123), ML99_call(F, v(1, 2)))
ML99_EVAL
#define ML99_EVAL(...)
Evaluates a metaprogram.
Definition lang.h:28

## ML99_fatal

#define ML99_fatal | ( |  | f,
|  |  | ...
| ) |  | (0fatal, f, #__VA_ARGS__)

Emits a fatal error.

`f` must be a macro name that has caused the error and the rest of arguments comprise the error message.

ML99_fatal interprets its variadic arguments without preprocessor expansion – i.e., they are pasted as-is. This is intended because otherwise identifiers located in an error message may stand for other macros that will be unintentionally expanded.

# Examples

[`playground.c`]

#include <metalang99/lang.h>
ML99_EVAL(ML99_fatal(F, the description of your error))
ML99_fatal
#define ML99_fatal(f,...)
Emits a fatal error.
Definition lang.h:174

[`/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))
| ^~~~~~~~~

## ML99_QUOTE

#define ML99_QUOTE | ( |  | ... | ) | v(__VA_ARGS__)

Delays evaluation for provided terms.

`ML99_QUOTE(...)` is functionally equivalent to `v(...)`.

# Examples

#include <metalang99/lang.h>
#define F_IMPL(x) v(~x)
#define PROG ML99_TERMS(v(1), v(2), ML99_call(F, v(7)))
// The same as `PROG` pasted into a source file.
ML99_EVAL(ML99_QUOTE(PROG))
ML99_QUOTE
#define ML99_QUOTE(...)
Delays evaluation for provided terms.
Definition lang.h:226

## ML99_TERMS

#define ML99_TERMS | ( |  | ... | ) | __VA_ARGS__

A convenience macro to emphasize that your metafunction expands to more than one term.

This macro just expands to provided arguments.

# Examples

#include <metalang99/lang.h>
#define F_IMPL(x) ML99_TERMS(v(1), v(x), v(2))