Metalang99 1.13.3
Full-blown preprocessor metaprogramming
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. More...
 
#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. More...
 
#define ML99_appl(f, ...)   ML99_call(ML99_appl, f, __VA_ARGS__)
 Applies arguments to f. More...
 
#define ML99_appl2(f, a, b)   ML99_call(ML99_appl2, f, a, b)
 Applies a and b to f. More...
 
#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. More...
 
#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. More...
 
#define ML99_abort(...)   (0abort, __VA_ARGS__)
 Immediately aborts the interpretation with evaluated arguments. More...
 
#define ML99_TERMS(...)   __VA_ARGS__
 A convenience macro to emphasise that your metafunction expands to more than one term. More...
 
#define ML99_QUOTE(...)   v(__VA_ARGS__)
 Delays evaluation for provided terms. More...
 

Detailed Description

The core metalanguage.

Macro Definition Documentation

◆ ML99_abort

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

Immediately aborts the interpretation with evaluated arguments.

Examples

#define F_IMPL(x) v(~)
// 123
The core metalanguage.
#define ML99_call(op,...)
Invokes a metafunction with arguments.
Definition: lang.h:33
#define ML99_abort(...)
Immediately aborts the interpretation with evaluated arguments.
Definition: lang.h:191
#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:

#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

#define F_IMPL(x, y) v(x##y)
#define F_ARITY 2
// ab
ML99_appl(ML99_appl(v(F), v(a)), v(b))
#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,
 
)    ML99_call(ML99_appl2, f, a, b)

Applies a and b to f.

Examples

#define F_IMPL(x, y) v(x##y)
#define F_ARITY 2
// ab
ML99_appl2(v(F), v(a), v(b))
#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,
 
)    ML99_call(ML99_compose, f, g)

Functional composition of f and g.

Examples

#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))
#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

#define F_IMPL(x, y) v(x + y)
ML99_EVAL(v(abc ~ 123), ML99_call(F, v(1, 2)))
#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]

ML99_EVAL(ML99_fatal(F, the description of your error))
#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

#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.
#define ML99_QUOTE(...)
Delays evaluation for provided terms.
Definition: lang.h:226

◆ ML99_TERMS

#define ML99_TERMS (   ...)    __VA_ARGS__

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

This macro just expands to provided arguments.

Examples

#define F_IMPL(x) ML99_TERMS(v(1), v(x), v(2))