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

Detailed Description

Utilitary stuff.

Macro Definition Documentation

◆ ML99_CAT

#define ML99_CAT ( a,
b )
Value:
#define ML99_CAT_PRIMITIVE(a, b)
Concatenates a with b as-is, without expanding them.
Definition util.h:312

◆ ML99_cat

#define ML99_cat ( a,
b )
Value:
#define ML99_call(op,...)
Invokes a metafunction with arguments.
Definition lang.h:33
#define ML99_cat(a, b)
Concatenates a with b, leaving the result unevaluated.
Definition util.h:53

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.

◆ ML99_CAT3

#define ML99_CAT3 ( a,
b,
c )
Value:
#define ML99_CAT3_PRIMITIVE(a, b, c)
The same as ML99_CAT_PRIMITIVE but deals with 3 parameters.
Definition util.h:317

◆ ML99_cat3

#define ML99_cat3 ( a,
b,
c )
Value:
#define ML99_cat3(a, b, c)
The same as ML99_cat but deals with 3 parameters.
Definition util.h:58

The same as ML99_cat but deals with 3 parameters.

◆ ML99_CAT3_PRIMITIVE

#define ML99_CAT3_PRIMITIVE ( a,
b,
c )
Value:
a##b##c

The same as ML99_CAT_PRIMITIVE but deals with 3 parameters.

◆ ML99_CAT4

#define ML99_CAT4 ( a,
b,
c,
d )
Value:
#define ML99_CAT4_PRIMITIVE(a, b, c, d)
The same as ML99_CAT_PRIMITIVE but deals with 4 parameters.
Definition util.h:322

◆ ML99_cat4

#define ML99_cat4 ( a,
b,
c,
d )
Value:
ML99_call(ML99_cat4, a, b, c, d)
#define ML99_cat4(a, b, c, d)
The same as ML99_cat but deals with 4 parameters.
Definition util.h:63

The same as ML99_cat but deals with 4 parameters.

◆ ML99_CAT4_PRIMITIVE

#define ML99_CAT4_PRIMITIVE ( a,
b,
c,
d )
Value:
a##b##c##d

The same as ML99_CAT_PRIMITIVE but deals with 4 parameters.

◆ ML99_CAT_PRIMITIVE

#define ML99_CAT_PRIMITIVE ( a,
b )
Value:
a##b

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

Examples

// This macro will not be expanded.
#define ABC 7
// ABC123

◆ ML99_catEval

#define ML99_catEval ( a,
b )
Value:
#define ML99_catEval(a, b)
Concatenates a with b and evaluates the result.
Definition util.h:34

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))
Deprecated
I have seen no single use case over time. Please, open an issue if you need this function.

◆ ML99_CLANG_PRAGMA

#define ML99_CLANG_PRAGMA ( str)
Value:
ML99_PRIV_CLANG_PRAGMA(str)

The same as ML99_GCC_PRAGMA but for Clang.

◆ ML99_COMMA

#define ML99_COMMA ( ...)
Value:
,

Expands to a single comma, consuming all arguments.

◆ ML99_const

#define ML99_const ( x,
a )
Value:
#define ML99_const(x, a)
Evaluates to x, skipping a.
Definition util.h:110

Evaluates to x, skipping a.

Examples

// 123
ML99_const(v(123), v(5))

◆ ML99_empty

#define ML99_empty ( ...)
Value:
#define ML99_callUneval(ident,...)
Invokes a metafunction ident with unevaluated arguments.
Definition lang.h:42
#define ML99_empty(...)
Evaluates to nothing.
Definition util.h:82

Evaluates to nothing.

◆ ML99_flip

#define ML99_flip ( f)
Value:
#define ML99_flip(f)
Reverses the order of arguments of the binary function f.
Definition util.h:124

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

◆ ML99_GCC_PRAGMA

#define ML99_GCC_PRAGMA ( str)
Value:
ML99_PRIV_GCC_PRAGMA(str)

If you are compiling on GCC, this macro expands to _Pragma(str), otherwise to emptiness.

◆ ML99_GEN_SYM

#define ML99_GEN_SYM ( prefix,
id )
Value:
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 ( ...)
Value:
__VA_ARGS__

◆ ML99_id

#define ML99_id ( ...)
Value:
ML99_call(ML99_id, __VA_ARGS__)
#define ML99_id(...)
Evaluates to its arguments.
Definition util.h:96

Evaluates to its arguments.

Examples

// 1, 2, 3
ML99_id(v(1, 2, 3))

◆ ML99_LPAREN

#define ML99_LPAREN ( ...)
Value:
(

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

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
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 ( ...)
Value:
)

The same as ML99_LPAREN but emits a closing parenthesis.

Deprecated
For the same reason as ML99_LPAREN.

◆ ML99_STRINGIFY

#define ML99_STRINGIFY ( ...)
Value:
#define ML99_STRINGIFY_PRIMITIVE(...)
Stringifies x as-is, without expanding it.
Definition util.h:339

◆ ML99_stringify

#define ML99_stringify ( ...)
Value:
#define ML99_stringify(...)
Stringifies provided arguments.
Definition util.h:77

Stringifies provided arguments.

Examples

// "Billie Jean"
ML99_stringify(v(Billie Jean))

◆ ML99_STRINGIFY_PRIMITIVE

#define ML99_STRINGIFY_PRIMITIVE ( ...)
Value:
#__VA_ARGS__

Stringifies x as-is, without expanding it.

Examples

// This macro will not be expanded.
#define ABC 7
// "ABC"

◆ ML99_todo

#define ML99_todo ( f)
Value:
#define ML99_todo(f)
Indicates not yet implemented functionality of the macro f.
Definition util.h:184

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.
See also
Rust's std::todo! (thanks for the idea!)

◆ ML99_todoWithMsg

#define ML99_todoWithMsg ( f,
message )
Value:
#define ML99_todoWithMsg(f, message)
The same as ML99_todo but emits a caller-supplied message.
Definition util.h:200

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

◆ ML99_TRAILING_SEMICOLON

#define ML99_TRAILING_SEMICOLON ( ...)
Value:
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 ( ...)
Value:
ML99_call(ML99_uncomma, __VA_ARGS__)
#define ML99_uncomma(...)
Accepts terms and evaluates them with the space-separator.
Definition util.h:138

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

◆ ML99_unimplemented

#define ML99_unimplemented ( f)
Value:
#define ML99_unimplemented(f)
Indicates unimplemented functionality of the macro f.
Definition util.h:220

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.
See also
Rust's std::unimplemented! (thanks for the idea!)

◆ ML99_unimplementedWithMsg

#define ML99_unimplementedWithMsg ( f,
message )
Value:
#define ML99_unimplementedWithMsg(f, message)
The same as ML99_unimplemented but emits a caller-supplied message.
Definition util.h:236

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