Skip to content

Commit 8e511ea

Browse files
Add barebones-macro.c
1 parent 96a7cef commit 8e511ea

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

barebones-macro.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
/* The `Show` typeclass allows types to be turned into their string representation */
6+
typedef struct
7+
{
8+
char* (*const show)(void* self);
9+
} ShowTC;
10+
11+
typedef struct
12+
{
13+
void* self;
14+
ShowTC const* tc;
15+
} Show;
16+
17+
#define impl_show(T, Name, show_f) \
18+
Show Name(T* x) \
19+
{ \
20+
char* (*const show_)(T* self) = (show_f); \
21+
(void)show_; \
22+
static ShowTC const tc = {.show = (char* (*const)(void*))(show_f) }; \
23+
return (Show){.tc = &tc, .self = x}; \
24+
}
25+
26+
/* Polymorphic printing function */
27+
void print(Show showable)
28+
{
29+
char* const s = showable.tc->show(showable.self);
30+
puts(s);
31+
free(s);
32+
}
33+
34+
35+
/* A very holy enum */
36+
typedef enum
37+
{
38+
holy,
39+
hand,
40+
grenade
41+
} Antioch;
42+
43+
static inline char* strdup_(char const* x)
44+
{
45+
char* const s = malloc((strlen(x) + 1) * sizeof(*s));
46+
strcpy(s, x);
47+
return s;
48+
}
49+
50+
/* The `show` function implementation for `Antioch*` */
51+
static char* antioch_show(Antioch* x)
52+
{
53+
/*
54+
Note: The `show` function of a `Show` typeclass is expected to return a malloc'ed value
55+
The users of a generic `Show` are expected to `free` the returned pointer from the function `show`.
56+
*/
57+
switch (*x)
58+
{
59+
case holy:
60+
return strdup_("holy");
61+
case hand:
62+
return strdup_("hand");
63+
case grenade:
64+
return strdup_("grenade");
65+
default:
66+
return strdup_("breakfast cereal");
67+
}
68+
}
69+
70+
/* Make function to build a generic `Show` out of a concrete type- `Antioch` */
71+
impl_show(Antioch, prep_antioch_show, antioch_show)
72+
73+
int main(void)
74+
{
75+
Show const antsh = prep_antioch_show(&(Antioch){ hand });
76+
print(antsh);
77+
return 0;
78+
}

0 commit comments

Comments
 (0)