-
Notifications
You must be signed in to change notification settings - Fork 0
/
lua.h
277 lines (243 loc) · 8.57 KB
/
lua.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
#ifndef LUA
#define LUA
#include <stdbool.h>
#include <stdint.h>
#include "fix32.h"
#define __DEBUG_PRINT(level, fmt, args...) do {\
char buffer[150]; \
sprintf(buffer, "%s:%d:%s():", __FILE__, __LINE__, __func__); \
fprintf(stderr, level ": %-30s " fmt, buffer, ##args);\
} while (0)
#ifdef DEBUG2
#define DEBUG
#define DEBUG2_PRINT(fmt, args...) __DEBUG_PRINT("DEBUG2", fmt, ##args)
#else
#define DEBUG2_PRINT(...) do{ } while ( false )
#endif
#ifdef DEBUG
#define DEBUG_PRINT(fmt, args...) __DEBUG_PRINT("DEBUG", fmt, ##args)
#else
#define DEBUG_PRINT(...) do{ } while ( false )
#endif
// It is important that NUL=0 -- a bunch of places have
// memset(0) or calloc() and those zeroes are abused to
// ensure the containers are full of T_NULL
// The remaining values don't need to be in any particular order
enum typetag_t {NUL=0, STR=1, TAB=2, FUN=3, NUM=4, BOOL=5} __attribute__ ((__packed__));
_Static_assert(sizeof(enum typetag_t) == 1, "too big");
typedef struct TValue_s {
union {
uint16_t str_idx; // maybe high bit for short/long str?
fix32_t num;
uint16_t table_idx;
uint16_t fun_idx;
};
enum typetag_t tag; // 3 bits used only
} TValue_t;
_Static_assert(sizeof(TValue_t) == 6, "too big"); // 4 for fix32, 1 for enum, 1 for padding?
typedef struct TVRef_s {
uint16_t idx: 13;
enum typetag_t tag: 3;
} TVRef_t;
_Static_assert(sizeof(TVRef_t) == 2, "too big");
typedef struct TVRefSlice_s {
TVRef_t* ref;
uint16_t len;
} TVRefSlice_t;
typedef struct TVSlice_s {
TValue_t* elems;
uint16_t num;
} TVSlice_t;
typedef TValue_t (*Func_t)(TVSlice_t);
typedef struct TFunc_s {
Func_t fun;
#ifdef DEBUG
const char* name;
#endif
uint16_t env_table_idx;
} TFunc_t;
#ifdef DEBUG
_Static_assert(sizeof(TFunc_t) <= 24, "too big"); // (2)8 for pointer on 64bit, 2 for env, 4 for padding
#else
_Static_assert(sizeof(TFunc_t) <= 16, "too big"); // 8 for pointer on 64bit, 2 for env, 4 for padding
#endif
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(TFunc_t) <= 8, "too big"); // 4 for pointer on 32bit, 2 for env, 2 for padding.
#endif
typedef struct KV_s {
TValue_t key;
TValue_t value;
} KV_t;
typedef struct __attribute__((__packed__)) KVSlice_s {
KV_t* kvs;
uint16_t len;
} KVSlice_t;
_Static_assert(sizeof(KVSlice_t) <= 10, "too big");
typedef struct Metamethod_s {
TValue_t __index;
TValue_t __add;
TValue_t __mul;
TValue_t __sub;
TValue_t __div;
TValue_t __unm;
TValue_t __pow;
TValue_t __concat;
} Metamethod_t;
typedef struct Table_s {
Metamethod_t* mm;
KVSlice_t kvp;
uint16_t metatable_idx;
uint16_t count; // used for "# of valid key-value pairs", where kvp->len is "key-value capacity"
uint8_t refcount;
} Table_t;
// 8 on TValue_t __index (8 on 32bit)
// 16 on kvs (8 on 32bit)
// 5 on count/refcount/metatable_idx
// 3 on padding
_Static_assert(sizeof(Table_t) <= 24, "too big");
#if UINTPTR_MAX == UINT32_MAX
_Static_assert(sizeof(Table_t) <= 16, "too big");
#endif
typedef struct TArena_s {
Table_t* tables;
uint32_t* free_tables;
uint16_t len;
uint16_t used;
} TArena_t;
typedef struct Str_s {
uint8_t* data;
uint16_t len;
uint8_t refcount;
} Str_t;
typedef struct SArena_s {
Str_t* strings;
uint16_t len;
} SArena_t;
typedef struct FArena_s {
TFunc_t* funcs;
uint16_t len;
} FArena_t;
#define TNUM(x) ((TValue_t){.tag = NUM, .num = (x)})
#define TNUM8(x) ((TValue_t){.tag = NUM, .num = (fix32_from_int8(x))})
#define TNUM16(x) ((TValue_t){.tag = NUM, .num = (fix32_from_int16(x))})
#define TSTR(x) ((TValue_t){.tag = STR, .str_idx = (make_str(x))})
#define TSTRi(i) ((TValue_t){.tag = STR, .str_idx = (i)})
#define CONSTSTR(x) ((Str_t){.data = (uint8_t*)(x), .len=(sizeof((x))-1), .refcount=1})
// CONSTSTR has .refcount=1 because it must operate on `const char*`
#define TBOOL(x) ((TValue_t){.tag = BOOL, .num = (fix32_from_int8(x))})
#ifdef DEBUG
#define TFUN(x) ((TValue_t){.tag = FUN, .fun_idx = (make_fun(x, UINT16_MAX, #x))})
#define TCLOSURE(x,y) ((TValue_t){.tag = FUN, .fun_idx = (make_fun(x, (y).table_idx, #x))})
#else
#define TFUN(x) ((TValue_t){.tag = FUN, .fun_idx = (make_fun(x, UINT16_MAX))})
#define TCLOSURE(x,y) ((TValue_t){.tag = FUN, .fun_idx = (make_fun(x, (y).table_idx))})
#endif
#define TTAB(x) ((TValue_t){.tag = TAB, .table_idx = x})
#define CALL(x, y) _Generic(x, TValue_t: __call, Func_t: __direct_call)((x), (y))
#define _bool(x) _Generic((x), TValue_t: __bool, bool: __mbool)(x)
// Declaring this as a `const TValue_t` still raises warnings
// the warnings are solved by making the enum const (wtf?)
// but that raises other warnings
#define T_NULL ((TValue_t){.tag = NUL})
static const fix32_t _zero = {.i=0, .f=0};
static const fix32_t _one = {.i=1, .f=0};
static const TValue_t T_TRUE = {.tag = BOOL, .num = {.i=1, .f=0}};
static const TValue_t T_FALSE = {.tag = BOOL, .num = {.i=0, .f=0}};
static const Str_t STR__INDEX = CONSTSTR("__index");
static const Str_t STR__ADD = CONSTSTR("__add");
static const Str_t STR__SUB = CONSTSTR("__sub");
#define gc __attribute__((__cleanup__(__decref)))
#define printh print_tvalue
// grep -P '^\w+.*{$' lua.c | sed 's/\s\+{/;/'
TValue_t __direct_call(Func_t f, TVSlice_t args);
TValue_t __call(TValue_t t, TVSlice_t args);
TValue_t printh_lambda(TVSlice_t);
void print_bool(bool b);
void print_str(char* c);
TValue_t print_tvalue(TValue_t v);
void print_tvalue_ptr(TValue_t* v);
bool _streq(Str_t a, Str_t b);
bool equal(TValue_t a, TValue_t b);
TValue_t _equal(TValue_t a, TValue_t b);
void grow_table(uint16_t idx);
void set_tabvalue(TValue_t t, TValue_t key, TValue_t v);
TValue_t get_tabvalue(TValue_t u, TValue_t key);
TValue_t del_tabvalue(TValue_t u, TValue_t key);
TValue_t _mult(TValue_t a, TValue_t b);
TValue_t _add(TValue_t a, TValue_t b);
TValue_t _sub(TValue_t a, TValue_t b);
TValue_t _floor_div(TValue_t a, TValue_t b);
TValue_t _div(TValue_t a, TValue_t b);
TValue_t _sqrt(TValue_t a);
TValue_t _pow(TValue_t a, TValue_t b);
TValue_t _ceil(TValue_t a);
void _pluseq(TValue_t* a, TValue_t b);
void _muleq(TValue_t* a, TValue_t b);
void _minuseq(TValue_t* a, TValue_t b);
void _diveq(TValue_t* a, TValue_t b);
void _modeq(TValue_t* a, TValue_t b);
TValue_t _geq(TValue_t a, TValue_t b);
TValue_t _gt(TValue_t a, TValue_t b);
TValue_t _leq(TValue_t a, TValue_t b);
TValue_t _lt(TValue_t a, TValue_t b);
TValue_t _invert_sign(TValue_t a);
TValue_t _notequal(TValue_t a, TValue_t b);
TValue_t _not(TValue_t a);
TValue_t _mod(TValue_t a, TValue_t b);
bool __mbool(bool b);
bool __bool(TValue_t a);
TValue_t _or(TValue_t a, TValue_t b);
TValue_t _and(TValue_t a, TValue_t b);
uint16_t make_table(uint16_t size);
void free_tvalue(TValue_t tv);
TValue_t flr(TValue_t f);
TValue_t getmetatable(TValue_t t);
void setmetatable(TValue_t t, TValue_t meta);
void iadd_tab(TValue_t t, TValue_t key, TValue_t v);
void isub_tab(TValue_t t, TValue_t key, TValue_t v);
void imul_tab(TValue_t t, TValue_t key, TValue_t v);
void idiv_tab(TValue_t t, TValue_t key, TValue_t v);
uint16_t _find_str_index(Str_t s);
uint16_t _store_str(Str_t s);
uint16_t _store_str_at_or_die(Str_t s, uint16_t idx);
void _grow_strings_to(uint16_t new_len);
uint16_t make_str(char* c);
#ifdef DEBUG
uint16_t make_fun(Func_t f, uint16_t env_table_idx, const char* name);
#else
uint16_t make_fun(Func_t f, uint16_t env_table_idx);
#endif
void run_gc();
void _str_decref(Str_t* s);
void _tab_decref(Table_t* t, uint16_t cur_idx);
void _decref(TValue_t v);
void __decref(TValue_t* v);
void _incref(TValue_t v);
void _set(TValue_t* dst, TValue_t src);
void _mark_for_gc(TValue_t val);
void add_to_gc(uint16_t idx, enum typetag_t tag);
TValue_t _concat(TValue_t a, TValue_t b);
TValue_t __internal_debug_str_len();
TValue_t __internal_debug_str_used();
TValue_t __internal_debug_tables_used();
TValue_t tostring(TValue_t v);
void __internal_debug_assert_eq(TValue_t got, TValue_t expected);
TValue_t __get_array_index_capped(TVSlice_t arr, uint8_t idx);
int16_t __get_int(TVSlice_t args, uint8_t idx);
int16_t __opt_int(TVSlice_t args, uint8_t idx, int16_t _default);
bool __get_bool(TVSlice_t args, uint8_t idx);
bool __opt_bool(TVSlice_t args, uint8_t idx, bool _default);
fix32_t __get_num(TVSlice_t args, uint8_t idx);
fix32_t __opt_num(TVSlice_t args, uint8_t idx, fix32_t _default);
Str_t* __get_str(TVSlice_t args, uint8_t idx);
Table_t* __get_tab(TVSlice_t args, uint8_t idx);
TValue_t __opt_value(TVSlice_t args, uint8_t idx, TValue_t _default);
TValue_t type(TValue_t arg);
TValue_t sub(TVSlice_t args);
TValue_t _length(TValue_t arg);
Str_t* GETSTRP(TValue_t x);
Str_t GETSTR(TValue_t x);
Table_t* GETTAB(TValue_t x);
TFunc_t* GETTFUN(TValue_t x);
Table_t GETMETATAB(Table_t x);
#endif