← Back to davo.co
summaryrefslogtreecommitdiffstats
path: root/anonymous_function.c
blob: 8144e6ffda2622ef89c00f0d3d17ae8515184c23 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <stdio.h>

/**
 ** @file
 **
 ** This plays with gcc features to define a weird macro that emulates
 ** anonymous functions that can be used as closures. Don't use that
 ** seriously, this is only meant to prove that this is syntactically
 ** not a big deal, and that the ideas necessary for it can be found
 ** in modern compilers.
 **
 **/

/**
 ** @def ANONYMOUS(RET)
 ** @brief Use this to define an anonymous function with return type @a RET.
 **
 ** The @c ... argument list is the parameter list of the
 ** function. This the expects the code of the function in <code>({
 ** })</code> parenthesis. A simple example would be
 **
 ** @code
 ** // Function header
 ** ANONYMOUS(int) (double a, unsigned b)
 ** // Function body
 ** ({
 **    return printf("we found %g for %u, average %g\n", a, b, a/b);
 ** })
 ** // Function arguments
 ** (x, 23);
 ** @endcode
 **
 ** Of course you would usually put such things inside a macro. See
 ** MAX() for a more complicated example.
 **/
#ifdef __clang__
# define ANONYMOUS(RET) (^ RET ANON_PART2
# define ANON_PART2(...) (__VA_ARGS__) ANON_PART3
# define ANON_PART3(...) __VA_ARGS__)
#else
# define ANONYMOUS(RET) ({ RET __anon_func ANON_PART2
# define ANON_PART2(...) (__VA_ARGS__) ANON_PART3
# define ANON_PART3(...) __VA_ARGS__ __anon_func; })
#endif

#define MAXU(A, B)                              \
ANONYMOUS(uintmax_t) (uintmax_t a, uintmax_t b) \
({                                              \
    if (a < b) return b;                        \
    else return a;                              \
})                                              \
((A), (B))

#define MAX(A, B)                               \
/* function header */                           \
  /* return type */                             \
ANONYMOUS(__typeof__(1 ? (A) : (B)))            \
 /*and then argument list */                    \
(__typeof__(A) a, __typeof__(B) b)              \
/* function body */                             \
({                                              \
  if (a < b) return b;                          \
  else return a;                                \
 })                                             \
/* function call */                             \
((A), (B))

/**
 ** Test to see if that even works when such functions are nested.
 **/

typedef void df(unsigned);

df* Df[5] = { };

void g(unsigned level, unsigned depth) {
  Df[depth%5] =
    ANONYMOUS(void) (register unsigned a)
    ({
      printf("from level %u, depth %u found in position %u\n",
             level, depth,
             MAX(2*a, depth)
             );
      return;
    });
  if (level)
    g(level-1, depth+1);
  else
    for (unsigned i = 0; i < 5; ++i)
      if (Df[i]) Df[i](i);
}


int main(int argc, [[maybe_unused]] char* argv[]) {
  g(argc, 0);
}