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) ML99_call(ML99_catEval, a, b)
| Concatenates `a` with `b` and evaluates the result.
#define | ML99_cat(a, b) ML99_call(ML99_cat, a, b)
| Concatenates `a` with `b`, leaving the result unevaluated.
#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.
#define | ML99_empty(...) ML99_callUneval(ML99_empty, )
| Evaluates to nothing.
#define | ML99_id(...) ML99_call(ML99_id, __VA_ARGS__)
| Evaluates to its arguments.
#define | ML99_const(x, a) ML99_call(ML99_const, x, a)
| Evaluates to `x`, skipping `a`.
#define | ML99_flip(f) ML99_call(ML99_flip, f)
| Reverses the order of arguments of the binary function `f`.
#define | ML99_uncomma(...) ML99_call(ML99_uncomma, __VA_ARGS__)
| Accepts terms and evaluates them with the space-separator.
#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.
#define | ML99_todo(f) ML99_call(ML99_todo, f)
| Indicates not yet implemented functionality of the macro `f`.
#define | ML99_todoWithMsg(f, message) ML99_call(ML99_todoWithMsg, f, message)
| The same as ML99_todo but emits a caller-supplied message.
#define | ML99_unimplemented(f) ML99_call(ML99_unimplemented, f)
| Indicates unimplemented functionality of the macro `f`.
#define | ML99_unimplementedWithMsg(f, message) ML99_call(ML99_unimplementedWithMsg, f, message)
| The same as ML99_unimplemented but emits a caller-supplied message.
#define | ML99_GEN_SYM(prefix, id) ML99_CAT4(prefix, id, _, __COUNTER__)
| Generates a unique identifier `id` in the namespace `prefix`.
#define | ML99_TRAILING_SEMICOLON(...) struct ml99_priv_trailing_semicolon
| Forces a caller to put a trailing semicolon.
#define | ML99_CAT_PRIMITIVE(a, b) a##b
| Concatenates `a` with `b` as-is, without expanding them.
#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.
#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) 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,
|  |  | b
| ) |  | ML99_call(ML99_cat, a, b)

Concatenates `a` with `b`, 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))
v
#define v(...)
A value that is pasted as-is; no evaluation occurs on provided arguments.
Definition lang.h:145
util.h
Utilitary stuff.
ML99_cat
#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,
|  |  | b
| ) |  | a##b

Concatenates `a` with `b` 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_CAT_PRIMITIVE
#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,
|  |  | b
| ) |  | ML99_call(ML99_catEval, a, b)

Concatenates `a` with `b` 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))
ML99_catEval
#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,
|  |  | a
| ) |  | ML99_call(ML99_const, x, a)

Evaluates to `x`, skipping `a`.

# Examples

#include <metalang99/util.h>
// 123
ML99_const(v(123), v(5))
ML99_const
#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

#include <metalang99/util.h>
// ABC123
ML99_appl2(ML99_flip(v(ML99_catUnevaluated)), v(123), v(ABC))
ML99_appl2
#define ML99_appl2(f, a, b)
Applies a and b to f.
Definition lang.h:110
ML99_flip
#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

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

#include <metalang99/util.h>
// 1, 2, 3
ML99_id(v(1, 2, 3))
ML99_id
#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

#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))
ML99_reify
#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
variadics.h
Variadic arguments: x, y, z.
ML99_variadicsForEach
#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

#include <metalang99/util.h>
// "Billie Jean"
ML99_stringify(v(Billie Jean))
ML99_stringify
#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

#include <metalang99/util.h>
// This macro will not be expanded.
#define ABC 7
// "ABC"
ML99_STRINGIFY_PRIMITIVE(ABC)
ML99_STRINGIFY_PRIMITIVE
#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

#include <metalang99/util.h>
// A not-yet implemented error.
ML99_todo(v(F))
ML99_todo
#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

#include <metalang99/util.h>
// A not-yet-implemented error.
ML99_todoWithMsg(v(F), v("your message"))
ML99_todoWithMsg
#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

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

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

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_QUOTE
#define ML99_QUOTE(...)
Delays evaluation for provided terms.
Definition lang.h:226
ML99_uncomma
#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

#include <metalang99/util.h>
// A not-implemented error.
ML99_unimplemented(v(F))
ML99_unimplemented
#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

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