util.h¶
Utilitary stuff.
Defines
-
ML99_catEval(a, b)¶
Concatenates
a
withb
and evaluates the result.Examples
#include <metalang99/util.h> #define ABC123 v(Billie Jean) // Billie Jean ML99_catEval(v(ABC), v(123)) // ERROR: 123ABC is not a valid Metalang99 term. ML99_catEval(v(123), v(ABC))
- Deprecated:
I have seen no single use case over time. Please, open an issue if you need this function.
-
ML99_cat(a, b)¶
Concatenates
a
withb
, leaving the result unevaluated.Examples
#include <metalang99/util.h> #define ABC123 Billie Jean // Billie Jean ML99_cat(v(ABC), v(123)) // 123ABC ML99_cat(v(123), v(ABC))
-
ML99_stringify(...)¶
Stringifies provided arguments.
Examples
#include <metalang99/util.h> // "Billie Jean" ML99_stringify(v(Billie Jean))
-
ML99_empty(...)¶
Evaluates to nothing.
-
ML99_id(...)¶
Evaluates to its arguments.
Examples
#include <metalang99/util.h> // 1, 2, 3 ML99_id(v(1, 2, 3))
-
ML99_const(x, a)¶
Evaluates to
x
, skippinga
.Examples
#include <metalang99/util.h> // 123 ML99_const(v(123), v(5))
-
ML99_flip(f)¶
Reverses the order of arguments of the binary function
f
.Examples
#include <metalang99/util.h> // ABC123 ML99_appl2(ML99_flip(v(ML99_catUnevaluated)), v(123), v(ABC))
-
ML99_uncomma(...)¶
Accepts terms and evaluates them with the space-separator.
Examples
#include <metalang99/util.h> // 1 2 3 ML99_uncomma(ML99_QUOTE(v(1), v(2), v(3)))
-
ML99_reify(f)¶
Turns
f
into a Metalang99-compliant metafunction with the arity of 1, which can be then called by ML99_appl.f
can be any C function or function-like macro.Examples
#include <metalang99/util.h> #include <metalang99/variadics.h> #define F(x) @x // @1 @2 @3 ML99_variadicsForEach(ML99_reify(v(F)), v(1, 2, 3))
Without ML99_reify, you would need to write some additional boilerplate:
#define F_IMPL(x) v(@x) #define F_ARITY 1
-
ML99_todo(f)¶
Indicates not yet implemented functionality of the macro
f
.ML99_todo is the same as ML99_unimplemented except that the former conveys an intent that the functionality is to be implemented later but ML99_unimplemented makes no such claims.
Examples
#include <metalang99/util.h> // A not-yet implemented error. ML99_todo(v(F))
See also
Rust’s std::todo! (thanks for the idea!)
-
ML99_todoWithMsg(f, message)¶
The same as ML99_todo but emits a caller-supplied message.
message
must be a string literal.Examples
#include <metalang99/util.h> // A not-yet-implemented error. ML99_todoWithMsg(v(F), v("your message"))
-
ML99_unimplemented(f)¶
Indicates unimplemented functionality of the macro
f
.ML99_unimplemented is the same as ML99_todo except that the latter conveys an intent that the functionality is to be implemented later but ML99_unimplemented makes no such claims.
Examples
#include <metalang99/util.h> // A not-implemented error. ML99_unimplemented(v(F))
See also
Rust’s std::unimplemented! (thanks for the idea!)
-
ML99_unimplementedWithMsg(f, message)¶
The same as ML99_unimplemented but emits a caller-supplied message.
message
must be a string literal.Examples
#include <metalang99/util.h> // A not-implemented error. ML99_unimplementedWithMsg(v(F), v("your message"))
-
ML99_GEN_SYM(prefix, id)¶
Generates a unique identifier
id
in the namespaceprefix
.Let
FOO
be the name of an enclosing macro. ThenFOO_
must be specified forprefix
, andid
should be given any meaningful name (this makes debugging easier).Examples
#include <metalang99/util.h> #define FOO(...) FOO_NAMED(ML99_GEN_SYM(FOO_, x), __VA_ARGS__) #define FOO_NAMED(x_sym, ...) \ do { int x_sym = 5; __VA_ARGS__ } while (0) // `x` here will not conflict with the `x` inside `FOO`. FOO({ int x = 7; printf("x is %d\n", x); // x is 7 });
Note
Two identical calls to ML99_GEN_SYM will yield different identifiers, therefore, to refer to the result later, you must save it in an auxiliary macro’s parameter, as shown in the example above.
Note
ML99_GEN_SYM is defined only if
__COUNTER__
is defined, which must be a macro yielding integral literals starting from 0 incremented by 1 each time it is called. Currently, it is supported at least by Clang, GCC, TCC, and MSVC.
-
ML99_TRAILING_SEMICOLON(...)¶
Forces a caller to put a trailing semicolon.
It is useful when defining macros, to make them formatted as complete statements.
Examples
#include <metalang99/util.h> #define MY_MACRO(fn_name, val_ty, val) \ inline static val_ty fn_name(void) { return val; } \ ML99_TRAILING_SEMICOLON() // Defines a function that always returns 0. MY_MACRO(zero, int, 0);
Note
ML99_TRAILING_SEMICOLON is to be used outside of functions: unlike the
do { ... } while (0)
idiom, this macro expands to a C declaration.
-
ML99_CAT_PRIMITIVE(a, b)¶
Concatenates
a
withb
as-is, without expanding them.Examples
#include <metalang99/util.h> // This macro will not be expanded. #define ABC 7 // ABC123 ML99_CAT_PRIMITIVE(ABC, 123)
-
ML99_CAT3_PRIMITIVE(a, b, c)¶
The same as ML99_CAT_PRIMITIVE but deals with 3 parameters.
-
ML99_CAT4_PRIMITIVE(a, b, c, d)¶
The same as ML99_CAT_PRIMITIVE but deals with 4 parameters.
-
ML99_STRINGIFY_PRIMITIVE(...)¶
Stringifies
x
as-is, without expanding it.Examples
#include <metalang99/util.h> // This macro will not be expanded. #define ABC 7 // "ABC" ML99_STRINGIFY_PRIMITIVE(ABC)
-
ML99_LPAREN(...)¶
Expands to an opening parenthesis (
(
).This is helpful when you want to delay macro arguments passing: just type
BAR ML99_LPAREN() initial args...
at the end of some macroFOO
and complete the invocation ofBAR
withthe rest of args...)
in future.This macro consumes all its arguments.
- Deprecated:
This macro results in code that is difficult to reason about.
-
ML99_RPAREN(...)¶
The same as ML99_LPAREN but emits a closing parenthesis.
- Deprecated:
For the same reason as ML99_LPAREN.
-
ML99_COMMA(...)¶
Expands to a single comma, consuming all arguments.
-
ML99_GCC_PRAGMA(str)¶
If you are compiling on GCC, this macro expands to
_Pragma(str)
, otherwise to emptiness.
-
ML99_CLANG_PRAGMA(str)¶
The same as ML99_GCC_PRAGMA but for Clang.
-
ML99_CAT(a, b)¶
-
ML99_CAT3(a, b, c)¶
-
ML99_CAT4(a, b, c, d)¶
-
ML99_STRINGIFY(...)¶
-
ML99_EMPTY(...)¶
-
ML99_ID(...)¶