diff options
Diffstat (limited to 'src/bytecode/compiler.h')
-rwxr-xr-x | src/bytecode/compiler.h | 144 |
1 files changed, 72 insertions, 72 deletions
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index 27c5ead..d7d7920 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h | |||
@@ -4,31 +4,31 @@ | |||
4 | #include "chunk.h" | 4 | #include "chunk.h" |
5 | #include "lexer.h" | 5 | #include "lexer.h" |
6 | 6 | ||
7 | typedef struct Visitor { | 7 | typedef struct Compiler { |
8 | Token *tokens; | 8 | Token *tokens; |
9 | size_t current; | 9 | size_t current; |
10 | } Visitor; | 10 | } Compiler; |
11 | 11 | ||
12 | // Mimics the functionality in the Scanner functions, but for entire tokens. | 12 | // Mimics the functionality in the Scanner functions, but for entire tokens. |
13 | Token next_token(Visitor *visitor); | 13 | Token next_token(Compiler *compiler); |
14 | Token peek_token(const Visitor *visitor); | 14 | Token peek_token(const Compiler *compiler); |
15 | bool has_next_token(const Visitor *visitor); | 15 | bool has_next_token(const Compiler *compiler); |
16 | 16 | ||
17 | Chunk * compile(Token *tokens); | 17 | Chunk * compile(Token *tokens); |
18 | 18 | ||
19 | Token | 19 | Token |
20 | peek_token(const Visitor *visitor) { | 20 | peek_token(const Compiler *compiler) { |
21 | return visitor->tokens[visitor->current]; | 21 | return compiler->tokens[compiler->current]; |
22 | } | 22 | } |
23 | 23 | ||
24 | Token | 24 | Token |
25 | next_token(Visitor *visitor) { | 25 | next_token(Compiler *compiler) { |
26 | return visitor->tokens[visitor->current++]; | 26 | return compiler->tokens[compiler->current++]; |
27 | } | 27 | } |
28 | 28 | ||
29 | bool | 29 | bool |
30 | has_next_token(const Visitor *visitor) { | 30 | has_next_token(const Compiler *compiler) { |
31 | return visitor->current < array_size(visitor->tokens); | 31 | return compiler->current < array_size(compiler->tokens); |
32 | } | 32 | } |
33 | 33 | ||
34 | void | 34 | void |
@@ -76,13 +76,13 @@ parse_fixnum(Chunk *chunk, Token tok) { | |||
76 | emit_constant(chunk, tok, FIXNUM_VAL(num * sign)); | 76 | emit_constant(chunk, tok, FIXNUM_VAL(num * sign)); |
77 | } | 77 | } |
78 | 78 | ||
79 | void parse_tree(Chunk *chunk, Visitor *vs); | 79 | void parse_tree(Chunk *chunk, Compiler *compiler); |
80 | 80 | ||
81 | void | 81 | void |
82 | compile_list_binary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | 82 | compile_list_binary_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) { |
83 | size_t n = 0; | 83 | size_t n = 0; |
84 | while (has_next_token(vs)) { | 84 | while (has_next_token(compiler)) { |
85 | Token tok = peek_token(vs); | 85 | Token tok = peek_token(compiler); |
86 | if (tok.type == TOKEN_EOF) { | 86 | if (tok.type == TOKEN_EOF) { |
87 | error_push((Error){ | 87 | error_push((Error){ |
88 | .type = ERR_TYPE_COMPILER, | 88 | .type = ERR_TYPE_COMPILER, |
@@ -93,7 +93,7 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
93 | return; | 93 | return; |
94 | } | 94 | } |
95 | if (tok.type == TOKEN_RPAREN) { | 95 | if (tok.type == TOKEN_RPAREN) { |
96 | next_token(vs); | 96 | next_token(compiler); |
97 | if (n <= 1) { | 97 | if (n <= 1) { |
98 | error_push((Error){ | 98 | error_push((Error){ |
99 | .type = ERR_TYPE_COMPILER, | 99 | .type = ERR_TYPE_COMPILER, |
@@ -105,7 +105,7 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
105 | } | 105 | } |
106 | break; | 106 | break; |
107 | } | 107 | } |
108 | parse_tree(chunk, vs); | 108 | parse_tree(chunk, compiler); |
109 | if (tok.type == TOKEN_SYMBOL) { | 109 | if (tok.type == TOKEN_SYMBOL) { |
110 | add_code(chunk, OP_GET, tok.line, tok.column); | 110 | add_code(chunk, OP_GET, tok.line, tok.column); |
111 | } | 111 | } |
@@ -116,10 +116,10 @@ compile_list_binary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
116 | } | 116 | } |
117 | 117 | ||
118 | void | 118 | void |
119 | compile_list_unary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | 119 | compile_list_unary_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) { |
120 | size_t n = 0; | 120 | size_t n = 0; |
121 | while (has_next_token(vs)) { | 121 | while (has_next_token(compiler)) { |
122 | Token tok = peek_token(vs); | 122 | Token tok = peek_token(compiler); |
123 | if (tok.type == TOKEN_EOF) { | 123 | if (tok.type == TOKEN_EOF) { |
124 | error_push((Error){ | 124 | error_push((Error){ |
125 | .type = ERR_TYPE_COMPILER, | 125 | .type = ERR_TYPE_COMPILER, |
@@ -130,7 +130,7 @@ compile_list_unary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
130 | return; | 130 | return; |
131 | } | 131 | } |
132 | if (tok.type == TOKEN_RPAREN) { | 132 | if (tok.type == TOKEN_RPAREN) { |
133 | next_token(vs); | 133 | next_token(compiler); |
134 | if (n == 0) { | 134 | if (n == 0) { |
135 | error_push((Error){ | 135 | error_push((Error){ |
136 | .type = ERR_TYPE_COMPILER, | 136 | .type = ERR_TYPE_COMPILER, |
@@ -141,7 +141,7 @@ compile_list_unary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
141 | } | 141 | } |
142 | return; | 142 | return; |
143 | } | 143 | } |
144 | parse_tree(chunk, vs); | 144 | parse_tree(chunk, compiler); |
145 | if (tok.type == TOKEN_SYMBOL) { | 145 | if (tok.type == TOKEN_SYMBOL) { |
146 | add_code(chunk, OP_GET, tok.line, tok.column); | 146 | add_code(chunk, OP_GET, tok.line, tok.column); |
147 | } | 147 | } |
@@ -165,9 +165,9 @@ compile_list_unary_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
165 | } | 165 | } |
166 | 166 | ||
167 | void | 167 | void |
168 | compile_list_simple_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | 168 | compile_list_simple_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) { |
169 | if (has_next_token(vs)) { | 169 | if (has_next_token(compiler)) { |
170 | Token tok = peek_token(vs); | 170 | Token tok = peek_token(compiler); |
171 | if (tok.type == TOKEN_EOF) { | 171 | if (tok.type == TOKEN_EOF) { |
172 | error_push((Error){ | 172 | error_push((Error){ |
173 | .type = ERR_TYPE_COMPILER, | 173 | .type = ERR_TYPE_COMPILER, |
@@ -186,7 +186,7 @@ compile_list_simple_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
186 | }); | 186 | }); |
187 | return; | 187 | return; |
188 | } | 188 | } |
189 | next_token(vs); | 189 | next_token(compiler); |
190 | add_code(chunk, op, start.line, start.column); | 190 | add_code(chunk, op, start.line, start.column); |
191 | return; | 191 | return; |
192 | } | 192 | } |
@@ -199,8 +199,8 @@ compile_list_simple_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
199 | } | 199 | } |
200 | 200 | ||
201 | void | 201 | void |
202 | compile_declare_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | 202 | compile_declare_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) { |
203 | Token name = peek_token(vs); | 203 | Token name = peek_token(compiler); |
204 | if (name.type != TOKEN_SYMBOL) { | 204 | if (name.type != TOKEN_SYMBOL) { |
205 | error_push((Error){ | 205 | error_push((Error){ |
206 | .type = ERR_TYPE_COMPILER, | 206 | .type = ERR_TYPE_COMPILER, |
@@ -210,8 +210,8 @@ compile_declare_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
210 | }); | 210 | }); |
211 | return; | 211 | return; |
212 | } | 212 | } |
213 | parse_tree(chunk, vs); | 213 | parse_tree(chunk, compiler); |
214 | Token expr = peek_token(vs); | 214 | Token expr = peek_token(compiler); |
215 | if (name.type == TOKEN_EOF || expr.type == TOKEN_EOF) { | 215 | if (name.type == TOKEN_EOF || expr.type == TOKEN_EOF) { |
216 | error_push((Error){ | 216 | error_push((Error){ |
217 | .type = ERR_TYPE_COMPILER, | 217 | .type = ERR_TYPE_COMPILER, |
@@ -230,11 +230,11 @@ compile_declare_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
230 | }); | 230 | }); |
231 | return; | 231 | return; |
232 | } | 232 | } |
233 | parse_tree(chunk, vs); | 233 | parse_tree(chunk, compiler); |
234 | if (expr.type == TOKEN_SYMBOL) { | 234 | if (expr.type == TOKEN_SYMBOL) { |
235 | add_code(chunk, OP_GET, expr.line, expr.column); | 235 | add_code(chunk, OP_GET, expr.line, expr.column); |
236 | } | 236 | } |
237 | if (peek_token(vs).type != TOKEN_RPAREN) { | 237 | if (peek_token(compiler).type != TOKEN_RPAREN) { |
238 | error_push((Error){ | 238 | error_push((Error){ |
239 | .type = ERR_TYPE_COMPILER, | 239 | .type = ERR_TYPE_COMPILER, |
240 | .value = ERR_TOO_MANY_ARGS, | 240 | .value = ERR_TOO_MANY_ARGS, |
@@ -243,13 +243,13 @@ compile_declare_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
243 | }); | 243 | }); |
244 | return; | 244 | return; |
245 | } | 245 | } |
246 | next_token(vs); | 246 | next_token(compiler); |
247 | add_code(chunk, op, start.line, start.column); | 247 | add_code(chunk, op, start.line, start.column); |
248 | } | 248 | } |
249 | 249 | ||
250 | void | 250 | void |
251 | compile_if_op(Chunk *chunk, Visitor *vs, Token start) { | 251 | compile_if_op(Chunk *chunk, Compiler *compiler, Token start) { |
252 | Token tok = peek_token(vs); | 252 | Token tok = peek_token(compiler); |
253 | if (tok.type == TOKEN_EOF) { | 253 | if (tok.type == TOKEN_EOF) { |
254 | error_push((Error){ | 254 | error_push((Error){ |
255 | .type = ERR_TYPE_COMPILER, | 255 | .type = ERR_TYPE_COMPILER, |
@@ -270,26 +270,26 @@ compile_if_op(Chunk *chunk, Visitor *vs, Token start) { | |||
270 | } | 270 | } |
271 | 271 | ||
272 | // Condition. | 272 | // Condition. |
273 | parse_tree(chunk, vs); | 273 | parse_tree(chunk, compiler); |
274 | size_t jmp_false = emit_jump(chunk, start, OP_JUMP_IF_FALSE, 0xFFFF); | 274 | size_t jmp_false = emit_jump(chunk, start, OP_JUMP_IF_FALSE, 0xFFFF); |
275 | 275 | ||
276 | // True expression. | 276 | // True expression. |
277 | parse_tree(chunk, vs); | 277 | parse_tree(chunk, compiler); |
278 | 278 | ||
279 | // No second expression. | 279 | // No second expression. |
280 | if (peek_token(vs).type == TOKEN_RPAREN) { | 280 | if (peek_token(compiler).type == TOKEN_RPAREN) { |
281 | patch_jump(chunk, jmp_false); | 281 | patch_jump(chunk, jmp_false); |
282 | next_token(vs); | 282 | next_token(compiler); |
283 | return; | 283 | return; |
284 | } | 284 | } |
285 | 285 | ||
286 | // False expression. | 286 | // False expression. |
287 | size_t jmp_end = emit_jump(chunk, start, OP_JUMP, 0xFFFF); | 287 | size_t jmp_end = emit_jump(chunk, start, OP_JUMP, 0xFFFF); |
288 | patch_jump(chunk, jmp_false); | 288 | patch_jump(chunk, jmp_false); |
289 | parse_tree(chunk, vs); | 289 | parse_tree(chunk, compiler); |
290 | patch_jump(chunk, jmp_end); | 290 | patch_jump(chunk, jmp_end); |
291 | 291 | ||
292 | if (peek_token(vs).type != TOKEN_RPAREN) { | 292 | if (peek_token(compiler).type != TOKEN_RPAREN) { |
293 | error_push((Error){ | 293 | error_push((Error){ |
294 | .type = ERR_TYPE_COMPILER, | 294 | .type = ERR_TYPE_COMPILER, |
295 | .value = ERR_TOO_MANY_ARGS, | 295 | .value = ERR_TOO_MANY_ARGS, |
@@ -298,12 +298,12 @@ compile_if_op(Chunk *chunk, Visitor *vs, Token start) { | |||
298 | }); | 298 | }); |
299 | return; | 299 | return; |
300 | } | 300 | } |
301 | next_token(vs); | 301 | next_token(compiler); |
302 | } | 302 | } |
303 | 303 | ||
304 | void | 304 | void |
305 | parse_list(Chunk *chunk, Visitor *vs, Token start) { | 305 | parse_list(Chunk *chunk, Compiler *compiler, Token start) { |
306 | if (!has_next_token(vs)) { | 306 | if (!has_next_token(compiler)) { |
307 | error_push((Error){ | 307 | error_push((Error){ |
308 | .type = ERR_TYPE_COMPILER, | 308 | .type = ERR_TYPE_COMPILER, |
309 | .value = ERR_UNBALANCED_PAREN, | 309 | .value = ERR_UNBALANCED_PAREN, |
@@ -312,27 +312,27 @@ parse_list(Chunk *chunk, Visitor *vs, Token start) { | |||
312 | }); | 312 | }); |
313 | return; | 313 | return; |
314 | } | 314 | } |
315 | Token tok = next_token(vs); | 315 | Token tok = next_token(compiler); |
316 | switch (tok.type) { | 316 | switch (tok.type) { |
317 | case TOKEN_ADD: { compile_list_binary_op(chunk, vs, start, OP_SUM); } break; | 317 | case TOKEN_ADD: { compile_list_binary_op(chunk, compiler, start, OP_SUM); } break; |
318 | case TOKEN_SUB: { compile_list_binary_op(chunk, vs, start, OP_SUB); } break; | 318 | case TOKEN_SUB: { compile_list_binary_op(chunk, compiler, start, OP_SUB); } break; |
319 | case TOKEN_MUL: { compile_list_binary_op(chunk, vs, start, OP_MUL); } break; | 319 | case TOKEN_MUL: { compile_list_binary_op(chunk, compiler, start, OP_MUL); } break; |
320 | case TOKEN_DIV: { compile_list_binary_op(chunk, vs, start, OP_DIV); } break; | 320 | case TOKEN_DIV: { compile_list_binary_op(chunk, compiler, start, OP_DIV); } break; |
321 | case TOKEN_MOD: { compile_list_binary_op(chunk, vs, start, OP_MOD); } break; | 321 | case TOKEN_MOD: { compile_list_binary_op(chunk, compiler, start, OP_MOD); } break; |
322 | case TOKEN_NOT: { compile_list_unary_op(chunk, vs, start, OP_NOT); } break; | 322 | case TOKEN_NOT: { compile_list_unary_op(chunk, compiler, start, OP_NOT); } break; |
323 | case TOKEN_AND: { compile_list_binary_op(chunk, vs, start, OP_AND); } break; | 323 | case TOKEN_AND: { compile_list_binary_op(chunk, compiler, start, OP_AND); } break; |
324 | case TOKEN_OR: { compile_list_binary_op(chunk, vs, start, OP_OR); } break; | 324 | case TOKEN_OR: { compile_list_binary_op(chunk, compiler, start, OP_OR); } break; |
325 | case TOKEN_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_EQUAL); } break; | 325 | case TOKEN_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_EQUAL); } break; |
326 | case TOKEN_LESS: { compile_list_binary_op(chunk, vs, start, OP_LESS); } break; | 326 | case TOKEN_LESS: { compile_list_binary_op(chunk, compiler, start, OP_LESS); } break; |
327 | case TOKEN_GREATER: { compile_list_binary_op(chunk, vs, start, OP_GREATER); } break; | 327 | case TOKEN_GREATER: { compile_list_binary_op(chunk, compiler, start, OP_GREATER); } break; |
328 | case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_LESS_EQUAL); } break; | 328 | case TOKEN_LESS_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_LESS_EQUAL); } break; |
329 | case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, vs, start, OP_GREATER_EQUAL); } break; | 329 | case TOKEN_GREATER_EQUAL: { compile_list_binary_op(chunk, compiler, start, OP_GREATER_EQUAL); } break; |
330 | case TOKEN_PRINT: { compile_list_unary_op(chunk, vs, start, OP_PRINT); } break; | 330 | case TOKEN_PRINT: { compile_list_unary_op(chunk, compiler, start, OP_PRINT); } break; |
331 | case TOKEN_DISPLAY: { compile_list_unary_op(chunk, vs, start, OP_DISPLAY); } break; | 331 | case TOKEN_DISPLAY: { compile_list_unary_op(chunk, compiler, start, OP_DISPLAY); } break; |
332 | case TOKEN_NEWLINE: { compile_list_simple_op(chunk, vs, start, OP_NEWLINE); } break; | 332 | case TOKEN_NEWLINE: { compile_list_simple_op(chunk, compiler, start, OP_NEWLINE); } break; |
333 | case TOKEN_DEF: { compile_declare_op(chunk, vs, start, OP_DEF); } break; | 333 | case TOKEN_DEF: { compile_declare_op(chunk, compiler, start, OP_DEF); } break; |
334 | case TOKEN_SET: { compile_declare_op(chunk, vs, start, OP_SET); } break; | 334 | case TOKEN_SET: { compile_declare_op(chunk, compiler, start, OP_SET); } break; |
335 | case TOKEN_IF: { compile_if_op(chunk, vs, start); } break; | 335 | case TOKEN_IF: { compile_if_op(chunk, compiler, start); } break; |
336 | default: { | 336 | default: { |
337 | error_push((Error){ | 337 | error_push((Error){ |
338 | .type = ERR_TYPE_COMPILER, | 338 | .type = ERR_TYPE_COMPILER, |
@@ -345,8 +345,8 @@ parse_list(Chunk *chunk, Visitor *vs, Token start) { | |||
345 | } | 345 | } |
346 | 346 | ||
347 | void | 347 | void |
348 | parse_tree(Chunk *chunk, Visitor *vs) { | 348 | parse_tree(Chunk *chunk, Compiler *compiler) { |
349 | Token tok = next_token(vs); | 349 | Token tok = next_token(compiler); |
350 | if (errors_n != 0) { | 350 | if (errors_n != 0) { |
351 | return; | 351 | return; |
352 | } | 352 | } |
@@ -376,7 +376,7 @@ parse_tree(Chunk *chunk, Visitor *vs) { | |||
376 | // Object *base = make_pair(obj_quote, obj_nil); | 376 | // Object *base = make_pair(obj_quote, obj_nil); |
377 | // base->cdr = make_pair(obj_nil, obj_nil); | 377 | // base->cdr = make_pair(obj_nil, obj_nil); |
378 | // push_root(base); | 378 | // push_root(base); |
379 | // Object *next_obj = parse_tree(vs); | 379 | // Object *next_obj = parse_tree(compiler); |
380 | // if (next_obj == obj_err) { | 380 | // if (next_obj == obj_err) { |
381 | // return obj_err; | 381 | // return obj_err; |
382 | // } | 382 | // } |
@@ -385,7 +385,7 @@ parse_tree(Chunk *chunk, Visitor *vs) { | |||
385 | return; | 385 | return; |
386 | } break; | 386 | } break; |
387 | case TOKEN_LPAREN: { | 387 | case TOKEN_LPAREN: { |
388 | parse_list(chunk, vs, tok); | 388 | parse_list(chunk, compiler, tok); |
389 | return; | 389 | return; |
390 | } break; | 390 | } break; |
391 | case TOKEN_STRING: { | 391 | case TOKEN_STRING: { |
@@ -419,13 +419,13 @@ Chunk * | |||
419 | compile(Token *tokens) { | 419 | compile(Token *tokens) { |
420 | Chunk *chunk = NULL; | 420 | Chunk *chunk = NULL; |
421 | chunk = chunk_init(); | 421 | chunk = chunk_init(); |
422 | Visitor visitor = (Visitor){ | 422 | Compiler compiler = (Compiler){ |
423 | .tokens = tokens, | 423 | .tokens = tokens, |
424 | .current = 0, | 424 | .current = 0, |
425 | }; | 425 | }; |
426 | Token start_tok = peek_token(&visitor); | 426 | Token start_tok = peek_token(&compiler); |
427 | while (has_next_token(&visitor) && peek_token(&visitor).type != TOKEN_EOF) { | 427 | while (has_next_token(&compiler) && peek_token(&compiler).type != TOKEN_EOF) { |
428 | parse_tree(chunk, &visitor); | 428 | parse_tree(chunk, &compiler); |
429 | } | 429 | } |
430 | add_code(chunk, OP_RETURN, start_tok.line, start_tok.column); | 430 | add_code(chunk, OP_RETURN, start_tok.line, start_tok.column); |
431 | return chunk; | 431 | return chunk; |