-
Notifications
You must be signed in to change notification settings - Fork 1
/
chunktional.h
77 lines (53 loc) · 2.65 KB
/
chunktional.h
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
// Chunktional.h
// Steven Brunwasser, altece.com
// A collection of C Macros for making functional-style programming more intuitive in C.
#ifndef CHUNKTIONAL_H
#define CHUNKTIONAL_H
#include <stdlib.h>
#include <stdarg.h>
////
// datatype declarations
// define a datatype and all it's concrete types
#define datatype(dataname, ...) enum dataname { __VA_ARGS__ }; typedef struct { enum dataname type; } dataname;
// define the structure for a concrete type of a datatype
// will create "private" allocation and initialization static inline functions for the concrete type
#define datatypedefine(dataname, option, structure) struct option { enum dataname type; struct structure; }; \
static inline dataname *mk ## option () { \
void *v = allocdatatype(option); \
((struct option *)v)->type = option; \
return v; \
} \
static inline dataname *init ## option (dataname *value, struct option raw) { \
*((struct option *)value) = raw; \
return value; \
}
// define a concrete type of a datatype as being an atom
#define datatypeatom(dataname, option) datatypedefine(dataname, option, {})
////
// datatype creation and initialization
// allocate the raw space for the concrete type
#define allocdatatype(option) ((void *)calloc(1, sizeof(struct option)))
// "private" stack constructor for the concrete type
#define __mkdatatype(option, ...) ((struct option) {option, {__VA_ARGS__}})
// allocate and initialize a new instance of the concrete type
#define mkdatatype(option, ...) init ## option (mk ## option (), __mkdatatype(option, ## __VA_ARGS__))
////
// caseof statement
// open a new caseof statement for a given datatype instance
#define caseof(value) { void *___VALUE___ = value; switch((int)value->type) { case -99: {
// close a caseof statement
#define endcaseof ;} break; }}
// define a case for an instance of the specified concrete type assigned to the given value symbol
#define where(option, result) ;} break; case option: { struct option *result = (struct option *)___VALUE___;
// define a case for an atom instance of the specified concrete type
#define whereatom(option) ;} break; case option: {
// define a default case for the caseof statement
#define otherwise ;} break; default: {
////
// closures
// define a closure of the given type, for the given symbol name,
// whose closure would follow the given structure, and that takes the given parameters
#define closure(type, fn, context, ...) struct _ ## fn ## _context context; type fn (struct _ ## fn ## _context closure, ## __VA_ARGS__)
// call a closure function with the given context structure and parameters
#define call(fn, context, ...) fn((struct _ ## fn ## _context)context, ## __VA_ARGS__)
#endif