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

Statement chaining. More...

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

Go to the source code of this file.

Macros

#define ML99_INTRODUCE_VAR_TO_STMT(...)   ML99_PRIV_INTRODUCE_VAR_TO_STMT_INNER(__VA_ARGS__)
 A statement chaining macro that introduces several variable definitions to a statement right after its invocation. More...
 
#define ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(ty, name, init)    ML99_PRIV_SHADOWS(for (ty *name = (init); name != 0; name = 0))
 The same as ML99_INTRODUCE_VAR_TO_STMT but deals with a single non-NULL pointer. More...
 
#define ML99_CHAIN_EXPR_STMT(expr)
 A statement chaining macro that executes an expression statement derived from expr right before the next statement. More...
 
#define ML99_CHAIN_EXPR_STMT_AFTER(expr)
 The same as ML99_CHAIN_EXPR_STMT but executes expr after the next statement. More...
 
#define ML99_SUPPRESS_UNUSED_BEFORE_STMT(expr)   ML99_CHAIN_EXPR_STMT((void)expr)
 A statement chaining macro that suppresses the "unused X" warning right before a statement after its invocation. More...
 

Detailed Description

Statement chaining.

This module exports a bunch of so-called statement chaining macros: they expect a statement right after their invocation, and moreover, an invocation of such a macro with a statement afterwards altogether form a single statement.

How can this be helpful? Imagine you are writing a macro with the following syntax:

MY_MACRO(...) { bla bla bla }

Then MY_MACRO must expand to a statement prefix, i.e., something that expects a statement after itself. One possible solution is to make MY_MACRO expand to a sequence of statement chaining macros like this:

#define MY_MACRO(...) \
ML99_INTRODUCE_VAR_TO_STMT(int x = 5) \
ML99_CHAIN_EXPR_STMT(printf("%d\n", x)) \
// and so on...

Here ML99_INTRODUCE_VAR_TO_STMT accepts the statement formed by ML99_CHAIN_EXPR_STMT, which, in turn, accepts the next statement and so on, until a caller of MY_MACRO specifies the final statement, thus completing the chain.

See also
https://www.chiark.greenend.org.uk/~sgtatham/mp/ for a more involved explanation.

Macro Definition Documentation

◆ ML99_CHAIN_EXPR_STMT

#define ML99_CHAIN_EXPR_STMT (   expr)
Value:
ML99_PRIV_SHADOWS(for (int ml99_priv_expr_stmt_break = ((expr), 0); \
ml99_priv_expr_stmt_break != 1; \
ml99_priv_expr_stmt_break = 1))

A statement chaining macro that executes an expression statement derived from expr right before the next statement.

Top-level break/continue inside a user-provided statement are prohibited.

Example

int x;
for(;;)
ML99_CHAIN_EXPR_STMT(printf("%d\n", x))
puts("abc");
Statement chaining.
#define ML99_CHAIN_EXPR_STMT(expr)
A statement chaining macro that executes an expression statement derived from expr right before the n...
Definition: stmt.h:106

◆ ML99_CHAIN_EXPR_STMT_AFTER

#define ML99_CHAIN_EXPR_STMT_AFTER (   expr)
Value:
ML99_PRIV_SHADOWS(for (int ml99_priv_expr_stmt_after_break = 0; \
ml99_priv_expr_stmt_after_break != 1; \
((expr), ml99_priv_expr_stmt_after_break = 1)))

The same as ML99_CHAIN_EXPR_STMT but executes expr after the next statement.

◆ ML99_INTRODUCE_NON_NULL_PTR_TO_STMT

#define ML99_INTRODUCE_NON_NULL_PTR_TO_STMT (   ty,
  name,
  init 
)     ML99_PRIV_SHADOWS(for (ty *name = (init); name != 0; name = 0))

The same as ML99_INTRODUCE_VAR_TO_STMT but deals with a single non-NULL pointer.

In comparison with ML99_INTRODUCE_VAR_TO_STMT, this macro generates a little less code. It introduces a pointer to ty identified by name and initialised to init.

Top-level break/continue inside a user-provided statement are prohibited.

Example

double x = 5.0, y = 7.0;
for (int i = 0; i < 10; i++)
printf("i = %d, x = %f, y = %f\n", i, *x_ptr, *y_ptr);
#define ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(ty, name, init)
The same as ML99_INTRODUCE_VAR_TO_STMT but deals with a single non-NULL pointer.
Definition: stmt.h:84
Note
Unlike ML99_INTRODUCE_VAR_TO_STMT, the generated pointer is guaranteed to be used at least once, meaning that you do not need to suppress the unused variable warning.
init is guaranteed to be executed only once.

◆ ML99_INTRODUCE_VAR_TO_STMT

#define ML99_INTRODUCE_VAR_TO_STMT (   ...)    ML99_PRIV_INTRODUCE_VAR_TO_STMT_INNER(__VA_ARGS__)

A statement chaining macro that introduces several variable definitions to a statement right after its invocation.

Variable definitions must be specified as in the first clause of the for-loop.

Top-level break/continue inside a user-provided statement are prohibited.

Example

for (int i = 0; i < 10; i++)
ML99_INTRODUCE_VAR_TO_STMT(double x = 5.0, y = 7.0)
if (i % 2 == 0)
printf("i = %d, x = %f, y = %f\n", i, x, y);
#define ML99_INTRODUCE_VAR_TO_STMT(...)
A statement chaining macro that introduces several variable definitions to a statement right after it...
Definition: stmt.h:57

◆ ML99_SUPPRESS_UNUSED_BEFORE_STMT

#define ML99_SUPPRESS_UNUSED_BEFORE_STMT (   expr)    ML99_CHAIN_EXPR_STMT((void)expr)

A statement chaining macro that suppresses the "unused X" warning right before a statement after its invocation.

Top-level break/continue inside a user-provided statement are prohibited.

Example

int x, y;
for(;;)
puts("abc");
#define ML99_SUPPRESS_UNUSED_BEFORE_STMT(expr)
A statement chaining macro that suppresses the "unused X" warning right before a statement after its ...
Definition: stmt.h:140
Deprecated:
Use ML99_CHAIN_EXPR_STMT((void)expr) instead.