forked from avsm/EpiVM
-
Notifications
You must be signed in to change notification settings - Fork 10
/
closure.h
279 lines (221 loc) · 7.61 KB
/
closure.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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#ifndef _CLOSURE_H
#define _CLOSURE_H
# ifndef WIN32
# include <pthread.h>
# define GC_THREADS
# else
# define GC_WIN32_THREADS
# endif
#include <gc/gc.h>
//#include <emalloc.h>
#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define EMALLOC GC_malloc
#define EREADY(x)
#define EREALLOC GC_realloc
#define EFREE GC_free
typedef intptr_t eint;
//#define EMALLOC malloc
//#define EREALLOC realloc
//#define EFREE free
#define MKCON (con*)EMALLOC(sizeof(con))
#define MKFUN (fun*)EMALLOC(sizeof(fun))
#define MKTHUNK (thunk*)EMALLOC(sizeof(thunk))
#define MKCLOSURE (Closure*)EMALLOC(sizeof(Closure))
#define MKUNIT (void*)0
#define INTOP(op,x,y) MKINT((eint)((((eint)(x))>>1) op (((eint)(y))>>1)))
#define ADD(x,y) (void*)(((eint)x)+(((eint)y)-1))
#define MULT(x,y) (MKINT((((eint)x)>>1) * (((eint)y)>>1)))
#define CHECKEVALUATED(x) if(ISFUN(x) || ISTHUNK(x) \
|| ISFV(x)) return 0;
#define MKARGS(x) (void**)EMALLOC(sizeof(VAL)*(x));
#define MOREARGS(args,x) (void**)EREALLOC(args,sizeof(VAL)*(x));
typedef enum {
FUN,
THUNK,
CON,
INT,
BIGINT,
FLOAT,
BIGFLOAT,
STRING,
UNIT,
PTR,
FREEVAR,
IND
} ClosureType;
typedef struct {
int ty;
void* info;
} Closure;
void dumpClosure(Closure* c);
void assertConR(Closure* c);
void assertIntR(Closure* c);
#define assertCon(x)
#define assertInt(x)
//assertConR(x)
//assertIntR(x)
typedef Closure* VAL;
#define GETTY(x) (ISINT(x) ? INT : ((ClosureType)(((x)->ty) >> 24)))
#define QGETTY(x) ((ClosureType)(((x)->ty) >> 24))
#define SETTY(x,t) (x)->ty = (((eint)t) << 24)
#define REF(x) x
#define DEREF(x)
typedef void*(*func)(void**);
typedef struct {
func fn;
void** args;
void** arg_end;
int arity;
} fun;
typedef struct {
void* fn;
void** args;
int numargs;
} thunk;
typedef struct {
int tag;
void** args;
} con;
#define UPDATE(x,res) if (ISINT(res)) { x = MKINT(GETINT(res)); } else { \
SETTY(x, GETTY(res)); x->info=res->info; }
#define TAG(x) (((con*)((Closure*)x)->info)->tag & 65535)
#define ARITY(x) (((con*)((Closure*)x)->info)->tag >> 16)
#define ISCON(x) (GETTY(((Closure*)(x)))==CON)
#define ISINT(x) ((((eint)x)&1) == 1)
#define ISTHUNK(x) (GETTY(((Closure*)(x)))==THUNK)
#define ISFUN(x) (GETTY(((Closure*)(x)))==FUN)
#define ISFV(x) (GETTY(((Closure*)(x)))==FREEVAR)
#define NEEDSEVAL(x) ((x) && GETTY((Closure*)(x))<CON)
#define NONEEDSEVAL(x) ((x) && GETTY((Closure*)(x))>=CON)
#ifdef TRACEON
#define TRACE if(1)
#else
#define TRACE if(0)
#endif
// Evaluate x to head normal form
VAL DO_EVAL(VAL x, int update);
//#define EVAL(x) DO_EVAL(x)
#define EVAL(x) (!ISINT(x) && NEEDSEVAL(x) ? DO_EVAL(x, 1) : x)
#define EVALINT(x) (!ISINT(x) ? DO_EVAL(x, 1) : x)
#define EVAL_NOUP(x) (!ISINT(x) && NEEDSEVAL(x) ? DO_EVAL(x, 0) : x)
#define EVALINT_NOUP(x) (!ISINT(x) ? DO_EVAL(x, 0) : x)
//#define EVAL(x) ((x && (ISFUN(x) || ISTHUNK(x))) ? DO_EVAL(x, 1) : x)
//#define EVAL_NOUP(x) ((x && (ISFUN(x) || ISTHUNK(x))) ? DO_EVAL(x, 0) : x)
#define CONSTRUCTOR(t,a,b) ((a)==0 && t<255 ? zcon[t] : CONSTRUCTORn(t,a,b))
// Return a new constructor
inline VAL CONSTRUCTORn(int tag, int arity, void** block);
inline VAL CONSTRUCTOR1(int tag, VAL a1);
inline VAL CONSTRUCTOR2(int tag, VAL a1, VAL a2);
inline VAL CONSTRUCTOR3(int tag, VAL a1, VAL a2, VAL a3);
inline VAL CONSTRUCTOR4(int tag, VAL a1, VAL a2, VAL a3, VAL a4);
inline VAL CONSTRUCTOR5(int tag, VAL a1, VAL a2, VAL a3, VAL a4, VAL a5);
// Return a new function node
VAL CLOSURE(func x, int arity, int args, void** block);
// Add arguments to an already existing thunk
VAL CLOSURE_ADDN(VAL x, int args, void** block);
VAL CLOSURE_ADD1(VAL xin, VAL a1);
VAL CLOSURE_ADD2(VAL xin, VAL a1, VAL a2);
VAL CLOSURE_ADD3(VAL xin, VAL a1, VAL a2, VAL a3);
VAL CLOSURE_ADD4(VAL xin, VAL a1, VAL a2, VAL a3, VAL a4);
VAL CLOSURE_ADD5(VAL xin, VAL a1, VAL a2, VAL a3, VAL a4, VAL a5);
// Apply a closure to some arguments
VAL CLOSURE_APPLY(VAL x, int args, void** block);
VAL CLOSURE_APPLY1(VAL x, VAL a1);
VAL CLOSURE_APPLY2(VAL x, VAL a1, VAL a2);
VAL CLOSURE_APPLY3(VAL x, VAL a1, VAL a2, VAL a3);
VAL CLOSURE_APPLY4(VAL x, VAL a1, VAL a2, VAL a3, VAL a4);
VAL CLOSURE_APPLY5(VAL x, VAL a1, VAL a2, VAL a3, VAL a4, VAL a5);
// Project an argument from a constructor
#define PROJECT(x,arg) (((con*)((x)->info))->args[arg])
//void* DO_PROJECT(VAL x, int arg);
#define ASSIGNINT(t, x) t=MKINT(x);
//extern VAL one;
// array of zero arity constructors. We don't need more than one of each...
extern VAL* zcon;
#define MKINT(x) ((void*)(((x)<<1)+1))
#define GETINT(x) ((eint)(x)>>1)
#define GETPTR(x) ((void*)(((VAL)(x))->info))
#define GETSTR(x) ((char*)(((VAL)(x))->info))
#define INTTOEINT(x) ((eint)(x))
#define EINTTOINT(x) ((int)(x))
//void* MKINT(int x);
void* NEWBIGINT(char* bigint);
void* MKBIGINT(mpz_t* bigint);
void* MKSTR(char* str);
void* MKPTR(void* ptr);
// Get values from a closure
//int GETINT(void* x);
mpz_t* GETBIGINT(void* x);
//void* GETPTR(void* x);
void* MKFREE(void *x);
// Exit with fatal error
void ERROR(char* msg);
// Initialise everything
void init_evm();
void* FASTMALLOC(int size);
#define CONSTRUCTOR1m(c,t,x) \
c=EMALLOC(sizeof(Closure)+sizeof(con)+sizeof(VAL)); \
((con*)((VAL)c+1))->tag = t + (1 << 16); \
((con*)((VAL)c+1))->args = (void*)c+sizeof(Closure)+sizeof(con); \
((con*)((VAL)c+1))->args[0] = x; \
SETTY(((VAL)c),CON); \
((VAL)c)->info = (void*)((con*)((VAL)c+1)); \
EREADY(c);
#define CONSTRUCTOR2m(c,t,x,y) \
c=EMALLOC(sizeof(Closure)+sizeof(con)+2*sizeof(VAL)); \
((con*)((VAL)c+1))->tag = t + (2 << 16); \
((con*)((VAL)c+1))->args = (void*)c+sizeof(Closure)+sizeof(con); \
((con*)((VAL)c+1))->args[0] = x; \
((con*)((VAL)c+1))->args[1] = y; \
SETTY(((VAL)c),CON); \
((VAL)c)->info = (void*)((con*)((VAL)c+1)); \
EREADY(c);
#define CONSTRUCTOR3m(c,t,x,y,z) \
c=EMALLOC(sizeof(Closure)+sizeof(con)+3*sizeof(VAL)); \
((con*)((VAL)c+1))->tag = t + (3 << 16); \
((con*)((VAL)c+1))->args = (void*)c+sizeof(Closure)+sizeof(con); \
((con*)((VAL)c+1))->args[0] = x; \
((con*)((VAL)c+1))->args[1] = y; \
((con*)((VAL)c+1))->args[2] = z; \
SETTY(((VAL)c),CON); \
((VAL)c)->info = (void*)((con*)((VAL)c+1)); \
EREADY(c);
#define CONSTRUCTOR4m(c,t,x,y,z,w) \
c=EMALLOC(sizeof(Closure)+sizeof(con)+4*sizeof(VAL)); \
((con*)((VAL)c+1))->tag = t + (4<< 16); \
((con*)((VAL)c+1))->args = (void*)c+sizeof(Closure)+sizeof(con); \
((con*)((VAL)c+1))->args[0] = x; \
((con*)((VAL)c+1))->args[1] = y; \
((con*)((VAL)c+1))->args[2] = z; \
((con*)((VAL)c+1))->args[3] = w; \
SETTY(((VAL)c),CON); \
((VAL)c)->info = (void*)((con*)((VAL)c+1)); \
EREADY(c);
#define CONSTRUCTOR5m(c,t,x,y,z,w,v) \
c=EMALLOC(sizeof(Closure)+sizeof(con)+5*sizeof(VAL)); \
((con*)((VAL)c+1))->tag = t + (5 << 16); \
((con*)((VAL)c+1))->args = (void*)c+sizeof(Closure)+sizeof(con); \
((con*)((VAL)c+1))->args[0] = x; \
((con*)((VAL)c+1))->args[1] = y; \
((con*)((VAL)c+1))->args[2] = z; \
((con*)((VAL)c+1))->args[3] = w; \
((con*)((VAL)c+1))->args[4] = v; \
SETTY(((VAL)c),CON); \
((VAL)c)->info = (void*)((con*)((VAL)c+1)); \
EREADY(c);
// s = EMALLOC(sizeof(Closure)+strlen(x)+sizeof(char)+1);
#define INITSTRING(var, str) \
static Closure* var = NULL; \
if (var==NULL) { var = MKSTR(str); }
#define MKSTRm(c,s) c = s;
// SETTY((VAL)c, STRING);
// ((VAL)(c))->info = ((void*)c)+sizeof(Closure);
// strcpy(((VAL)(c))->info,x);
#define MKPTRm(c, x) \
c = MKCLOSURE; \
SETTY((VAL)c, PTR); \
((VAL)(c))->info = x;
#endif