Loading...
Searching...
No Matches
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.
#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.
#define | ML99_CHAIN_EXPR_STMT(expr)
| A statement chaining macro that executes an expression statement derived from `expr` right before the next statement.
#define | ML99_CHAIN_EXPR_STMT_AFTER(expr)
| The same as ML99_CHAIN_EXPR_STMT but executes `expr` after the next statement.
#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.

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

#include <metalang99/stmt.h>
int x;
for(;;)
ML99_CHAIN_EXPR_STMT(x = 5)
ML99_CHAIN_EXPR_STMT(printf("%d\n", x))
puts("abc");
stmt.h
Statement chaining.
ML99_CHAIN_EXPR_STMT
#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 initialized to `init`.

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

# Example

#include <metalang99/stmt.h>
double x = 5.0, y = 7.0;
for (int i = 0; i < 10; i++)
ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(double, x_ptr, &x)
ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(double, y_ptr, &y)
printf("i = %d, x = %f, y = %f\n", i, *x_ptr, *y_ptr);
ML99_INTRODUCE_NON_NULL_PTR_TO_STMT
#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

#include <metalang99/stmt.h>
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);
ML99_INTRODUCE_VAR_TO_STMT
#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

#include <metalang99/stmt.h>
int x, y;
for(;;)
ML99_SUPPRESS_UNUSED_BEFORE_STMT(x)
ML99_SUPPRESS_UNUSED_BEFORE_STMT(y)
puts("abc");
ML99_SUPPRESS_UNUSED_BEFORE_STMT
#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.