-
Notifications
You must be signed in to change notification settings - Fork 0
/
continuation_passing.h
181 lines (142 loc) · 4.79 KB
/
continuation_passing.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#ifndef CONTINUATION_PASSING_H
#define CONTINUATION_PASSING_H
#include <assert.h>
#include "memory.h"
//
// Continuation memory management (doubly linked list)
//
#define internal static
#define DEFAULT_EXPAND_RATE 64
typedef struct cont_list_node {
struct cont_list_node *next;
struct cont_list_node *prev;
cont_p cont;
} cont_list_node;
typedef struct cont_list {
int count;
cont_list_node *first;
cont_list_node *last;
cont_list_node *next;
} cont_list;
extern cont_list *continuation_list;
cont_list *cont_list_create();
#define cont_list_count(L) ((L)->count)
#define cont_list_first(L) ((L)->first != NULL ? (L)->first->cont : NULL)
#define cont_list_last(L) ((L)->last != NULL ? (L)->last->cont : NULL)
#define cont_list_next(L) ((L)->next != NULL ? (L)->next->cont : NULL)
void cont_list_init(cont_list *list);
void cont_list_push_back(cont_list *list, cont_p cont);
void cont_list_push_front(cont_list *list, cont_p cont);
cont_p cont_list_obtain(cont_list *list);
void cont_list_release(cont_list *list);
cont_p cont_list_remove(cont_list *list, cont_list_node *node);
//
// Continuation passing calls
//
#define CP_CALL1(cont, func, arg1, next) \
return _CP_CALL1(cont, func, arg1, next);
internal inline cont_p
_CP_CALL1(cont_p cont, cont_func_t func, object_p arg1, cont_func_t next)
{
assert(continuation_list != NULL && "Continuation list must be preallocated");
cont_p new_cont = cont_list_obtain(continuation_list);
cont->next = next;
new_cont->caller = cont;
new_cont->args_locals[0] = arg1;
new_cont->next = func;
return new_cont;
}
#define CP_CALL2(cont, func, arg1, arg2, next) \
return _CP_CALL2(cont, func, arg1, arg2, next);
internal inline cont_p
_CP_CALL2(cont_p cont, cont_func_t func, object_p arg1, object_p arg2, cont_func_t next)
{
assert(continuation_list != NULL && "Continuation list must be preallocated");
cont_p new_cont = cont_list_obtain(continuation_list);
cont->next = next;
new_cont->caller = cont;
new_cont->args_locals[0] = arg1;
new_cont->args_locals[1] = arg2;
new_cont->next = func;
return new_cont;
}
#define CP_CALL3(cont, func, arg1, arg2, arg3, next) \
return _CP_CALL3(cont, func, arg1, arg2, arg3, next);
internal inline cont_p
_CP_CALL3(cont_p cont, cont_func_t func, object_p arg1, object_p arg2, object_p arg3, cont_func_t next)
{
assert(continuation_list != NULL && "Continuation list must be preallocated");
cont_p new_cont = cont_list_obtain(continuation_list);
cont->next = next;
new_cont->caller = cont;
new_cont->args_locals[0] = arg1;
new_cont->args_locals[1] = arg2;
new_cont->args_locals[2] = arg3;
new_cont->next = func;
return new_cont;
}
#define CP_CALL4(cont, func, arg1, arg2, arg3, arg4, next) \
return _CP_CALL4(cont, func, arg1, arg2, arg3, arg4, next);
internal inline cont_p
_CP_CALL4(cont_p cont, cont_func_t func, object_p arg1, object_p arg2, object_p arg3, object_p arg4, cont_func_t next)
{
assert(continuation_list != NULL && "Continuation list must be preallocated");
cont_p new_cont = cont_list_obtain(continuation_list);
cont->next = next;
new_cont->caller = cont;
new_cont->args_locals[0] = arg1;
new_cont->args_locals[1] = arg2;
new_cont->args_locals[2] = arg3;
new_cont->args_locals[3] = arg4;
new_cont->next = func;
return new_cont;
}
#define CP_TAILCALL1(cont, func, arg1) \
return _CP_TAILCALL1(cont, func, arg1);
internal inline cont_p
_CP_TAILCALL1(cont_p cont, cont_func_t func, object_p arg1)
{
cont->args_locals[0] = arg1;
cont->next = func;
return cont;
}
#define CP_TAILCALL2(cont, func, arg1, arg2) \
return _CP_TAILCALL2(cont, func, arg1, arg2);
internal inline cont_p
_CP_TAILCALL2(cont_p cont, cont_func_t func, object_p arg1, object_p arg2)
{
cont->args_locals[0] = arg1;
cont->args_locals[1] = arg2;
cont->next = func;
return cont;
}
#define CP_TAILCALL3(cont, func, arg1, arg2, arg3) \
return _CP_TAILCALL3(cont, func, arg1, arg2, arg3);
internal inline cont_p
_CP_TAILCALL3(cont_p cont, cont_func_t func, object_p arg1, object_p arg2, object_p arg3)
{
cont->args_locals[0] = arg1;
cont->args_locals[1] = arg2;
cont->args_locals[2] = arg3;
cont->next = func;
return cont;
}
#define CP_RETURN(cont, ret_val) \
return _CP_RETURN(cont, ret_val);
internal inline cont_p
_CP_RETURN(cont_p cont, object_p ret_val)
{
assert(continuation_list != NULL && "Continuation list must be preallocated");
cont->caller->ret_val = ret_val;
cont_list_release(continuation_list);
return cont->caller;
}
#define CP_JUMP(cont, func) \
return _CP_JUMP(cont, func);
internal inline cont_p
_CP_JUMP(cont_p cont, cont_func_t func)
{
cont->next = func;
return cont;
}
#endif