Metalang99 1.13.3
Full-blown preprocessor metaprogramming
|
The core metalanguage. More...
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 emphasise that your metafunction expands to more than one term. | |
#define | ML99_QUOTE(...) v(__VA_ARGS__) |
Delays evaluation for provided terms. | |
The core metalanguage.
#define ML99_abort | ( | ... | ) | (0abort, __VA_ARGS__) |
Immediately aborts the interpretation with evaluated arguments.
#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:
In this case, x
, y
, and z
can be specified separately but other arguments all at once.
#define ML99_appl2 | ( | f, | |
a, | |||
b | |||
) | ML99_call(ML99_appl2, f, a, b) |
Applies a
and b
to f
.
#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.
#define ML99_compose | ( | f, | |
g | |||
) | ML99_call(ML99_compose, f, g) |
Functional composition of f
and g
.
#define ML99_EVAL | ( | ... | ) | ML99_PRIV_EVAL(__VA_ARGS__) |
#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.
[playground.c
]
[/bin/sh
]
#define ML99_QUOTE | ( | ... | ) | v(__VA_ARGS__) |
Delays evaluation for provided terms.
ML99_QUOTE(...)
is functionally equivalent to v(...)
.
#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.