Metalang99 1.13.3
Full-blown preprocessor metaprogramming
util.h File Reference

Utilitary stuff. More...

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

Go to the source code of this file.

Macros

#define ML99_catEval(a, b)   ML99_call(ML99_catEval, a, b)
 Concatenates a with b and evaluates the result. More...
 
#define ML99_cat(a, b)   ML99_call(ML99_cat, a, b)
 Concatenates a with b, leaving the result unevaluated. More...
 
#define ML99_cat3(a, b, c)   ML99_call(ML99_cat3, a, b, c)
 The same as ML99_cat but deals with 3 parameters.
 
#define ML99_cat4(a, b, c, d)   ML99_call(ML99_cat4, a, b, c, d)
 The same as ML99_cat but deals with 4 parameters.
 
#define ML99_stringify(...)   ML99_call(ML99_stringify, __VA_ARGS__)
 Stringifies provided arguments. More...
 
#define ML99_empty(...)   ML99_callUneval(ML99_empty, )
 Evaluates to nothing.
 
#define ML99_id(...)   ML99_call(ML99_id, __VA_ARGS__)
 Evaluates to its arguments. More...
 
#define ML99_const(x, a)   ML99_call(ML99_const, x, a)
 Evaluates to x, skipping a. More...
 
#define ML99_flip(f)   ML99_call(ML99_flip, f)
 Reverses the order of arguments of the binary function f. More...
 
#define ML99_uncomma(...)   ML99_call(ML99_uncomma, __VA_ARGS__)
 Accepts terms and evaluates them with the space-separator. More...
 
#define ML99_reify(f)   ML99_call(ML99_reify, f)
 Turns f into a Metalang99-compliant metafunction with the arity of 1, which can be then called by ML99_appl. More...
 
#define ML99_todo(f)   ML99_call(ML99_todo, f)
 Indicates not yet implemented functionality of the macro f. More...
 
#define ML99_todoWithMsg(f, message)   ML99_call(ML99_todoWithMsg, f, message)
 The same as ML99_todo but emits a caller-supplied message. More...
 
#define ML99_unimplemented(f)   ML99_call(ML99_unimplemented, f)
 Indicates unimplemented functionality of the macro f. More...
 
#define ML99_unimplementedWithMsg(f, message)   ML99_call(ML99_unimplementedWithMsg, f, message)
 The same as ML99_unimplemented but emits a caller-supplied message. More...
 
#define ML99_GEN_SYM(prefix, id)   ML99_CAT4(prefix, id, _, __COUNTER__)
 Generates a unique identifier id in the namespace prefix. More...
 
#define ML99_TRAILING_SEMICOLON(...)   struct ml99_priv_trailing_semicolon
 Forces a caller to put a trailing semicolon. More...
 
#define ML99_CAT_PRIMITIVE(a, b)   a##b
 Concatenates a with b as-is, without expanding them. More...
 
#define ML99_CAT3_PRIMITIVE(a, b, c)   a##b##c
 The same as ML99_CAT_PRIMITIVE but deals with 3 parameters.
 
#define ML99_CAT4_PRIMITIVE(a, b, c, d)   a##b##c##d
 The same as ML99_CAT_PRIMITIVE but deals with 4 parameters.
 
#define ML99_STRINGIFY_PRIMITIVE(...)   #__VA_ARGS__
 Stringifies x as-is, without expanding it. More...
 
#define ML99_LPAREN(...)   (
 Expands to an opening parenthesis ((). More...
 
#define ML99_RPAREN(...)   )
 The same as ML99_LPAREN but emits a closing parenthesis. More...
 
#define ML99_COMMA(...)   ,
 Expands to a single comma, consuming all arguments.
 
#define ML99_GCC_PRAGMA(str)   ML99_PRIV_GCC_PRAGMA(str)
 If you are compiling on GCC, this macro expands to _Pragma(str), otherwise to emptiness.
 
#define ML99_CLANG_PRAGMA(str)   ML99_PRIV_CLANG_PRAGMA(str)
 The same as ML99_GCC_PRAGMA but for Clang.
 
#define ML99_CAT(a, b)   ML99_CAT_PRIMITIVE(a, b)
 
#define ML99_CAT3(a, b, c)   ML99_CAT3_PRIMITIVE(a, b, c)
 
#define ML99_CAT4(a, b, c, d)   ML99_CAT4_PRIMITIVE(a, b, c, d)
 
#define ML99_STRINGIFY(...)   ML99_STRINGIFY_PRIMITIVE(__VA_ARGS__)
 
#define ML99_EMPTY(...)
 
#define ML99_ID(...)   __VA_ARGS__
 

Detailed Description

Utilitary stuff.

Macro Definition Documentation

◆ ML99_cat

#define ML99_cat (   a,
 
)    ML99_call(ML99_cat, a, b)

Concatenates a with b, leaving the result unevaluated.

Examples

#define ABC123 Billie Jean
// Billie Jean
ML99_cat(v(ABC), v(123))
// 123ABC
ML99_cat(v(123), v(ABC))
#define v(...)
A value that is pasted as-is; no evaluation occurs on provided arguments.
Definition: lang.h:145
Utilitary stuff.
#define ML99_cat(a, b)
Concatenates a with b, leaving the result unevaluated.
Definition: util.h:53

◆ ML99_CAT_PRIMITIVE

#define ML99_CAT_PRIMITIVE (   a,
 
)    a##b

Concatenates a with b as-is, without expanding them.

Examples

// This macro will not be expanded.
#define ABC 7
// ABC123
#define ML99_CAT_PRIMITIVE(a, b)
Concatenates a with b as-is, without expanding them.
Definition: util.h:312

◆ ML99_catEval

#define ML99_catEval (   a,
 
)    ML99_call(ML99_catEval, a, b)

Concatenates a with b and evaluates the result.

Examples

#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))
#define ML99_catEval(a, b)
Concatenates a with b and evaluates the result.
Definition: util.h:34
Deprecated:
I have seen no single use case over time. Please, open an issue if you need this function.

◆ ML99_const

#define ML99_const (   x,
 
)    ML99_call(ML99_const, x, a)

Evaluates to x, skipping a.

Examples

// 123
ML99_const(v(123), v(5))
#define ML99_const(x, a)
Evaluates to x, skipping a.
Definition: util.h:110

◆ ML99_flip

#define ML99_flip (   f)    ML99_call(ML99_flip, f)

Reverses the order of arguments of the binary function f.

Examples

// ABC123
ML99_appl2(ML99_flip(v(ML99_catUnevaluated)), v(123), v(ABC))
#define ML99_appl2(f, a, b)
Applies a and b to f.
Definition: lang.h:110
#define ML99_flip(f)
Reverses the order of arguments of the binary function f.
Definition: util.h:124

◆ ML99_GEN_SYM

#define ML99_GEN_SYM (   prefix,
  id 
)    ML99_CAT4(prefix, id, _, __COUNTER__)

Generates a unique identifier id in the namespace prefix.

Let FOO be the name of an enclosing macro. Then FOO_ must be specified for prefix, and id should be given any meaningful name (this makes debugging easier).

Examples

#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.
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.
See also
https://en.wikipedia.org/wiki/Hygienic_macro

◆ ML99_id

#define ML99_id (   ...)    ML99_call(ML99_id, __VA_ARGS__)

Evaluates to its arguments.

Examples

// 1, 2, 3
ML99_id(v(1, 2, 3))
#define ML99_id(...)
Evaluates to its arguments.
Definition: util.h:96

◆ ML99_LPAREN

#define 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 macro FOO and complete the invocation of BAR with the rest of args...) in future.

This macro consumes all its arguments.

Deprecated:
This macro results in code that is difficult to reason about.

◆ ML99_reify

#define ML99_reify (   f)    ML99_call(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

#define F(x) @x
// @1 @2 @3
#define ML99_reify(f)
Turns f into a Metalang99-compliant metafunction with the arity of 1, which can be then called by ML9...
Definition: util.h:165
Variadic arguments: x, y, z.
#define ML99_variadicsForEach(f,...)
Applies f to each argument.
Definition: variadics.h:103

Without ML99_reify, you would need to write some additional boilerplate:

#define F_IMPL(x) v(@x)
#define F_ARITY 1

◆ ML99_RPAREN

#define ML99_RPAREN (   ...)    )

The same as ML99_LPAREN but emits a closing parenthesis.

Deprecated:
For the same reason as ML99_LPAREN.

◆ ML99_stringify

#define ML99_stringify (   ...)    ML99_call(ML99_stringify, __VA_ARGS__)

Stringifies provided arguments.

Examples

// "Billie Jean"
ML99_stringify(v(Billie Jean))
#define ML99_stringify(...)
Stringifies provided arguments.
Definition: util.h:77

◆ ML99_STRINGIFY_PRIMITIVE

#define ML99_STRINGIFY_PRIMITIVE (   ...)    #__VA_ARGS__

Stringifies x as-is, without expanding it.

Examples

// This macro will not be expanded.
#define ABC 7
// "ABC"
#define ML99_STRINGIFY_PRIMITIVE(...)
Stringifies x as-is, without expanding it.
Definition: util.h:339

◆ ML99_todo

#define ML99_todo (   f)    ML99_call(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

// A not-yet implemented error.
#define ML99_todo(f)
Indicates not yet implemented functionality of the macro f.
Definition: util.h:184
See also
Rust's std::todo! (thanks for the idea!)

◆ ML99_todoWithMsg

#define ML99_todoWithMsg (   f,
  message 
)    ML99_call(ML99_todoWithMsg, f, message)

The same as ML99_todo but emits a caller-supplied message.

message must be a string literal.

Examples

// A not-yet-implemented error.
ML99_todoWithMsg(v(F), v("your message"))
#define ML99_todoWithMsg(f, message)
The same as ML99_todo but emits a caller-supplied message.
Definition: util.h:200

◆ ML99_TRAILING_SEMICOLON

#define ML99_TRAILING_SEMICOLON (   ...)    struct ml99_priv_trailing_semicolon

Forces a caller to put a trailing semicolon.

It is useful when defining macros, to make them formatted as complete statements.

Examples

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

#define ML99_uncomma (   ...)    ML99_call(ML99_uncomma, __VA_ARGS__)

Accepts terms and evaluates them with the space-separator.

Examples

// 1 2 3
ML99_uncomma(ML99_QUOTE(v(1), v(2), v(3)))
#define ML99_QUOTE(...)
Delays evaluation for provided terms.
Definition: lang.h:226
#define ML99_uncomma(...)
Accepts terms and evaluates them with the space-separator.
Definition: util.h:138

◆ ML99_unimplemented

#define ML99_unimplemented (   f)    ML99_call(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

// A not-implemented error.
#define ML99_unimplemented(f)
Indicates unimplemented functionality of the macro f.
Definition: util.h:220
See also
Rust's std::unimplemented! (thanks for the idea!)

◆ ML99_unimplementedWithMsg

#define ML99_unimplementedWithMsg (   f,
  message 
)    ML99_call(ML99_unimplementedWithMsg, f, message)

The same as ML99_unimplemented but emits a caller-supplied message.

message must be a string literal.

Examples

// A not-implemented error.
ML99_unimplementedWithMsg(v(F), v("your message"))
#define ML99_unimplementedWithMsg(f, message)
The same as ML99_unimplemented but emits a caller-supplied message.
Definition: util.h:236