lang.h¶
The core metalanguage.
Defines
-
ML99_EVAL(...)¶
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_call(op, ...)¶
Invokes a metafunction with arguments.
-
ML99_callUneval(ident, ...)¶
Invokes a metafunction
ident
with unevaluated arguments.It is semantically the same as
ML99_call(ident, v(...))
but performs one less reduction steps.
-
ML99_appl(f, ...)¶
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. Iff
is a macro name, then a macro named<f>_ARITY
(its arity specifier) must denote how many timesf
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 off
; when the arity off
is already 1, it eventually calls the initialf
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 specifier2
, then you must invoke ML99_appl exactly 2 times (eitherx
+y, z
orx, 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
, andz
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))
Note
Currently, the maximum arity is ML99_NAT_MAX. However, some compilers might not support more than 127 macro parameters.
-
ML99_appl2(f, a, b)¶
Applies
a
andb
tof
.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_appl3(f, a, b, c)¶
Applies
a
,b
, andc
tof
.
-
ML99_appl4(f, a, b, c, d)¶
Applies
a
,b
,c
, andd
tof
.
-
ML99_compose(f, g)¶
Functional composition of
f
andg
.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))
-
v(...)¶
A value that is pasted as-is; no evaluation occurs on provided arguments.
-
ML99_fatal(f, ...)¶
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))
[
/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_abort(...)¶
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)))
-
ML99_TERMS(...)¶
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))
-
ML99_QUOTE(...)¶
Delays evaluation for provided terms.
ML99_QUOTE(...)
is functionally equivalent tov(...)
.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))