blob: 596e04eb822ea0a5e403dcd21ae447e940d84bfa [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <unistd.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <string.h>
6#include <assert.h>
7
8#include "misc.h"
Damienc025ebb2013-10-12 14:30:21 +01009#include "mpyconfig.h"
Damien429d7192013-10-04 19:53:11 +010010#include "lexer.h"
Damien429d7192013-10-04 19:53:11 +010011#include "parse.h"
12#include "compile.h"
13#include "scope.h"
14#include "runtime.h"
15#include "emit.h"
16
Damienc025ebb2013-10-12 14:30:21 +010017#ifdef MICROPY_EMIT_ENABLE_CPYTHON
Damien429d7192013-10-04 19:53:11 +010018
Damien415eb6f2013-10-05 12:19:06 +010019struct _emit_t {
Damien429d7192013-10-04 19:53:11 +010020 int pass;
Damien429d7192013-10-04 19:53:11 +010021 int byte_code_offset;
22 int stack_size;
23 bool last_emit_was_return_value;
24
25 scope_t *scope;
26
Damienb05d7072013-10-05 13:37:10 +010027 uint max_num_labels;
Damien429d7192013-10-04 19:53:11 +010028 int *label_offsets;
29};
30
Damien6cdd3af2013-10-05 18:08:26 +010031// forward declaration
Damien4b03e772013-10-05 14:17:09 +010032static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes);
33
Damien6cdd3af2013-10-05 18:08:26 +010034emit_t *emit_cpython_new(uint max_num_labels) {
35 emit_t *emit = m_new(emit_t, 1);
36 emit->max_num_labels = max_num_labels;
37 emit->label_offsets = m_new(int, max_num_labels);
38 return emit;
39}
40
Damien415eb6f2013-10-05 12:19:06 +010041static void emit_cpy_set_native_types(emit_t *emit, bool do_native_types) {
Damien429d7192013-10-04 19:53:11 +010042}
43
Damien415eb6f2013-10-05 12:19:06 +010044static void emit_cpy_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien429d7192013-10-04 19:53:11 +010045 emit->pass = pass;
Damien429d7192013-10-04 19:53:11 +010046 emit->byte_code_offset = 0;
47 emit->stack_size = 0;
48 emit->last_emit_was_return_value = false;
49 emit->scope = scope;
Damienb05d7072013-10-05 13:37:10 +010050 if (pass == PASS_2) {
51 memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(int));
Damien429d7192013-10-04 19:53:11 +010052 }
53}
54
Damien415eb6f2013-10-05 12:19:06 +010055static void emit_cpy_end_pass(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010056 // check stack is back to zero size
57 if (emit->stack_size != 0) {
58 printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
59 }
Damien429d7192013-10-04 19:53:11 +010060}
61
Damien415eb6f2013-10-05 12:19:06 +010062static bool emit_cpy_last_emit_was_return_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010063 return emit->last_emit_was_return_value;
64}
65
Damien415eb6f2013-10-05 12:19:06 +010066static int emit_cpy_get_stack_size(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010067 return emit->stack_size;
68}
69
Damien415eb6f2013-10-05 12:19:06 +010070static void emit_cpy_set_stack_size(emit_t *emit, int size) {
Damien429d7192013-10-04 19:53:11 +010071 emit->stack_size = size;
72}
73
Damien4b03e772013-10-05 14:17:09 +010074static void emit_cpy_load_id(emit_t *emit, qstr qstr) {
Damien6cdd3af2013-10-05 18:08:26 +010075 emit_common_load_id(emit, &emit_cpython_method_table, emit->scope, qstr);
Damien4b03e772013-10-05 14:17:09 +010076}
77
78static void emit_cpy_store_id(emit_t *emit, qstr qstr) {
Damien6cdd3af2013-10-05 18:08:26 +010079 emit_common_store_id(emit, &emit_cpython_method_table, emit->scope, qstr);
Damien4b03e772013-10-05 14:17:09 +010080}
81
82static void emit_cpy_delete_id(emit_t *emit, qstr qstr) {
Damien6cdd3af2013-10-05 18:08:26 +010083 emit_common_delete_id(emit, &emit_cpython_method_table, emit->scope, qstr);
Damien4b03e772013-10-05 14:17:09 +010084}
85
Damien415eb6f2013-10-05 12:19:06 +010086static void emit_pre(emit_t *emit, int stack_size_delta, int byte_code_size) {
Damien429d7192013-10-04 19:53:11 +010087 emit->stack_size += stack_size_delta;
Damienb05d7072013-10-05 13:37:10 +010088 if (emit->stack_size > emit->scope->stack_size) {
Damien429d7192013-10-04 19:53:11 +010089 emit->scope->stack_size = emit->stack_size;
90 }
91 emit->last_emit_was_return_value = false;
92 if (emit->pass == PASS_3 && byte_code_size > 0) {
93 if (emit->byte_code_offset >= 1000) {
94 printf("%d ", emit->byte_code_offset);
95 } else {
96 printf("% 4d ", emit->byte_code_offset);
97 }
98 }
99 emit->byte_code_offset += byte_code_size;
100}
101
Damien415eb6f2013-10-05 12:19:06 +0100102static void emit_cpy_label_assign(emit_t *emit, int l) {
Damien429d7192013-10-04 19:53:11 +0100103 emit_pre(emit, 0, 0);
Damienb05d7072013-10-05 13:37:10 +0100104 assert(l < emit->max_num_labels);
105 if (emit->pass == PASS_2) {
106 // assign label offset
107 assert(emit->label_offsets[l] == -1);
108 emit->label_offsets[l] = emit->byte_code_offset;
109 } else if (emit->pass == PASS_3) {
110 // ensure label offset has not changed from PASS_2 to PASS_3
111 assert(emit->label_offsets[l] == emit->byte_code_offset);
112 //printf("l%d: (at %d)\n", l, emit->byte_code_offset);
Damien429d7192013-10-04 19:53:11 +0100113 }
114}
115
Damien415eb6f2013-10-05 12:19:06 +0100116static void emit_cpy_import_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100117 emit_pre(emit, -1, 3);
118 if (emit->pass == PASS_3) {
119 printf("IMPORT_NAME %s\n", qstr_str(qstr));
120 }
121}
122
Damien415eb6f2013-10-05 12:19:06 +0100123static void emit_cpy_import_from(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100124 emit_pre(emit, 1, 3);
125 if (emit->pass == PASS_3) {
126 printf("IMPORT_FROM %s\n", qstr_str(qstr));
127 }
128}
129
Damien415eb6f2013-10-05 12:19:06 +0100130static void emit_cpy_import_star(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100131 emit_pre(emit, -1, 1);
132 if (emit->pass == PASS_3) {
133 printf("IMPORT_STAR\n");
134 }
135}
136
Damien415eb6f2013-10-05 12:19:06 +0100137static void emit_cpy_load_const_tok(emit_t *emit, py_token_kind_t tok) {
Damien429d7192013-10-04 19:53:11 +0100138 emit_pre(emit, 1, 3);
139 if (emit->pass == PASS_3) {
140 printf("LOAD_CONST ");
141 switch (tok) {
142 case PY_TOKEN_KW_FALSE: printf("False"); break;
143 case PY_TOKEN_KW_NONE: printf("None"); break;
144 case PY_TOKEN_KW_TRUE: printf("True"); break;
145 default: printf("?=%d\n", tok); return; assert(0);
146 }
147 printf("\n");
148 }
149}
150
Damien415eb6f2013-10-05 12:19:06 +0100151static void emit_cpy_load_const_small_int(emit_t *emit, int arg) {
Damien429d7192013-10-04 19:53:11 +0100152 emit_pre(emit, 1, 3);
153 if (emit->pass == PASS_3) {
154 printf("LOAD_CONST %d\n", arg);
155 }
156}
157
Damien415eb6f2013-10-05 12:19:06 +0100158static void emit_cpy_load_const_int(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100159 emit_pre(emit, 1, 3);
160 if (emit->pass == PASS_3) {
161 printf("LOAD_CONST %s\n", qstr_str(qstr));
162 }
163}
164
Damien415eb6f2013-10-05 12:19:06 +0100165static void emit_cpy_load_const_dec(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100166 emit_pre(emit, 1, 3);
167 if (emit->pass == PASS_3) {
168 printf("LOAD_CONST %s\n", qstr_str(qstr));
169 }
170}
171
Damien415eb6f2013-10-05 12:19:06 +0100172static void emit_cpy_load_const_id(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100173 emit_pre(emit, 1, 3);
174 if (emit->pass == PASS_3) {
175 printf("LOAD_CONST '%s'\n", qstr_str(qstr));
176 }
177}
178
Damien415eb6f2013-10-05 12:19:06 +0100179static void emit_cpy_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien429d7192013-10-04 19:53:11 +0100180 emit_pre(emit, 1, 3);
181 if (emit->pass == PASS_3) {
182 printf("LOAD_CONST ");
Damien415eb6f2013-10-05 12:19:06 +0100183 emit_cpy_load_const_verbatim_quoted_str(emit, qstr, bytes);
Damien429d7192013-10-04 19:53:11 +0100184 printf("\n");
185 }
186}
187
Damien415eb6f2013-10-05 12:19:06 +0100188static void emit_cpy_load_const_verbatim_start(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100189 emit_pre(emit, 1, 3);
190 if (emit->pass == PASS_3) {
191 printf("LOAD_CONST ");
192 }
193}
194
Damien415eb6f2013-10-05 12:19:06 +0100195static void emit_cpy_load_const_verbatim_int(emit_t *emit, int val) {
Damien429d7192013-10-04 19:53:11 +0100196 if (emit->pass == PASS_3) {
197 printf("%d", val);
198 }
199}
200
Damien415eb6f2013-10-05 12:19:06 +0100201static void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) {
Damien429d7192013-10-04 19:53:11 +0100202 if (emit->pass == PASS_3) {
203 printf("%s", str);
204 }
205}
206
Damien415eb6f2013-10-05 12:19:06 +0100207static void emit_cpy_load_const_verbatim_strn(emit_t *emit, const char *str, int len) {
Damien429d7192013-10-04 19:53:11 +0100208 if (emit->pass == PASS_3) {
209 printf("%.*s", len, str);
210 }
211}
212
Damien415eb6f2013-10-05 12:19:06 +0100213static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes) {
Damien429d7192013-10-04 19:53:11 +0100214 // TODO strings should be escaped before we get here
215 if (emit->pass == PASS_3) {
216 const char *str = qstr_str(qstr);
217 int len = strlen(str);
218 bool has_single_quote = false;
219 bool has_double_quote = false;
220 for (int i = 0; i < len; i++) {
221 if (str[i] == '\'') {
222 has_single_quote = true;
223 } else if (str[i] == '"') {
224 has_double_quote = true;
225 }
226 }
227 if (bytes) {
228 printf("b");
229 }
230 bool quote_single = false;
231 if (has_single_quote && !has_double_quote) {
232 printf("\"");
233 } else {
234 quote_single = true;
235 printf("'");
236 }
237 for (int i = 0; i < len; i++) {
238 if (str[i] == '\n') {
239 printf("\\n");
240 } else if (str[i] == '\\' && str[i + 1] == '\'') {
241 i += 1;
242 if (quote_single) {
243 printf("\\'");
244 } else {
245 printf("'");
246 }
247 } else if (str[i] == '\'' && quote_single) {
248 printf("\\'");
249 } else {
250 printf("%c", str[i]);
251 }
252 }
253 if (has_single_quote && !has_double_quote) {
254 printf("\"");
255 } else {
256 printf("'");
257 }
258 }
259}
260
Damien415eb6f2013-10-05 12:19:06 +0100261static void emit_cpy_load_const_verbatim_end(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100262 if (emit->pass == PASS_3) {
263 printf("\n");
264 }
265}
266
Damien6cdd3af2013-10-05 18:08:26 +0100267static void emit_cpy_load_fast(emit_t *emit, qstr qstr, int local_num) {
268 emit_pre(emit, 1, 3);
269 if (emit->pass == PASS_3) {
270 printf("LOAD_FAST %d %s\n", local_num, qstr_str(qstr));
271 }
272}
273
Damien415eb6f2013-10-05 12:19:06 +0100274static void emit_cpy_load_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100275 emit_pre(emit, 1, 3);
276 if (emit->pass == PASS_3) {
277 printf("LOAD_NAME %s\n", qstr_str(qstr));
278 }
279}
280
Damien415eb6f2013-10-05 12:19:06 +0100281static void emit_cpy_load_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100282 emit_pre(emit, 1, 3);
283 if (emit->pass == PASS_3) {
284 printf("LOAD_GLOBAL %s\n", qstr_str(qstr));
285 }
286}
287
Damien415eb6f2013-10-05 12:19:06 +0100288static void emit_cpy_load_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100289 emit_pre(emit, 1, 3);
290 if (emit->pass == PASS_3) {
291 printf("LOAD_DEREF %s\n", qstr_str(qstr));
292 }
293}
294
Damien415eb6f2013-10-05 12:19:06 +0100295static void emit_cpy_load_closure(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100296 emit_pre(emit, 1, 3);
297 if (emit->pass == PASS_3) {
298 printf("LOAD_CLOSURE %s\n", qstr_str(qstr));
299 }
300}
301
Damien415eb6f2013-10-05 12:19:06 +0100302static void emit_cpy_load_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100303 emit_pre(emit, 0, 3);
304 if (emit->pass == PASS_3) {
305 printf("LOAD_ATTR %s\n", qstr_str(qstr));
306 }
307}
308
Damien415eb6f2013-10-05 12:19:06 +0100309static void emit_cpy_load_method(emit_t *emit, qstr qstr) {
310 emit_cpy_load_attr(emit, qstr);
Damien429d7192013-10-04 19:53:11 +0100311}
312
Damien415eb6f2013-10-05 12:19:06 +0100313static void emit_cpy_load_build_class(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100314 emit_pre(emit, 1, 1);
315 if (emit->pass == PASS_3) {
316 printf("LOAD_BUILD_CLASS\n");
317 }
318}
319
Damien6cdd3af2013-10-05 18:08:26 +0100320static void emit_cpy_store_fast(emit_t *emit, qstr qstr, int local_num) {
321 emit_pre(emit, -1, 3);
322 if (emit->pass == PASS_3) {
323 printf("STORE_FAST %d %s\n", local_num, qstr_str(qstr));
324 }
325}
326
Damien415eb6f2013-10-05 12:19:06 +0100327static void emit_cpy_store_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100328 emit_pre(emit, -1, 3);
329 if (emit->pass == PASS_3) {
330 printf("STORE_NAME %s\n", qstr_str(qstr));
331 }
332}
333
Damien415eb6f2013-10-05 12:19:06 +0100334static void emit_cpy_store_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100335 emit_pre(emit, -1, 3);
336 if (emit->pass == PASS_3) {
337 printf("STORE_GLOBAL %s\n", qstr_str(qstr));
338 }
339}
340
Damien415eb6f2013-10-05 12:19:06 +0100341static void emit_cpy_store_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100342 emit_pre(emit, -1, 3);
343 if (emit->pass == PASS_3) {
344 printf("STORE_DEREF %s\n", qstr_str(qstr));
345 }
346}
347
Damien415eb6f2013-10-05 12:19:06 +0100348static void emit_cpy_store_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100349 emit_pre(emit, -2, 3);
350 if (emit->pass == PASS_3) {
351 printf("STORE_ATTR %s\n", qstr_str(qstr));
352 }
353}
354
Damien415eb6f2013-10-05 12:19:06 +0100355static void emit_cpy_store_subscr(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100356 emit_pre(emit, -3, 1);
357 if (emit->pass == PASS_3) {
358 printf("STORE_SUBSCR\n");
359 }
360}
361
Damiena3977762013-10-09 23:10:10 +0100362static void emit_cpy_store_locals(emit_t *emit) {
363 emit_pre(emit, -1, 1);
364 if (emit->pass == PASS_3) {
365 printf("STORE_LOCALS\n");
366 }
367}
368
Damien6cdd3af2013-10-05 18:08:26 +0100369static void emit_cpy_delete_fast(emit_t *emit, qstr qstr, int local_num) {
370 emit_pre(emit, 0, 3);
371 if (emit->pass == PASS_3) {
372 printf("DELETE_FAST %d %s\n", local_num, qstr_str(qstr));
373 }
374}
375
Damien415eb6f2013-10-05 12:19:06 +0100376static void emit_cpy_delete_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100377 emit_pre(emit, 0, 3);
378 if (emit->pass == PASS_3) {
379 printf("DELETE_NAME %s\n", qstr_str(qstr));
380 }
381}
382
Damien415eb6f2013-10-05 12:19:06 +0100383static void emit_cpy_delete_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100384 emit_pre(emit, 0, 3);
385 if (emit->pass == PASS_3) {
386 printf("DELETE_GLOBAL %s\n", qstr_str(qstr));
387 }
388}
389
Damien415eb6f2013-10-05 12:19:06 +0100390static void emit_cpy_delete_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100391 emit_pre(emit, 0, 3);
392 if (emit->pass == PASS_3) {
393 printf("DELETE_DEREF %s\n", qstr_str(qstr));
394 }
395}
396
Damien415eb6f2013-10-05 12:19:06 +0100397static void emit_cpy_delete_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100398 emit_pre(emit, -1, 3);
399 if (emit->pass == PASS_3) {
400 printf("DELETE_ATTR %s\n", qstr_str(qstr));
401 }
402}
403
Damien415eb6f2013-10-05 12:19:06 +0100404static void emit_cpy_delete_subscr(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100405 emit_pre(emit, -2, 1);
406 if (emit->pass == PASS_3) {
407 printf("DELETE_SUBSCR\n");
408 }
409}
410
Damien415eb6f2013-10-05 12:19:06 +0100411static void emit_cpy_dup_top(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100412 emit_pre(emit, 1, 1);
413 if (emit->pass == PASS_3) {
414 printf("DUP_TOP\n");
415 }
416}
417
Damien415eb6f2013-10-05 12:19:06 +0100418static void emit_cpy_dup_top_two(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100419 emit_pre(emit, 2, 1);
420 if (emit->pass == PASS_3) {
421 printf("DUP_TOP_TWO\n");
422 }
423}
424
Damien415eb6f2013-10-05 12:19:06 +0100425static void emit_cpy_pop_top(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100426 emit_pre(emit, -1, 1);
427 if (emit->pass == PASS_3) {
428 printf("POP_TOP\n");
429 }
430}
431
Damien415eb6f2013-10-05 12:19:06 +0100432static void emit_cpy_rot_two(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100433 emit_pre(emit, 0, 1);
434 if (emit->pass == PASS_3) {
435 printf("ROT_TWO\n");
436 }
437}
438
Damien415eb6f2013-10-05 12:19:06 +0100439static void emit_cpy_rot_three(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100440 emit_pre(emit, 0, 1);
441 if (emit->pass == PASS_3) {
442 printf("ROT_THREE\n");
443 }
444}
445
Damien415eb6f2013-10-05 12:19:06 +0100446static void emit_cpy_jump(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100447 emit_pre(emit, 0, 3);
448 if (emit->pass == PASS_3) {
449 int dest = emit->label_offsets[label];
450 if (dest < emit->byte_code_offset) {
451 printf("JUMP_ABSOLUTE %d\n", emit->label_offsets[label]);
452 } else {
453 printf("JUMP_FORWARD %d\n", emit->label_offsets[label]);
454 }
455 }
456}
457
Damien415eb6f2013-10-05 12:19:06 +0100458static void emit_cpy_pop_jump_if_true(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100459 emit_pre(emit, -1, 3);
460 if (emit->pass == PASS_3) {
461 printf("POP_JUMP_IF_TRUE %d\n", emit->label_offsets[label]);
462 }
463}
464
Damien415eb6f2013-10-05 12:19:06 +0100465static void emit_cpy_pop_jump_if_false(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100466 emit_pre(emit, -1, 3);
467 if (emit->pass == PASS_3) {
468 printf("POP_JUMP_IF_FALSE %d\n", emit->label_offsets[label]);
469 }
470}
471
Damien415eb6f2013-10-05 12:19:06 +0100472static void emit_cpy_jump_if_true_or_pop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100473 emit_pre(emit, -1, 3);
474 if (emit->pass == PASS_3) {
475 printf("JUMP_IF_TRUE_OR_POP %d\n", emit->label_offsets[label]);
476 }
477}
478
Damien415eb6f2013-10-05 12:19:06 +0100479static void emit_cpy_jump_if_false_or_pop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100480 emit_pre(emit, -1, 3);
481 if (emit->pass == PASS_3) {
482 printf("JUMP_IF_FALSE_OR_POP %d\n", emit->label_offsets[label]);
483 }
484}
485
Damien415eb6f2013-10-05 12:19:06 +0100486static void emit_cpy_setup_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100487 emit_pre(emit, 0, 3);
488 if (emit->pass == PASS_3) {
489 printf("SETUP_LOOP %d\n", emit->label_offsets[label]);
490 }
491}
492
Damien415eb6f2013-10-05 12:19:06 +0100493static void emit_cpy_break_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100494 emit_pre(emit, 0, 1);
495 if (emit->pass == PASS_3) {
496 printf("BREAK_LOOP\n"); // CPython doesn't have label
497 //printf("BREAK_LOOP %d\n", emit->label_offsets[label]);
498 }
499}
500
Damien415eb6f2013-10-05 12:19:06 +0100501static void emit_cpy_continue_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100502 emit_pre(emit, 0, 3);
503 if (emit->pass == PASS_3) {
504 printf("CONTINUE_LOOP %d\n", emit->label_offsets[label]);
505 }
506}
507
Damien415eb6f2013-10-05 12:19:06 +0100508static void emit_cpy_setup_with(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100509 emit_pre(emit, 7, 3);
510 if (emit->pass == PASS_3) {
511 printf("SETUP_WITH %d\n", emit->label_offsets[label]);
512 }
513}
514
Damien415eb6f2013-10-05 12:19:06 +0100515static void emit_cpy_with_cleanup(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100516 emit_pre(emit, -7, 1);
517 if (emit->pass == PASS_3) {
518 printf("WITH_CLEANUP\n");
519 }
520}
521
Damien415eb6f2013-10-05 12:19:06 +0100522static void emit_cpy_setup_except(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100523 emit_pre(emit, 6, 3);
524 if (emit->pass == PASS_3) {
525 printf("SETUP_EXCEPT %d\n", emit->label_offsets[label]);
526 }
527}
528
Damien415eb6f2013-10-05 12:19:06 +0100529static void emit_cpy_setup_finally(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100530 emit_pre(emit, 6, 3);
531 if (emit->pass == PASS_3) {
532 printf("SETUP_FINALLY %d\n", emit->label_offsets[label]);
533 }
534}
535
Damien415eb6f2013-10-05 12:19:06 +0100536static void emit_cpy_end_finally(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100537 emit_pre(emit, -1, 1);
538 if (emit->pass == PASS_3) {
539 printf("END_FINALLY\n");
540 }
541}
542
Damien415eb6f2013-10-05 12:19:06 +0100543static void emit_cpy_get_iter(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100544 emit_pre(emit, 0, 1);
545 if (emit->pass == PASS_3) {
546 printf("GET_ITER\n");
547 }
548}
549
Damien415eb6f2013-10-05 12:19:06 +0100550static void emit_cpy_for_iter(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100551 emit_pre(emit, 1, 3);
552 if (emit->pass == PASS_3) {
553 printf("FOR_ITER %d\n", emit->label_offsets[label]);
554 }
555}
556
Damien415eb6f2013-10-05 12:19:06 +0100557static void emit_cpy_for_iter_end(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100558 emit_pre(emit, -1, 0);
559}
560
Damien415eb6f2013-10-05 12:19:06 +0100561static void emit_cpy_pop_block(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100562 emit_pre(emit, 0, 1);
563 if (emit->pass == PASS_3) {
564 printf("POP_BLOCK\n");
565 }
566}
567
Damien415eb6f2013-10-05 12:19:06 +0100568static void emit_cpy_pop_except(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100569 emit_pre(emit, 0, 1);
570 if (emit->pass == PASS_3) {
571 printf("POP_EXCEPT\n");
572 }
573}
574
Damien415eb6f2013-10-05 12:19:06 +0100575static void emit_cpy_unary_op(emit_t *emit, rt_unary_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100576 emit_pre(emit, 0, 1);
577 if (emit->pass == PASS_3) {
578 switch (op) {
579 case RT_UNARY_OP_NOT: printf("UNARY_NOT\n"); break;
580 case RT_UNARY_OP_POSITIVE: printf("UNARY_POSITIVE\n"); break;
581 case RT_UNARY_OP_NEGATIVE: printf("UNARY_NEGATIVE\n"); break;
582 case RT_UNARY_OP_INVERT: printf("UNARY_INVERT\n"); break;
583 default: assert(0);
584 }
585 }
586}
587
Damien415eb6f2013-10-05 12:19:06 +0100588static void emit_cpy_binary_op(emit_t *emit, rt_binary_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100589 emit_pre(emit, -1, 1);
590 if (emit->pass == PASS_3) {
591 switch (op) {
592 case RT_BINARY_OP_SUBSCR: printf("BINARY_SUBSCR\n"); break;
593 case RT_BINARY_OP_OR: printf("BINARY_OR\n"); break;
594 case RT_BINARY_OP_XOR: printf("BINARY_XOR\n"); break;
595 case RT_BINARY_OP_AND: printf("BINARY_AND\n"); break;
596 case RT_BINARY_OP_LSHIFT: printf("BINARY_LSHIFT\n"); break;
597 case RT_BINARY_OP_RSHIFT: printf("BINARY_RSHIFT\n"); break;
598 case RT_BINARY_OP_ADD: printf("BINARY_ADD\n"); break;
599 case RT_BINARY_OP_SUBTRACT: printf("BINARY_SUBTRACT\n"); break;
600 case RT_BINARY_OP_MULTIPLY: printf("BINARY_MULTIPLY\n"); break;
601 case RT_BINARY_OP_FLOOR_DIVIDE: printf("BINARY_FLOOR_DIVIDE\n"); break;
602 case RT_BINARY_OP_TRUE_DIVIDE: printf("BINARY_TRUE_DIVIDE\n"); break;
603 case RT_BINARY_OP_MODULO: printf("BINARY_MODULO\n"); break;
604 case RT_BINARY_OP_POWER: printf("BINARY_POWER\n"); break;
605 case RT_BINARY_OP_INPLACE_OR: printf("INPLACE_OR\n"); break;
606 case RT_BINARY_OP_INPLACE_XOR: printf("INPLACE_XOR\n"); break;
607 case RT_BINARY_OP_INPLACE_AND: printf("INPLACE_AND\n"); break;
608 case RT_BINARY_OP_INPLACE_LSHIFT: printf("INPLACE_LSHIFT\n"); break;
609 case RT_BINARY_OP_INPLACE_RSHIFT: printf("INPLACE_RSHIFT\n"); break;
610 case RT_BINARY_OP_INPLACE_ADD: printf("INPLACE_ADD\n"); break;
611 case RT_BINARY_OP_INPLACE_SUBTRACT: printf("INPLACE_SUBTRACT\n"); break;
612 case RT_BINARY_OP_INPLACE_MULTIPLY: printf("INPLACE_MULTIPLY\n"); break;
613 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: printf("INPLACE_FLOOR_DIVIDE\n"); break;
614 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: printf("INPLACE_TRUE_DIVIDE\n"); break;
615 case RT_BINARY_OP_INPLACE_MODULO: printf("INPLACE_MODULO\n"); break;
616 case RT_BINARY_OP_INPLACE_POWER: printf("INPLACE_POWER\n"); break;
617 default: assert(0);
618 }
619 }
620}
621
Damien415eb6f2013-10-05 12:19:06 +0100622static void emit_cpy_compare_op(emit_t *emit, rt_compare_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100623 emit_pre(emit, -1, 3);
624 if (emit->pass == PASS_3) {
625 switch (op) {
626 case RT_COMPARE_OP_LESS: printf("COMPARE_OP <\n"); break;
627 case RT_COMPARE_OP_MORE: printf("COMPARE_OP >\n"); break;
628 case RT_COMPARE_OP_EQUAL: printf("COMPARE_OP ==\n"); break;
629 case RT_COMPARE_OP_LESS_EQUAL: printf("COMPARE_OP <=\n"); break;
630 case RT_COMPARE_OP_MORE_EQUAL: printf("COMPARE_OP >=\n"); break;
631 case RT_COMPARE_OP_NOT_EQUAL: printf("COMPARE_OP !=\n"); break;
632 case RT_COMPARE_OP_IN: printf("COMPARE_OP in\n"); break;
633 case RT_COMPARE_OP_NOT_IN: printf("COMPARE_OP not in\n"); break;
634 case RT_COMPARE_OP_IS: printf("COMPARE_OP is\n"); break;
635 case RT_COMPARE_OP_IS_NOT: printf("COMPARE_OP is not\n"); break;
636 case RT_COMPARE_OP_EXCEPTION_MATCH: printf("COMPARE_OP exception match\n"); break;
637 default: assert(0);
638 }
639 }
640}
641
Damien415eb6f2013-10-05 12:19:06 +0100642static void emit_cpy_build_tuple(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100643 emit_pre(emit, 1 - n_args, 3);
644 if (emit->pass == PASS_3) {
645 printf("BUILD_TUPLE %d\n", n_args);
646 }
647}
648
Damien415eb6f2013-10-05 12:19:06 +0100649static void emit_cpy_build_list(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100650 emit_pre(emit, 1 - n_args, 3);
651 if (emit->pass == PASS_3) {
652 printf("BUILD_LIST %d\n", n_args);
653 }
654}
655
Damien415eb6f2013-10-05 12:19:06 +0100656static void emit_cpy_list_append(emit_t *emit, int list_index) {
Damien429d7192013-10-04 19:53:11 +0100657 emit_pre(emit, -1, 3);
658 if (emit->pass == PASS_3) {
659 printf("LIST_APPEND %d\n", list_index);
660 }
661}
662
Damien415eb6f2013-10-05 12:19:06 +0100663static void emit_cpy_build_map(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100664 emit_pre(emit, 1, 3);
665 if (emit->pass == PASS_3) {
666 printf("BUILD_MAP %d\n", n_args);
667 }
668}
669
Damien415eb6f2013-10-05 12:19:06 +0100670static void emit_cpy_store_map(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100671 emit_pre(emit, -2, 1);
672 if (emit->pass == PASS_3) {
673 printf("STORE_MAP\n");
674 }
675}
676
Damien415eb6f2013-10-05 12:19:06 +0100677static void emit_cpy_map_add(emit_t *emit, int map_index) {
Damien429d7192013-10-04 19:53:11 +0100678 emit_pre(emit, -2, 3);
679 if (emit->pass == PASS_3) {
680 printf("MAP_ADD %d\n", map_index);
681 }
682}
683
Damien415eb6f2013-10-05 12:19:06 +0100684static void emit_cpy_build_set(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100685 emit_pre(emit, 1 - n_args, 3);
686 if (emit->pass == PASS_3) {
687 printf("BUILD_SET %d\n", n_args);
688 }
689}
690
Damien415eb6f2013-10-05 12:19:06 +0100691static void emit_cpy_set_add(emit_t *emit, int set_index) {
Damien429d7192013-10-04 19:53:11 +0100692 emit_pre(emit, -1, 3);
693 if (emit->pass == PASS_3) {
694 printf("SET_ADD %d\n", set_index);
695 }
696}
697
Damien415eb6f2013-10-05 12:19:06 +0100698static void emit_cpy_build_slice(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100699 emit_pre(emit, 1 - n_args, 3);
700 if (emit->pass == PASS_3) {
701 printf("BUILD_SLICE %d\n", n_args);
702 }
703}
704
Damien415eb6f2013-10-05 12:19:06 +0100705static void emit_cpy_unpack_sequence(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100706 emit_pre(emit, -1 + n_args, 3);
707 if (emit->pass == PASS_3) {
708 printf("UNPACK_SEQUENCE %d\n", n_args);
709 }
710}
711
Damien415eb6f2013-10-05 12:19:06 +0100712static void emit_cpy_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien429d7192013-10-04 19:53:11 +0100713 emit_pre(emit, -1 + n_left + n_right + 1, 3);
714 if (emit->pass == PASS_3) {
715 printf("UNPACK_EX %d\n", n_left | (n_right << 8));
716 }
717}
718
Damien415eb6f2013-10-05 12:19:06 +0100719static void emit_cpy_call_function(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
Damien429d7192013-10-04 19:53:11 +0100720 int s = 0;
721 if (have_star_arg) {
722 s += 1;
723 }
724 if (have_dbl_star_arg) {
725 s += 1;
726 }
727 emit_pre(emit, -n_positional - 2 * n_keyword - s, 3);
728 if (emit->pass == PASS_3) {
729 if (have_star_arg) {
730 if (have_dbl_star_arg) {
731 printf("CALL_FUNCTION_VAR_KW");
732 } else {
733 printf("CALL_FUNCTION_VAR");
734 }
735 } else {
736 if (have_dbl_star_arg) {
737 printf("CALL_FUNCTION_KW");
738 } else {
739 printf("CALL_FUNCTION");
740 }
741 }
742 printf(" %d, %d\n", n_positional, n_keyword);
743 }
744}
745
Damien415eb6f2013-10-05 12:19:06 +0100746static void emit_cpy_call_method(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
747 emit_cpy_call_function(emit, n_positional, n_keyword, have_star_arg, have_dbl_star_arg);
Damien429d7192013-10-04 19:53:11 +0100748}
749
Damien415eb6f2013-10-05 12:19:06 +0100750static void emit_cpy_return_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100751 emit_pre(emit, -1, 1);
752 emit->last_emit_was_return_value = true;
753 if (emit->pass == PASS_3) {
754 printf("RETURN_VALUE\n");
755 }
756}
757
Damien415eb6f2013-10-05 12:19:06 +0100758static void emit_cpy_raise_varargs(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100759 emit_pre(emit, -n_args, 3);
760 if (emit->pass == PASS_3) {
761 printf("RAISE_VARARGS %d\n", n_args);
762 }
763}
764
Damien415eb6f2013-10-05 12:19:06 +0100765static void load_cpy_const_code_and_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100766 emit_pre(emit, 1, 3);
767 if (emit->pass == PASS_3) {
768 printf("LOAD_CONST code %s\n", qstr_str(qstr));
769 }
770 // load qualified name
771 emit_pre(emit, 1, 3);
772 if (emit->pass == PASS_3) {
773 printf("LOAD_CONST '");
774 // code just to work out the qualname (or whatever it is)
775 {
776 int depth = 0;
777 for (scope_t *s = emit->scope; s->parent != NULL; s = s->parent) {
778 depth += 1;
779 }
780 for (int wanted_depth = depth; wanted_depth >= 0; wanted_depth--) {
781 scope_t *s = emit->scope;
782 for (int i = 0; i < wanted_depth; i++) {
783 s = s->parent;
784 }
785 if (s->kind == SCOPE_FUNCTION) {
786 printf("%s.<locals>.", qstr_str(s->simple_name));
787 } else if (s->kind == SCOPE_CLASS) {
788 printf("%s.", qstr_str(s->simple_name));
789 }
790 }
791 }
792 printf("%s'\n", qstr_str(qstr));
793 }
794}
795
Damien415eb6f2013-10-05 12:19:06 +0100796static void emit_cpy_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
797 load_cpy_const_code_and_name(emit, scope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100798 emit_pre(emit, -1 - n_default_params - 2 * n_dict_params, 3);
799 if (emit->pass == PASS_3) {
800 printf("MAKE_FUNCTION %d\n", (n_dict_params << 8) | n_default_params);
801 }
802}
803
Damien415eb6f2013-10-05 12:19:06 +0100804static void emit_cpy_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
805 load_cpy_const_code_and_name(emit, scope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100806 emit_pre(emit, -2 - n_default_params - 2 * n_dict_params, 3);
807 if (emit->pass == PASS_3) {
808 printf("MAKE_CLOSURE %d\n", (n_dict_params << 8) | n_default_params);
809 }
810}
811
Damien415eb6f2013-10-05 12:19:06 +0100812static void emit_cpy_yield_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100813 emit_pre(emit, 0, 1);
814 if (emit->pass == PASS_2) {
815 emit->scope->flags |= SCOPE_FLAG_GENERATOR;
816 }
817 if (emit->pass == PASS_3) {
818 printf("YIELD_VALUE\n");
819 }
820}
821
Damien415eb6f2013-10-05 12:19:06 +0100822static void emit_cpy_yield_from(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100823 emit_pre(emit, -1, 1);
824 if (emit->pass == PASS_2) {
825 emit->scope->flags |= SCOPE_FLAG_GENERATOR;
826 }
827 if (emit->pass == PASS_3) {
828 printf("YIELD_FROM\n");
829 }
830}
831
Damien6cdd3af2013-10-05 18:08:26 +0100832const emit_method_table_t emit_cpython_method_table = {
Damien415eb6f2013-10-05 12:19:06 +0100833 emit_cpy_set_native_types,
834 emit_cpy_start_pass,
835 emit_cpy_end_pass,
836 emit_cpy_last_emit_was_return_value,
837 emit_cpy_get_stack_size,
838 emit_cpy_set_stack_size,
839
Damien4b03e772013-10-05 14:17:09 +0100840 emit_cpy_load_id,
841 emit_cpy_store_id,
842 emit_cpy_delete_id,
843
Damien415eb6f2013-10-05 12:19:06 +0100844 emit_cpy_label_assign,
845 emit_cpy_import_name,
846 emit_cpy_import_from,
847 emit_cpy_import_star,
848 emit_cpy_load_const_tok,
849 emit_cpy_load_const_small_int,
850 emit_cpy_load_const_int,
851 emit_cpy_load_const_dec,
852 emit_cpy_load_const_id,
853 emit_cpy_load_const_str,
854 emit_cpy_load_const_verbatim_start,
855 emit_cpy_load_const_verbatim_int,
856 emit_cpy_load_const_verbatim_str,
857 emit_cpy_load_const_verbatim_strn,
858 emit_cpy_load_const_verbatim_quoted_str,
859 emit_cpy_load_const_verbatim_end,
860 emit_cpy_load_fast,
861 emit_cpy_load_name,
862 emit_cpy_load_global,
863 emit_cpy_load_deref,
864 emit_cpy_load_closure,
865 emit_cpy_load_attr,
866 emit_cpy_load_method,
867 emit_cpy_load_build_class,
868 emit_cpy_store_fast,
869 emit_cpy_store_name,
870 emit_cpy_store_global,
871 emit_cpy_store_deref,
872 emit_cpy_store_attr,
Damien415eb6f2013-10-05 12:19:06 +0100873 emit_cpy_store_subscr,
Damiena3977762013-10-09 23:10:10 +0100874 emit_cpy_store_locals,
Damien415eb6f2013-10-05 12:19:06 +0100875 emit_cpy_delete_fast,
876 emit_cpy_delete_name,
877 emit_cpy_delete_global,
878 emit_cpy_delete_deref,
879 emit_cpy_delete_attr,
880 emit_cpy_delete_subscr,
881 emit_cpy_dup_top,
882 emit_cpy_dup_top_two,
883 emit_cpy_pop_top,
884 emit_cpy_rot_two,
885 emit_cpy_rot_three,
886 emit_cpy_jump,
887 emit_cpy_pop_jump_if_true,
888 emit_cpy_pop_jump_if_false,
889 emit_cpy_jump_if_true_or_pop,
890 emit_cpy_jump_if_false_or_pop,
891 emit_cpy_setup_loop,
892 emit_cpy_break_loop,
893 emit_cpy_continue_loop,
894 emit_cpy_setup_with,
895 emit_cpy_with_cleanup,
896 emit_cpy_setup_except,
897 emit_cpy_setup_finally,
898 emit_cpy_end_finally,
899 emit_cpy_get_iter,
900 emit_cpy_for_iter,
901 emit_cpy_for_iter_end,
902 emit_cpy_pop_block,
903 emit_cpy_pop_except,
904 emit_cpy_unary_op,
905 emit_cpy_binary_op,
906 emit_cpy_compare_op,
907 emit_cpy_build_tuple,
908 emit_cpy_build_list,
909 emit_cpy_list_append,
910 emit_cpy_build_map,
911 emit_cpy_store_map,
912 emit_cpy_map_add,
913 emit_cpy_build_set,
914 emit_cpy_set_add,
915 emit_cpy_build_slice,
916 emit_cpy_unpack_sequence,
917 emit_cpy_unpack_ex,
918 emit_cpy_make_function,
919 emit_cpy_make_closure,
920 emit_cpy_call_function,
921 emit_cpy_call_method,
922 emit_cpy_return_value,
923 emit_cpy_raise_varargs,
924 emit_cpy_yield_value,
925 emit_cpy_yield_from,
926};
927
Damienc025ebb2013-10-12 14:30:21 +0100928#endif // MICROPY_EMIT_ENABLE_CPYTHON