blob: 1c600ac5771689921b0b2ff684ea8463f6dbac88 [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"
9#include "lexer.h"
10#include "machine.h"
11#include "parse.h"
12#include "compile.h"
13#include "scope.h"
14#include "runtime.h"
15#include "emit.h"
16
Damien415eb6f2013-10-05 12:19:06 +010017#ifdef EMIT_ENABLE_CPY
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;
21 int next_label;
22 int byte_code_offset;
23 int stack_size;
24 bool last_emit_was_return_value;
25
26 scope_t *scope;
27
28 int max_num_labels;
29 int *label_offsets;
30};
31
Damien415eb6f2013-10-05 12:19:06 +010032static void emit_cpy_set_native_types(emit_t *emit, bool do_native_types) {
Damien429d7192013-10-04 19:53:11 +010033}
34
Damien415eb6f2013-10-05 12:19:06 +010035static void emit_cpy_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien429d7192013-10-04 19:53:11 +010036 emit->pass = pass;
37 emit->next_label = 1;
38 emit->byte_code_offset = 0;
39 emit->stack_size = 0;
40 emit->last_emit_was_return_value = false;
41 emit->scope = scope;
42 if (pass > PASS_1) {
43 if (emit->label_offsets == NULL) {
44 emit->label_offsets = m_new(int, emit->max_num_labels);
45 }
46 if (pass == PASS_2) {
47 memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(int));
48 }
49 }
50}
51
Damien415eb6f2013-10-05 12:19:06 +010052static void emit_cpy_end_pass(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010053 // check stack is back to zero size
54 if (emit->stack_size != 0) {
55 printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
56 }
57
58 // calculate number of labels need
59 if (emit->pass == PASS_1) {
60 if (emit->next_label > emit->max_num_labels) {
61 emit->max_num_labels = emit->next_label;
62 }
63 }
64}
65
Damien415eb6f2013-10-05 12:19:06 +010066static bool emit_cpy_last_emit_was_return_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010067 return emit->last_emit_was_return_value;
68}
69
Damien415eb6f2013-10-05 12:19:06 +010070static int emit_cpy_get_stack_size(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010071 return emit->stack_size;
72}
73
Damien415eb6f2013-10-05 12:19:06 +010074static void emit_cpy_set_stack_size(emit_t *emit, int size) {
Damien429d7192013-10-04 19:53:11 +010075 emit->stack_size = size;
76}
77
Damien415eb6f2013-10-05 12:19:06 +010078static void emit_pre(emit_t *emit, int stack_size_delta, int byte_code_size) {
Damien429d7192013-10-04 19:53:11 +010079 emit->stack_size += stack_size_delta;
80 if (emit->pass > PASS_1 && emit->stack_size > emit->scope->stack_size) {
81 emit->scope->stack_size = emit->stack_size;
82 }
83 emit->last_emit_was_return_value = false;
84 if (emit->pass == PASS_3 && byte_code_size > 0) {
85 if (emit->byte_code_offset >= 1000) {
86 printf("%d ", emit->byte_code_offset);
87 } else {
88 printf("% 4d ", emit->byte_code_offset);
89 }
90 }
91 emit->byte_code_offset += byte_code_size;
92}
93
Damien415eb6f2013-10-05 12:19:06 +010094static int emit_cpy_label_new(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010095 return emit->next_label++;
96}
97
Damien415eb6f2013-10-05 12:19:06 +010098static void emit_cpy_label_assign(emit_t *emit, int l) {
Damien429d7192013-10-04 19:53:11 +010099 emit_pre(emit, 0, 0);
100 if (emit->pass > PASS_1) {
101 assert(l < emit->max_num_labels);
102 if (emit->pass == PASS_2) {
103 // assign label offset
104 assert(emit->label_offsets[l] == -1);
105 emit->label_offsets[l] = emit->byte_code_offset;
106 } else if (emit->pass == PASS_3) {
107 // ensure label offset has not changed from PASS_2 to PASS_3
108 assert(emit->label_offsets[l] == emit->byte_code_offset);
109 //printf("l%d: (at %d)\n", l, emit->byte_code_offset);
110 }
111 }
112}
113
Damien415eb6f2013-10-05 12:19:06 +0100114static void emit_cpy_import_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100115 emit_pre(emit, -1, 3);
116 if (emit->pass == PASS_3) {
117 printf("IMPORT_NAME %s\n", qstr_str(qstr));
118 }
119}
120
Damien415eb6f2013-10-05 12:19:06 +0100121static void emit_cpy_import_from(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100122 emit_pre(emit, 1, 3);
123 if (emit->pass == PASS_3) {
124 printf("IMPORT_FROM %s\n", qstr_str(qstr));
125 }
126}
127
Damien415eb6f2013-10-05 12:19:06 +0100128static void emit_cpy_import_star(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100129 emit_pre(emit, -1, 1);
130 if (emit->pass == PASS_3) {
131 printf("IMPORT_STAR\n");
132 }
133}
134
Damien415eb6f2013-10-05 12:19:06 +0100135static void emit_cpy_load_const_tok(emit_t *emit, py_token_kind_t tok) {
Damien429d7192013-10-04 19:53:11 +0100136 emit_pre(emit, 1, 3);
137 if (emit->pass == PASS_3) {
138 printf("LOAD_CONST ");
139 switch (tok) {
140 case PY_TOKEN_KW_FALSE: printf("False"); break;
141 case PY_TOKEN_KW_NONE: printf("None"); break;
142 case PY_TOKEN_KW_TRUE: printf("True"); break;
143 default: printf("?=%d\n", tok); return; assert(0);
144 }
145 printf("\n");
146 }
147}
148
Damien415eb6f2013-10-05 12:19:06 +0100149static void emit_cpy_load_const_small_int(emit_t *emit, int arg) {
Damien429d7192013-10-04 19:53:11 +0100150 emit_pre(emit, 1, 3);
151 if (emit->pass == PASS_3) {
152 printf("LOAD_CONST %d\n", arg);
153 }
154}
155
Damien415eb6f2013-10-05 12:19:06 +0100156static void emit_cpy_load_const_int(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100157 emit_pre(emit, 1, 3);
158 if (emit->pass == PASS_3) {
159 printf("LOAD_CONST %s\n", qstr_str(qstr));
160 }
161}
162
Damien415eb6f2013-10-05 12:19:06 +0100163static void emit_cpy_load_const_dec(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100164 emit_pre(emit, 1, 3);
165 if (emit->pass == PASS_3) {
166 printf("LOAD_CONST %s\n", qstr_str(qstr));
167 }
168}
169
Damien415eb6f2013-10-05 12:19:06 +0100170static void emit_cpy_load_const_id(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100171 emit_pre(emit, 1, 3);
172 if (emit->pass == PASS_3) {
173 printf("LOAD_CONST '%s'\n", qstr_str(qstr));
174 }
175}
176
Damien415eb6f2013-10-05 12:19:06 +0100177static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes);
178static void emit_cpy_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien429d7192013-10-04 19:53:11 +0100179 emit_pre(emit, 1, 3);
180 if (emit->pass == PASS_3) {
181 printf("LOAD_CONST ");
Damien415eb6f2013-10-05 12:19:06 +0100182 emit_cpy_load_const_verbatim_quoted_str(emit, qstr, bytes);
Damien429d7192013-10-04 19:53:11 +0100183 printf("\n");
184 }
185}
186
Damien415eb6f2013-10-05 12:19:06 +0100187static void emit_cpy_load_const_verbatim_start(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100188 emit_pre(emit, 1, 3);
189 if (emit->pass == PASS_3) {
190 printf("LOAD_CONST ");
191 }
192}
193
Damien415eb6f2013-10-05 12:19:06 +0100194static void emit_cpy_load_const_verbatim_int(emit_t *emit, int val) {
Damien429d7192013-10-04 19:53:11 +0100195 if (emit->pass == PASS_3) {
196 printf("%d", val);
197 }
198}
199
Damien415eb6f2013-10-05 12:19:06 +0100200static void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) {
Damien429d7192013-10-04 19:53:11 +0100201 if (emit->pass == PASS_3) {
202 printf("%s", str);
203 }
204}
205
Damien415eb6f2013-10-05 12:19:06 +0100206static void emit_cpy_load_const_verbatim_strn(emit_t *emit, const char *str, int len) {
Damien429d7192013-10-04 19:53:11 +0100207 if (emit->pass == PASS_3) {
208 printf("%.*s", len, str);
209 }
210}
211
Damien415eb6f2013-10-05 12:19:06 +0100212static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes) {
Damien429d7192013-10-04 19:53:11 +0100213 // TODO strings should be escaped before we get here
214 if (emit->pass == PASS_3) {
215 const char *str = qstr_str(qstr);
216 int len = strlen(str);
217 bool has_single_quote = false;
218 bool has_double_quote = false;
219 for (int i = 0; i < len; i++) {
220 if (str[i] == '\'') {
221 has_single_quote = true;
222 } else if (str[i] == '"') {
223 has_double_quote = true;
224 }
225 }
226 if (bytes) {
227 printf("b");
228 }
229 bool quote_single = false;
230 if (has_single_quote && !has_double_quote) {
231 printf("\"");
232 } else {
233 quote_single = true;
234 printf("'");
235 }
236 for (int i = 0; i < len; i++) {
237 if (str[i] == '\n') {
238 printf("\\n");
239 } else if (str[i] == '\\' && str[i + 1] == '\'') {
240 i += 1;
241 if (quote_single) {
242 printf("\\'");
243 } else {
244 printf("'");
245 }
246 } else if (str[i] == '\'' && quote_single) {
247 printf("\\'");
248 } else {
249 printf("%c", str[i]);
250 }
251 }
252 if (has_single_quote && !has_double_quote) {
253 printf("\"");
254 } else {
255 printf("'");
256 }
257 }
258}
259
Damien415eb6f2013-10-05 12:19:06 +0100260static void emit_cpy_load_const_verbatim_end(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100261 if (emit->pass == PASS_3) {
262 printf("\n");
263 }
264}
265
Damien415eb6f2013-10-05 12:19:06 +0100266static void emit_cpy_load_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100267 emit_pre(emit, 1, 3);
268 if (emit->pass == PASS_3) {
269 printf("LOAD_NAME %s\n", qstr_str(qstr));
270 }
271}
272
Damien415eb6f2013-10-05 12:19:06 +0100273static void emit_cpy_load_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100274 emit_pre(emit, 1, 3);
275 if (emit->pass == PASS_3) {
276 printf("LOAD_GLOBAL %s\n", qstr_str(qstr));
277 }
278}
279
Damien415eb6f2013-10-05 12:19:06 +0100280static void emit_cpy_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien429d7192013-10-04 19:53:11 +0100281 emit_pre(emit, 1, 3);
282 if (emit->pass == PASS_3) {
283 printf("LOAD_FAST %s\n", qstr_str(qstr));
284 }
285}
286
Damien415eb6f2013-10-05 12:19:06 +0100287static void emit_cpy_load_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100288 emit_pre(emit, 1, 3);
289 if (emit->pass == PASS_3) {
290 printf("LOAD_DEREF %s\n", qstr_str(qstr));
291 }
292}
293
Damien415eb6f2013-10-05 12:19:06 +0100294static void emit_cpy_load_closure(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100295 emit_pre(emit, 1, 3);
296 if (emit->pass == PASS_3) {
297 printf("LOAD_CLOSURE %s\n", qstr_str(qstr));
298 }
299}
300
Damien415eb6f2013-10-05 12:19:06 +0100301static void emit_cpy_load_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100302 emit_pre(emit, 0, 3);
303 if (emit->pass == PASS_3) {
304 printf("LOAD_ATTR %s\n", qstr_str(qstr));
305 }
306}
307
Damien415eb6f2013-10-05 12:19:06 +0100308static void emit_cpy_load_method(emit_t *emit, qstr qstr) {
309 emit_cpy_load_attr(emit, qstr);
Damien429d7192013-10-04 19:53:11 +0100310}
311
Damien415eb6f2013-10-05 12:19:06 +0100312static void emit_cpy_load_build_class(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100313 emit_pre(emit, 1, 1);
314 if (emit->pass == PASS_3) {
315 printf("LOAD_BUILD_CLASS\n");
316 }
317}
318
Damien415eb6f2013-10-05 12:19:06 +0100319static void emit_cpy_store_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100320 emit_pre(emit, -1, 3);
321 if (emit->pass == PASS_3) {
322 printf("STORE_NAME %s\n", qstr_str(qstr));
323 }
324}
325
Damien415eb6f2013-10-05 12:19:06 +0100326static void emit_cpy_store_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100327 emit_pre(emit, -1, 3);
328 if (emit->pass == PASS_3) {
329 printf("STORE_GLOBAL %s\n", qstr_str(qstr));
330 }
331}
332
Damien415eb6f2013-10-05 12:19:06 +0100333static void emit_cpy_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien429d7192013-10-04 19:53:11 +0100334 emit_pre(emit, -1, 3);
335 if (emit->pass == PASS_3) {
336 printf("STORE_FAST %s\n", qstr_str(qstr));
337 }
338}
339
Damien415eb6f2013-10-05 12:19:06 +0100340static void emit_cpy_store_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100341 emit_pre(emit, -1, 3);
342 if (emit->pass == PASS_3) {
343 printf("STORE_DEREF %s\n", qstr_str(qstr));
344 }
345}
346
Damien415eb6f2013-10-05 12:19:06 +0100347static void emit_cpy_store_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100348 emit_pre(emit, -2, 3);
349 if (emit->pass == PASS_3) {
350 printf("STORE_ATTR %s\n", qstr_str(qstr));
351 }
352}
353
Damien415eb6f2013-10-05 12:19:06 +0100354static void emit_cpy_store_locals(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100355 emit_pre(emit, -1, 1);
356 if (emit->pass == PASS_3) {
357 printf("STORE_LOCALS\n");
358 }
359}
360
Damien415eb6f2013-10-05 12:19:06 +0100361static void emit_cpy_store_subscr(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100362 emit_pre(emit, -3, 1);
363 if (emit->pass == PASS_3) {
364 printf("STORE_SUBSCR\n");
365 }
366}
367
Damien415eb6f2013-10-05 12:19:06 +0100368static void emit_cpy_delete_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100369 emit_pre(emit, 0, 3);
370 if (emit->pass == PASS_3) {
371 printf("DELETE_NAME %s\n", qstr_str(qstr));
372 }
373}
374
Damien415eb6f2013-10-05 12:19:06 +0100375static void emit_cpy_delete_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100376 emit_pre(emit, 0, 3);
377 if (emit->pass == PASS_3) {
378 printf("DELETE_GLOBAL %s\n", qstr_str(qstr));
379 }
380}
381
Damien415eb6f2013-10-05 12:19:06 +0100382static void emit_cpy_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien429d7192013-10-04 19:53:11 +0100383 emit_pre(emit, 0, 3);
384 if (emit->pass == PASS_3) {
385 printf("DELETE_FAST %s\n", qstr_str(qstr));
386 }
387}
388
Damien415eb6f2013-10-05 12:19:06 +0100389static void emit_cpy_delete_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100390 emit_pre(emit, 0, 3);
391 if (emit->pass == PASS_3) {
392 printf("DELETE_DEREF %s\n", qstr_str(qstr));
393 }
394}
395
Damien415eb6f2013-10-05 12:19:06 +0100396static void emit_cpy_delete_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100397 emit_pre(emit, -1, 3);
398 if (emit->pass == PASS_3) {
399 printf("DELETE_ATTR %s\n", qstr_str(qstr));
400 }
401}
402
Damien415eb6f2013-10-05 12:19:06 +0100403static void emit_cpy_delete_subscr(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100404 emit_pre(emit, -2, 1);
405 if (emit->pass == PASS_3) {
406 printf("DELETE_SUBSCR\n");
407 }
408}
409
Damien415eb6f2013-10-05 12:19:06 +0100410static void emit_cpy_dup_top(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100411 emit_pre(emit, 1, 1);
412 if (emit->pass == PASS_3) {
413 printf("DUP_TOP\n");
414 }
415}
416
Damien415eb6f2013-10-05 12:19:06 +0100417static void emit_cpy_dup_top_two(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100418 emit_pre(emit, 2, 1);
419 if (emit->pass == PASS_3) {
420 printf("DUP_TOP_TWO\n");
421 }
422}
423
Damien415eb6f2013-10-05 12:19:06 +0100424static void emit_cpy_pop_top(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100425 emit_pre(emit, -1, 1);
426 if (emit->pass == PASS_3) {
427 printf("POP_TOP\n");
428 }
429}
430
Damien415eb6f2013-10-05 12:19:06 +0100431static void emit_cpy_rot_two(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100432 emit_pre(emit, 0, 1);
433 if (emit->pass == PASS_3) {
434 printf("ROT_TWO\n");
435 }
436}
437
Damien415eb6f2013-10-05 12:19:06 +0100438static void emit_cpy_rot_three(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100439 emit_pre(emit, 0, 1);
440 if (emit->pass == PASS_3) {
441 printf("ROT_THREE\n");
442 }
443}
444
Damien415eb6f2013-10-05 12:19:06 +0100445static void emit_cpy_jump(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100446 emit_pre(emit, 0, 3);
447 if (emit->pass == PASS_3) {
448 int dest = emit->label_offsets[label];
449 if (dest < emit->byte_code_offset) {
450 printf("JUMP_ABSOLUTE %d\n", emit->label_offsets[label]);
451 } else {
452 printf("JUMP_FORWARD %d\n", emit->label_offsets[label]);
453 }
454 }
455}
456
Damien415eb6f2013-10-05 12:19:06 +0100457static void emit_cpy_pop_jump_if_true(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100458 emit_pre(emit, -1, 3);
459 if (emit->pass == PASS_3) {
460 printf("POP_JUMP_IF_TRUE %d\n", emit->label_offsets[label]);
461 }
462}
463
Damien415eb6f2013-10-05 12:19:06 +0100464static void emit_cpy_pop_jump_if_false(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100465 emit_pre(emit, -1, 3);
466 if (emit->pass == PASS_3) {
467 printf("POP_JUMP_IF_FALSE %d\n", emit->label_offsets[label]);
468 }
469}
470
Damien415eb6f2013-10-05 12:19:06 +0100471static void emit_cpy_jump_if_true_or_pop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100472 emit_pre(emit, -1, 3);
473 if (emit->pass == PASS_3) {
474 printf("JUMP_IF_TRUE_OR_POP %d\n", emit->label_offsets[label]);
475 }
476}
477
Damien415eb6f2013-10-05 12:19:06 +0100478static void emit_cpy_jump_if_false_or_pop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100479 emit_pre(emit, -1, 3);
480 if (emit->pass == PASS_3) {
481 printf("JUMP_IF_FALSE_OR_POP %d\n", emit->label_offsets[label]);
482 }
483}
484
Damien415eb6f2013-10-05 12:19:06 +0100485static void emit_cpy_setup_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100486 emit_pre(emit, 0, 3);
487 if (emit->pass == PASS_3) {
488 printf("SETUP_LOOP %d\n", emit->label_offsets[label]);
489 }
490}
491
Damien415eb6f2013-10-05 12:19:06 +0100492static void emit_cpy_break_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100493 emit_pre(emit, 0, 1);
494 if (emit->pass == PASS_3) {
495 printf("BREAK_LOOP\n"); // CPython doesn't have label
496 //printf("BREAK_LOOP %d\n", emit->label_offsets[label]);
497 }
498}
499
Damien415eb6f2013-10-05 12:19:06 +0100500static void emit_cpy_continue_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100501 emit_pre(emit, 0, 3);
502 if (emit->pass == PASS_3) {
503 printf("CONTINUE_LOOP %d\n", emit->label_offsets[label]);
504 }
505}
506
Damien415eb6f2013-10-05 12:19:06 +0100507static void emit_cpy_setup_with(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100508 emit_pre(emit, 7, 3);
509 if (emit->pass == PASS_3) {
510 printf("SETUP_WITH %d\n", emit->label_offsets[label]);
511 }
512}
513
Damien415eb6f2013-10-05 12:19:06 +0100514static void emit_cpy_with_cleanup(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100515 emit_pre(emit, -7, 1);
516 if (emit->pass == PASS_3) {
517 printf("WITH_CLEANUP\n");
518 }
519}
520
Damien415eb6f2013-10-05 12:19:06 +0100521static void emit_cpy_setup_except(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100522 emit_pre(emit, 6, 3);
523 if (emit->pass == PASS_3) {
524 printf("SETUP_EXCEPT %d\n", emit->label_offsets[label]);
525 }
526}
527
Damien415eb6f2013-10-05 12:19:06 +0100528static void emit_cpy_setup_finally(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100529 emit_pre(emit, 6, 3);
530 if (emit->pass == PASS_3) {
531 printf("SETUP_FINALLY %d\n", emit->label_offsets[label]);
532 }
533}
534
Damien415eb6f2013-10-05 12:19:06 +0100535static void emit_cpy_end_finally(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100536 emit_pre(emit, -1, 1);
537 if (emit->pass == PASS_3) {
538 printf("END_FINALLY\n");
539 }
540}
541
Damien415eb6f2013-10-05 12:19:06 +0100542static void emit_cpy_get_iter(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100543 emit_pre(emit, 0, 1);
544 if (emit->pass == PASS_3) {
545 printf("GET_ITER\n");
546 }
547}
548
Damien415eb6f2013-10-05 12:19:06 +0100549static void emit_cpy_for_iter(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100550 emit_pre(emit, 1, 3);
551 if (emit->pass == PASS_3) {
552 printf("FOR_ITER %d\n", emit->label_offsets[label]);
553 }
554}
555
Damien415eb6f2013-10-05 12:19:06 +0100556static void emit_cpy_for_iter_end(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100557 emit_pre(emit, -1, 0);
558}
559
Damien415eb6f2013-10-05 12:19:06 +0100560static void emit_cpy_pop_block(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100561 emit_pre(emit, 0, 1);
562 if (emit->pass == PASS_3) {
563 printf("POP_BLOCK\n");
564 }
565}
566
Damien415eb6f2013-10-05 12:19:06 +0100567static void emit_cpy_pop_except(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100568 emit_pre(emit, 0, 1);
569 if (emit->pass == PASS_3) {
570 printf("POP_EXCEPT\n");
571 }
572}
573
Damien415eb6f2013-10-05 12:19:06 +0100574static void emit_cpy_unary_op(emit_t *emit, rt_unary_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100575 emit_pre(emit, 0, 1);
576 if (emit->pass == PASS_3) {
577 switch (op) {
578 case RT_UNARY_OP_NOT: printf("UNARY_NOT\n"); break;
579 case RT_UNARY_OP_POSITIVE: printf("UNARY_POSITIVE\n"); break;
580 case RT_UNARY_OP_NEGATIVE: printf("UNARY_NEGATIVE\n"); break;
581 case RT_UNARY_OP_INVERT: printf("UNARY_INVERT\n"); break;
582 default: assert(0);
583 }
584 }
585}
586
Damien415eb6f2013-10-05 12:19:06 +0100587static void emit_cpy_binary_op(emit_t *emit, rt_binary_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100588 emit_pre(emit, -1, 1);
589 if (emit->pass == PASS_3) {
590 switch (op) {
591 case RT_BINARY_OP_SUBSCR: printf("BINARY_SUBSCR\n"); break;
592 case RT_BINARY_OP_OR: printf("BINARY_OR\n"); break;
593 case RT_BINARY_OP_XOR: printf("BINARY_XOR\n"); break;
594 case RT_BINARY_OP_AND: printf("BINARY_AND\n"); break;
595 case RT_BINARY_OP_LSHIFT: printf("BINARY_LSHIFT\n"); break;
596 case RT_BINARY_OP_RSHIFT: printf("BINARY_RSHIFT\n"); break;
597 case RT_BINARY_OP_ADD: printf("BINARY_ADD\n"); break;
598 case RT_BINARY_OP_SUBTRACT: printf("BINARY_SUBTRACT\n"); break;
599 case RT_BINARY_OP_MULTIPLY: printf("BINARY_MULTIPLY\n"); break;
600 case RT_BINARY_OP_FLOOR_DIVIDE: printf("BINARY_FLOOR_DIVIDE\n"); break;
601 case RT_BINARY_OP_TRUE_DIVIDE: printf("BINARY_TRUE_DIVIDE\n"); break;
602 case RT_BINARY_OP_MODULO: printf("BINARY_MODULO\n"); break;
603 case RT_BINARY_OP_POWER: printf("BINARY_POWER\n"); break;
604 case RT_BINARY_OP_INPLACE_OR: printf("INPLACE_OR\n"); break;
605 case RT_BINARY_OP_INPLACE_XOR: printf("INPLACE_XOR\n"); break;
606 case RT_BINARY_OP_INPLACE_AND: printf("INPLACE_AND\n"); break;
607 case RT_BINARY_OP_INPLACE_LSHIFT: printf("INPLACE_LSHIFT\n"); break;
608 case RT_BINARY_OP_INPLACE_RSHIFT: printf("INPLACE_RSHIFT\n"); break;
609 case RT_BINARY_OP_INPLACE_ADD: printf("INPLACE_ADD\n"); break;
610 case RT_BINARY_OP_INPLACE_SUBTRACT: printf("INPLACE_SUBTRACT\n"); break;
611 case RT_BINARY_OP_INPLACE_MULTIPLY: printf("INPLACE_MULTIPLY\n"); break;
612 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: printf("INPLACE_FLOOR_DIVIDE\n"); break;
613 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: printf("INPLACE_TRUE_DIVIDE\n"); break;
614 case RT_BINARY_OP_INPLACE_MODULO: printf("INPLACE_MODULO\n"); break;
615 case RT_BINARY_OP_INPLACE_POWER: printf("INPLACE_POWER\n"); break;
616 default: assert(0);
617 }
618 }
619}
620
Damien415eb6f2013-10-05 12:19:06 +0100621static void emit_cpy_compare_op(emit_t *emit, rt_compare_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100622 emit_pre(emit, -1, 3);
623 if (emit->pass == PASS_3) {
624 switch (op) {
625 case RT_COMPARE_OP_LESS: printf("COMPARE_OP <\n"); break;
626 case RT_COMPARE_OP_MORE: printf("COMPARE_OP >\n"); break;
627 case RT_COMPARE_OP_EQUAL: printf("COMPARE_OP ==\n"); break;
628 case RT_COMPARE_OP_LESS_EQUAL: printf("COMPARE_OP <=\n"); break;
629 case RT_COMPARE_OP_MORE_EQUAL: printf("COMPARE_OP >=\n"); break;
630 case RT_COMPARE_OP_NOT_EQUAL: printf("COMPARE_OP !=\n"); break;
631 case RT_COMPARE_OP_IN: printf("COMPARE_OP in\n"); break;
632 case RT_COMPARE_OP_NOT_IN: printf("COMPARE_OP not in\n"); break;
633 case RT_COMPARE_OP_IS: printf("COMPARE_OP is\n"); break;
634 case RT_COMPARE_OP_IS_NOT: printf("COMPARE_OP is not\n"); break;
635 case RT_COMPARE_OP_EXCEPTION_MATCH: printf("COMPARE_OP exception match\n"); break;
636 default: assert(0);
637 }
638 }
639}
640
Damien415eb6f2013-10-05 12:19:06 +0100641static void emit_cpy_build_tuple(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100642 emit_pre(emit, 1 - n_args, 3);
643 if (emit->pass == PASS_3) {
644 printf("BUILD_TUPLE %d\n", n_args);
645 }
646}
647
Damien415eb6f2013-10-05 12:19:06 +0100648static void emit_cpy_build_list(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100649 emit_pre(emit, 1 - n_args, 3);
650 if (emit->pass == PASS_3) {
651 printf("BUILD_LIST %d\n", n_args);
652 }
653}
654
Damien415eb6f2013-10-05 12:19:06 +0100655static void emit_cpy_list_append(emit_t *emit, int list_index) {
Damien429d7192013-10-04 19:53:11 +0100656 emit_pre(emit, -1, 3);
657 if (emit->pass == PASS_3) {
658 printf("LIST_APPEND %d\n", list_index);
659 }
660}
661
Damien415eb6f2013-10-05 12:19:06 +0100662static void emit_cpy_build_map(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100663 emit_pre(emit, 1, 3);
664 if (emit->pass == PASS_3) {
665 printf("BUILD_MAP %d\n", n_args);
666 }
667}
668
Damien415eb6f2013-10-05 12:19:06 +0100669static void emit_cpy_store_map(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100670 emit_pre(emit, -2, 1);
671 if (emit->pass == PASS_3) {
672 printf("STORE_MAP\n");
673 }
674}
675
Damien415eb6f2013-10-05 12:19:06 +0100676static void emit_cpy_map_add(emit_t *emit, int map_index) {
Damien429d7192013-10-04 19:53:11 +0100677 emit_pre(emit, -2, 3);
678 if (emit->pass == PASS_3) {
679 printf("MAP_ADD %d\n", map_index);
680 }
681}
682
Damien415eb6f2013-10-05 12:19:06 +0100683static void emit_cpy_build_set(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100684 emit_pre(emit, 1 - n_args, 3);
685 if (emit->pass == PASS_3) {
686 printf("BUILD_SET %d\n", n_args);
687 }
688}
689
Damien415eb6f2013-10-05 12:19:06 +0100690static void emit_cpy_set_add(emit_t *emit, int set_index) {
Damien429d7192013-10-04 19:53:11 +0100691 emit_pre(emit, -1, 3);
692 if (emit->pass == PASS_3) {
693 printf("SET_ADD %d\n", set_index);
694 }
695}
696
Damien415eb6f2013-10-05 12:19:06 +0100697static void emit_cpy_build_slice(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100698 emit_pre(emit, 1 - n_args, 3);
699 if (emit->pass == PASS_3) {
700 printf("BUILD_SLICE %d\n", n_args);
701 }
702}
703
Damien415eb6f2013-10-05 12:19:06 +0100704static void emit_cpy_unpack_sequence(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100705 emit_pre(emit, -1 + n_args, 3);
706 if (emit->pass == PASS_3) {
707 printf("UNPACK_SEQUENCE %d\n", n_args);
708 }
709}
710
Damien415eb6f2013-10-05 12:19:06 +0100711static void emit_cpy_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien429d7192013-10-04 19:53:11 +0100712 emit_pre(emit, -1 + n_left + n_right + 1, 3);
713 if (emit->pass == PASS_3) {
714 printf("UNPACK_EX %d\n", n_left | (n_right << 8));
715 }
716}
717
Damien415eb6f2013-10-05 12:19:06 +0100718static 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 +0100719 int s = 0;
720 if (have_star_arg) {
721 s += 1;
722 }
723 if (have_dbl_star_arg) {
724 s += 1;
725 }
726 emit_pre(emit, -n_positional - 2 * n_keyword - s, 3);
727 if (emit->pass == PASS_3) {
728 if (have_star_arg) {
729 if (have_dbl_star_arg) {
730 printf("CALL_FUNCTION_VAR_KW");
731 } else {
732 printf("CALL_FUNCTION_VAR");
733 }
734 } else {
735 if (have_dbl_star_arg) {
736 printf("CALL_FUNCTION_KW");
737 } else {
738 printf("CALL_FUNCTION");
739 }
740 }
741 printf(" %d, %d\n", n_positional, n_keyword);
742 }
743}
744
Damien415eb6f2013-10-05 12:19:06 +0100745static void emit_cpy_call_method(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
746 emit_cpy_call_function(emit, n_positional, n_keyword, have_star_arg, have_dbl_star_arg);
Damien429d7192013-10-04 19:53:11 +0100747}
748
Damien415eb6f2013-10-05 12:19:06 +0100749static void emit_cpy_return_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100750 emit_pre(emit, -1, 1);
751 emit->last_emit_was_return_value = true;
752 if (emit->pass == PASS_3) {
753 printf("RETURN_VALUE\n");
754 }
755}
756
Damien415eb6f2013-10-05 12:19:06 +0100757static void emit_cpy_raise_varargs(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100758 emit_pre(emit, -n_args, 3);
759 if (emit->pass == PASS_3) {
760 printf("RAISE_VARARGS %d\n", n_args);
761 }
762}
763
Damien415eb6f2013-10-05 12:19:06 +0100764static void load_cpy_const_code_and_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100765 emit_pre(emit, 1, 3);
766 if (emit->pass == PASS_3) {
767 printf("LOAD_CONST code %s\n", qstr_str(qstr));
768 }
769 // load qualified name
770 emit_pre(emit, 1, 3);
771 if (emit->pass == PASS_3) {
772 printf("LOAD_CONST '");
773 // code just to work out the qualname (or whatever it is)
774 {
775 int depth = 0;
776 for (scope_t *s = emit->scope; s->parent != NULL; s = s->parent) {
777 depth += 1;
778 }
779 for (int wanted_depth = depth; wanted_depth >= 0; wanted_depth--) {
780 scope_t *s = emit->scope;
781 for (int i = 0; i < wanted_depth; i++) {
782 s = s->parent;
783 }
784 if (s->kind == SCOPE_FUNCTION) {
785 printf("%s.<locals>.", qstr_str(s->simple_name));
786 } else if (s->kind == SCOPE_CLASS) {
787 printf("%s.", qstr_str(s->simple_name));
788 }
789 }
790 }
791 printf("%s'\n", qstr_str(qstr));
792 }
793}
794
Damien415eb6f2013-10-05 12:19:06 +0100795static void emit_cpy_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
796 load_cpy_const_code_and_name(emit, scope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100797 emit_pre(emit, -1 - n_default_params - 2 * n_dict_params, 3);
798 if (emit->pass == PASS_3) {
799 printf("MAKE_FUNCTION %d\n", (n_dict_params << 8) | n_default_params);
800 }
801}
802
Damien415eb6f2013-10-05 12:19:06 +0100803static void emit_cpy_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
804 load_cpy_const_code_and_name(emit, scope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100805 emit_pre(emit, -2 - n_default_params - 2 * n_dict_params, 3);
806 if (emit->pass == PASS_3) {
807 printf("MAKE_CLOSURE %d\n", (n_dict_params << 8) | n_default_params);
808 }
809}
810
Damien415eb6f2013-10-05 12:19:06 +0100811static void emit_cpy_yield_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100812 emit_pre(emit, 0, 1);
813 if (emit->pass == PASS_2) {
814 emit->scope->flags |= SCOPE_FLAG_GENERATOR;
815 }
816 if (emit->pass == PASS_3) {
817 printf("YIELD_VALUE\n");
818 }
819}
820
Damien415eb6f2013-10-05 12:19:06 +0100821static void emit_cpy_yield_from(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100822 emit_pre(emit, -1, 1);
823 if (emit->pass == PASS_2) {
824 emit->scope->flags |= SCOPE_FLAG_GENERATOR;
825 }
826 if (emit->pass == PASS_3) {
827 printf("YIELD_FROM\n");
828 }
829}
830
Damien415eb6f2013-10-05 12:19:06 +0100831static const emit_method_table_t emit_cpy_method_table = {
832 emit_cpy_set_native_types,
833 emit_cpy_start_pass,
834 emit_cpy_end_pass,
835 emit_cpy_last_emit_was_return_value,
836 emit_cpy_get_stack_size,
837 emit_cpy_set_stack_size,
838
839 emit_cpy_label_new,
840 emit_cpy_label_assign,
841 emit_cpy_import_name,
842 emit_cpy_import_from,
843 emit_cpy_import_star,
844 emit_cpy_load_const_tok,
845 emit_cpy_load_const_small_int,
846 emit_cpy_load_const_int,
847 emit_cpy_load_const_dec,
848 emit_cpy_load_const_id,
849 emit_cpy_load_const_str,
850 emit_cpy_load_const_verbatim_start,
851 emit_cpy_load_const_verbatim_int,
852 emit_cpy_load_const_verbatim_str,
853 emit_cpy_load_const_verbatim_strn,
854 emit_cpy_load_const_verbatim_quoted_str,
855 emit_cpy_load_const_verbatim_end,
856 emit_cpy_load_fast,
857 emit_cpy_load_name,
858 emit_cpy_load_global,
859 emit_cpy_load_deref,
860 emit_cpy_load_closure,
861 emit_cpy_load_attr,
862 emit_cpy_load_method,
863 emit_cpy_load_build_class,
864 emit_cpy_store_fast,
865 emit_cpy_store_name,
866 emit_cpy_store_global,
867 emit_cpy_store_deref,
868 emit_cpy_store_attr,
869 emit_cpy_store_locals,
870 emit_cpy_store_subscr,
871 emit_cpy_delete_fast,
872 emit_cpy_delete_name,
873 emit_cpy_delete_global,
874 emit_cpy_delete_deref,
875 emit_cpy_delete_attr,
876 emit_cpy_delete_subscr,
877 emit_cpy_dup_top,
878 emit_cpy_dup_top_two,
879 emit_cpy_pop_top,
880 emit_cpy_rot_two,
881 emit_cpy_rot_three,
882 emit_cpy_jump,
883 emit_cpy_pop_jump_if_true,
884 emit_cpy_pop_jump_if_false,
885 emit_cpy_jump_if_true_or_pop,
886 emit_cpy_jump_if_false_or_pop,
887 emit_cpy_setup_loop,
888 emit_cpy_break_loop,
889 emit_cpy_continue_loop,
890 emit_cpy_setup_with,
891 emit_cpy_with_cleanup,
892 emit_cpy_setup_except,
893 emit_cpy_setup_finally,
894 emit_cpy_end_finally,
895 emit_cpy_get_iter,
896 emit_cpy_for_iter,
897 emit_cpy_for_iter_end,
898 emit_cpy_pop_block,
899 emit_cpy_pop_except,
900 emit_cpy_unary_op,
901 emit_cpy_binary_op,
902 emit_cpy_compare_op,
903 emit_cpy_build_tuple,
904 emit_cpy_build_list,
905 emit_cpy_list_append,
906 emit_cpy_build_map,
907 emit_cpy_store_map,
908 emit_cpy_map_add,
909 emit_cpy_build_set,
910 emit_cpy_set_add,
911 emit_cpy_build_slice,
912 emit_cpy_unpack_sequence,
913 emit_cpy_unpack_ex,
914 emit_cpy_make_function,
915 emit_cpy_make_closure,
916 emit_cpy_call_function,
917 emit_cpy_call_method,
918 emit_cpy_return_value,
919 emit_cpy_raise_varargs,
920 emit_cpy_yield_value,
921 emit_cpy_yield_from,
922};
923
924void emit_new_cpython(emit_t **emit_out, const emit_method_table_t **emit_method_table_out) {
925 emit_t *emit = m_new(emit_t, 1);
926 emit->max_num_labels = 0;
927 emit->label_offsets = NULL;
928
929 *emit_out = emit;
930 *emit_method_table_out = &emit_cpy_method_table;
931}
932
933#endif // EMIT_ENABLE_CPY