-
Notifications
You must be signed in to change notification settings - Fork 0
/
coffee.h
398 lines (327 loc) · 9.12 KB
/
coffee.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
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
#ifndef COFFEE_H
#define COFFEE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define COFFEE_VERSION "0.1.0"
#define CF_VERSION COFFEE_VERSION
// #define OBJ_MAX 16000
#define STR(x) #x
#define CF_ASSERT(expr, error_msg) if(!(expr)) { \
fprintf(stderr, "[coffee] assertion '%s' failed, %s\n", STR(expr), error_msg); \
exit(1); \
}
#define CF_API
#define cf_foreach(vm, el, iter) for ((el) = cf_car((vm), (iter)); (iter) != cf_null((vm)); (iter) = cf_cdr((vm), (iter)), (el) = cf_car((vm), (iter)))
#define MARK_MASK 0x80
#define TYPE_MASK 0x7f
#define STACK_MAX 256
typedef struct Coffee Coffee;
typedef struct cf_bean_s cf_bean_t;
typedef cf_bean_t*(*cf_cfunc_t)(Coffee*);
typedef float cf_number_t;
typedef double cf_double_t;
typedef unsigned short cf_short_t;
typedef unsigned short cf_vptr_t;
typedef int cf_int_t;
typedef unsigned int cf_uint_t;
typedef long int cf_lint_t;
typedef void* cf_ptr_t;
typedef char* cf_string_t;
typedef char cf_bool_t;
typedef unsigned char cf_byte_t;
// co_short_t st;
// co_byte_t byte;
// co_string_t str;
typedef unsigned short cf_uint16;
typedef unsigned int cf_uint32;
typedef unsigned char cf_uint8;
typedef enum {
OP_RET = 0, // ret
OP_REQ, // req
OP_PRINT, // prn
OP_ADD, // +
OP_SUB, // -
OP_MUL, // *
OP_DIV // /
} OPCODE;
typedef struct cf_OpCode {
const char *name;
cf_byte_t args;
cf_cfunc_t fn;
} cf_OpCode;
CF_API cf_bean_t *cf_ret(Coffee *vm);
CF_API cf_bean_t *cf_req(Coffee *vm);
// CF_API cf_bean_t *cf_print(Coffee *vm);
CF_API cf_bean_t *cf_print(Coffee *vm);
CF_API cf_bean_t *cf_add(Coffee *vm);
CF_API cf_bean_t *cf_sub(Coffee *vm);
CF_API cf_bean_t *cf_mul(Coffee *vm);
CF_API cf_bean_t *cf_div(Coffee *vm);
CF_API cf_bean_t *cf_quote(Coffee *vm);
static cf_OpCode opcodes[] = {
{"ret", 1, NULL},
{"req", 1, NULL},
{"prn", -1, cf_print},
{"+", 2, cf_add},
{"-", 2, cf_sub},
{"*", 2, cf_mul},
{"/", 2, cf_div}
};
// typedef union cf_value_t {
// cf_byte_t header;
// cf_byte_t b;
// cf_number_t n;
// cf_string_t str;
// cf_ptr_t ptr;
// cf_cfunc_t fn;
// cf_bean_t *bn;
// } cf_value_t;
// typedef union cf_value_t {
// cf_byte_t b;
// struct {
// cf_byte_t p, q, r, s;
// };
// cf_byte_t str[4];
// cf_number_t n;
// cf_uint_t vptr;
// // cf_string_t
// } cf_value_t;
// co_value_t val;
typedef union cf_value_t {
cf_byte_t b;
cf_vptr_t vptr;
cf_uint_t tag;
cf_number_t n;
cf_uint_t i;
cf_byte_t str[4];
struct {
cf_vptr_t vptr0;
cf_vptr_t vptr1;
};
// struct
} cf_value_t;
struct cf_bean_s {
union {
struct {
cf_byte_t tag;
cf_vptr_t next;
union {
cf_byte_t byte;
cf_number_t n;
cf_uint_t i;
cf_byte_t str[4];
struct {
cf_vptr_t car;
cf_vptr_t cdr;
};
};
};
cf_double_t ln;
cf_lint_t li;
};
};
// co_bean_t bean;
// struct cf_bean_t {
// union {
// struct {
// union {
// cf_byte_t tag;
// cf_value_t car;
// struct {
// cf_vptr_t _;
// cf_vptr_t vptr;
// }
// };
// union {
// cf_byte_t b;
// cf_number_t n;
// cf_value_t cdr;
// };
// };
// // cf_string_t str;
// cf_bean_t *bn;
// cf_ptr_t ptr;
// cf_cfunc_t fn;
// cf_double_t ln;
// };
// // union {
// // cf_byte_t tag;
// // struct {
// // cf_value_t car;
// // cf_value_t cdr;
// // };
// // cf_number_t n;
// // cf_string_t str;
// // cf_ptr_t ptr;
// // cf_cfunc_t fn;
// // cf_double_t ln;
// // };
// // union {
// // struct {
// // union {
// // cf_value_t tag;
// // cf_value_t car;
// // };
// // cf_value_t cdr;
// // };
// // cf_cfunc_t fn;
// // cf_ptr_t ptr;
// // cf_double_t n;
// // cf_string_t str;
// // };
// };
// struct cf_bean_t {
// cf_byte_t header; // 1bit mark + 7bit type
// cf_byte_t s[3];
// // union {
// // cf_byte_t b;
// // cf_number_t n;
// // cf_string_t str;
// // cf_ptr_t ptr;
// // cf_cfunc_t fn;
// // struct {
// // cf_bean_t *car;
// // cf_bean_t *cdr;
// // };
// // };
// union {
// struct {
// cf_value_t car;
// cf_value_t cdr;
// };
// cf_ptr_t ptr;
// cf_cfunc_t fn;
// cf_double_t n;
// cf_string_t str;
// // void **pptr;
// // cf_byte_t data[8];
// // cf_short_t d[4];
// // cf_lint_t ptr;
// // void* ptr;
// };
// // cf_bean_t *next;
// };
typedef enum {
CF_TFREE = 0,
CF_TNULL, CF_TTRUE,
CF_TNUMBER, CF_TSTRING,
CF_TPAIR, CF_TTABLE,
CF_TFUNC, CF_TCFUNC,
CF_TPTR,
CF_TSYMBOL,
CF_TMAX
} CF_TYPE;
struct cf_HashTable {
cf_bean_t *nodes[10];
};
struct Coffee {
cf_bean_t *sNull;
cf_bean_t *sTrue;
unsigned int sp; // stack pointer
unsigned int hp; // heap pointer
unsigned int fp;
// cf_bean_t stack[STACK_MAX];
union {
cf_short_t *stack;
cf_bean_t *memory;
};
int mem_size;
// cf_bean_t *first;
// cf_bean_t *gc;
cf_bean_t *symbol_list;
// cf_bean_t *sym_table[10];
// symbols
// cf_byte_t *code;
};
// cf_bean_t sNull;
// cf_bean_t sTrue;
#if defined(__cplusplus)
extern "C" {
#endif
#define tonumber(bean) (bean)->n
#define tostring(bean) (bean)->str
#define tobool(bean)
#define tocfunc(vm, b) (cf_cdr(vm, b)->fn);
// Coffee* co_init(void *ptr, int size);
// int cof_deinit(Coffee *vm);
// cfe_mark(Coffee *vm, co_bean_t *bean);
// int co_sweep(Coffee *vm);
//
CF_API Coffee* cf_init(void *ptr, int size);
CF_API void cf_deinit(Coffee *vm);
CF_API void cf_mark(Coffee *vm, cf_bean_t *bean);
CF_API void cf_sweep(Coffee *vm);
CF_API void cf_gc(Coffee *vm);
CF_API void cf_error(Coffee *vm, const cf_string_t error);
CF_API cf_bean_t* cf_status(Coffee *vm);
CF_API int cf_top(Coffee *vm);
CF_API void cf_settop(Coffee *vm, int index);
CF_API cf_bean_t* cf_call(Coffee *vm, int args);
CF_API cf_bean_t* cf_set(Coffee *vm);
CF_API cf_bean_t* cf_get(Coffee *vm, int index);
#define cf_getnumber(vm, index) tonumber(cf_get((vm), (index)))
CF_API void cf_push(Coffee *vm, cf_bean_t *bean);
#define cf_pushnumber(vm, n) cf_push((vm), cf_number((vm), (n)))
#define cf_pushstring(vm, str) cf_push((vm), cf_string((vm), (str)))
#define cf_pushsymbol(vm, str) cf_push((vm), cf_symbol((vm), (str)))
#define cf_pushbool(vm, b) cf_push((vm), cf_bool((vm), (b)))
#define cf_pushcfunc(vm, cfn) cf_push((vm), cf_cfunc((vm), (cfn)))
#define cf_pushptr(vm, ptr) cf_push((vm), cf_ptr((vm), (ptr)))
#define cf_pushnull(vm) cf_push((vm), cf_null((vm)))
CF_API cf_bean_t* cf_pop(Coffee *vm);
#define cf_popnumber(vm) tonumber(cf_pop((vm)))
// pop a value from the stack and set as a global variable
CF_API cf_bean_t* cf_setglobal(Coffee *vm, const cf_string_t name);
// Check for a free object or malloc new
// Threw an error if is out of memory (hp < sp)
CF_API cf_bean_t* cf_create(Coffee *vm);
// Alloc a new object at heap (hp++)
CF_API cf_bean_t* cf_malloc(Coffee *vm);
// return the global null object
CF_API cf_bean_t* cf_null(Coffee *vm);
// return the global true object
CF_API cf_bean_t* cf_true(Coffee *vm);
// return a new number
CF_API cf_bean_t* cf_number(Coffee *vm, cf_number_t n);
// return a new string
CF_API cf_bean_t* cf_string(Coffee *vm, cf_string_t str);
// return global true or null
CF_API cf_bean_t* cf_bool(Coffee *vm, cf_bool_t b);
// return a new pair or 'a' and 'b'
CF_API cf_bean_t* cf_pair(Coffee *vm, cf_bean_t *a, cf_bean_t *b);
#define cf_cons(vm, a, b) cf_pair(vm, a, b)
// return a new table
CF_API cf_bean_t* cf_table(Coffee *vm, int sz);
CF_API cf_bean_t* cf_list(Coffee *vm, int sz);
// return a new cfunc
CF_API cf_bean_t* cf_cfunc(Coffee *vm, cf_cfunc_t fn);
// return a new ptr
CF_API cf_bean_t* cf_ptr(Coffee *vm, cf_ptr_t ptr);
// return a symbol (check in symbol list first)
CF_API cf_bean_t* cf_symbol(Coffee *vm, const cf_string_t str);
// return car (object at b->car position)
CF_API cf_bean_t* cf_car(Coffee *vm, cf_bean_t *b);
// return car (object at b->cdr position)
CF_API cf_bean_t* cf_cdr(Coffee *vm, cf_bean_t *b);
#define cf_tobean(vm, index) cf_optbean((vm), (index), cf_null((vm)))
#define cf_tonumber(vm, index) cf_optnumber((vm), (index), -1)
#define cf_tostring(vm, index) cf_optstring((vm), (index), NULL)
#define cf_tosymbol(vm, index) cf_optsymbol((vm), (index), cf_null((vm)))
#define cf_tobool(vm, index) cf_optbool((vm), (index), -1)
#define cf_tocfunc(vm, index) cf_optcfunc((vm), (index), NULL)
#define cf_toptr(vm, index) cf_optptr((vm), (index), NULL)
CF_API cf_bean_t* cf_optbean(Coffee *vm, int index, cf_bean_t *opt);
CF_API cf_number_t cf_optnumber(Coffee *vm, int index, cf_number_t opt);
CF_API const cf_string_t cf_optstring(Coffee *vm, int index, cf_string_t opt);
CF_API cf_bean_t* cf_optsymbol(Coffee *vm, int index, cf_bean_t *bn);
CF_API cf_bool_t cf_optbool(Coffee *vm, int index, cf_bool_t opt);
CF_API cf_cfunc_t cf_optcfunc(Coffee *vm, int index, cf_cfunc_t opt);
CF_API cf_ptr_t cf_optptr(Coffee *vm, int index, cf_ptr_t opt);
// REPL
CF_API cf_bean_t* cf_read(Coffee *vm, const char *str);
CF_API cf_bean_t* cf_eval(Coffee *vm);
#if defined(__cplusplus)
}
#endif
#endif