blob: 0a3149fcd5fa4f50fce609765a78026fe20c8a79 [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
Damienb05d7072013-10-05 13:37:10 +010028 uint max_num_labels;
Damien429d7192013-10-04 19:53:11 +010029 int *label_offsets;
30};
31
Damien4b03e772013-10-05 14:17:09 +010032// forward declarations
33static const emit_method_table_t emit_cpy_method_table;
34static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes);
35
Damien415eb6f2013-10-05 12:19:06 +010036static void emit_cpy_set_native_types(emit_t *emit, bool do_native_types) {
Damien429d7192013-10-04 19:53:11 +010037}
38
Damien415eb6f2013-10-05 12:19:06 +010039static void emit_cpy_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien429d7192013-10-04 19:53:11 +010040 emit->pass = pass;
41 emit->next_label = 1;
42 emit->byte_code_offset = 0;
43 emit->stack_size = 0;
44 emit->last_emit_was_return_value = false;
45 emit->scope = scope;
Damienb05d7072013-10-05 13:37:10 +010046 if (pass == PASS_2) {
47 memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(int));
Damien429d7192013-10-04 19:53:11 +010048 }
49}
50
Damien415eb6f2013-10-05 12:19:06 +010051static void emit_cpy_end_pass(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010052 // check stack is back to zero size
53 if (emit->stack_size != 0) {
54 printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
55 }
Damien429d7192013-10-04 19:53:11 +010056}
57
Damien415eb6f2013-10-05 12:19:06 +010058static bool emit_cpy_last_emit_was_return_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010059 return emit->last_emit_was_return_value;
60}
61
Damien415eb6f2013-10-05 12:19:06 +010062static int emit_cpy_get_stack_size(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010063 return emit->stack_size;
64}
65
Damien415eb6f2013-10-05 12:19:06 +010066static void emit_cpy_set_stack_size(emit_t *emit, int size) {
Damien429d7192013-10-04 19:53:11 +010067 emit->stack_size = size;
68}
69
Damien4b03e772013-10-05 14:17:09 +010070static void emit_cpy_load_id(emit_t *emit, qstr qstr) {
71 emit_common_load_id(emit, &emit_cpy_method_table, emit->scope, qstr);
72}
73
74static void emit_cpy_store_id(emit_t *emit, qstr qstr) {
75 emit_common_store_id(emit, &emit_cpy_method_table, emit->scope, qstr);
76}
77
78static void emit_cpy_delete_id(emit_t *emit, qstr qstr) {
79 emit_common_delete_id(emit, &emit_cpy_method_table, emit->scope, qstr);
80}
81
Damien415eb6f2013-10-05 12:19:06 +010082static void emit_pre(emit_t *emit, int stack_size_delta, int byte_code_size) {
Damien429d7192013-10-04 19:53:11 +010083 emit->stack_size += stack_size_delta;
Damienb05d7072013-10-05 13:37:10 +010084 if (emit->stack_size > emit->scope->stack_size) {
Damien429d7192013-10-04 19:53:11 +010085 emit->scope->stack_size = emit->stack_size;
86 }
87 emit->last_emit_was_return_value = false;
88 if (emit->pass == PASS_3 && byte_code_size > 0) {
89 if (emit->byte_code_offset >= 1000) {
90 printf("%d ", emit->byte_code_offset);
91 } else {
92 printf("% 4d ", emit->byte_code_offset);
93 }
94 }
95 emit->byte_code_offset += byte_code_size;
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);
Damienb05d7072013-10-05 13:37:10 +0100100 assert(l < emit->max_num_labels);
101 if (emit->pass == PASS_2) {
102 // assign label offset
103 assert(emit->label_offsets[l] == -1);
104 emit->label_offsets[l] = emit->byte_code_offset;
105 } else if (emit->pass == PASS_3) {
106 // ensure label offset has not changed from PASS_2 to PASS_3
107 assert(emit->label_offsets[l] == emit->byte_code_offset);
108 //printf("l%d: (at %d)\n", l, emit->byte_code_offset);
Damien429d7192013-10-04 19:53:11 +0100109 }
110}
111
Damien415eb6f2013-10-05 12:19:06 +0100112static void emit_cpy_import_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100113 emit_pre(emit, -1, 3);
114 if (emit->pass == PASS_3) {
115 printf("IMPORT_NAME %s\n", qstr_str(qstr));
116 }
117}
118
Damien415eb6f2013-10-05 12:19:06 +0100119static void emit_cpy_import_from(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100120 emit_pre(emit, 1, 3);
121 if (emit->pass == PASS_3) {
122 printf("IMPORT_FROM %s\n", qstr_str(qstr));
123 }
124}
125
Damien415eb6f2013-10-05 12:19:06 +0100126static void emit_cpy_import_star(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100127 emit_pre(emit, -1, 1);
128 if (emit->pass == PASS_3) {
129 printf("IMPORT_STAR\n");
130 }
131}
132
Damien415eb6f2013-10-05 12:19:06 +0100133static void emit_cpy_load_const_tok(emit_t *emit, py_token_kind_t tok) {
Damien429d7192013-10-04 19:53:11 +0100134 emit_pre(emit, 1, 3);
135 if (emit->pass == PASS_3) {
136 printf("LOAD_CONST ");
137 switch (tok) {
138 case PY_TOKEN_KW_FALSE: printf("False"); break;
139 case PY_TOKEN_KW_NONE: printf("None"); break;
140 case PY_TOKEN_KW_TRUE: printf("True"); break;
141 default: printf("?=%d\n", tok); return; assert(0);
142 }
143 printf("\n");
144 }
145}
146
Damien415eb6f2013-10-05 12:19:06 +0100147static void emit_cpy_load_const_small_int(emit_t *emit, int arg) {
Damien429d7192013-10-04 19:53:11 +0100148 emit_pre(emit, 1, 3);
149 if (emit->pass == PASS_3) {
150 printf("LOAD_CONST %d\n", arg);
151 }
152}
153
Damien415eb6f2013-10-05 12:19:06 +0100154static void emit_cpy_load_const_int(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100155 emit_pre(emit, 1, 3);
156 if (emit->pass == PASS_3) {
157 printf("LOAD_CONST %s\n", qstr_str(qstr));
158 }
159}
160
Damien415eb6f2013-10-05 12:19:06 +0100161static void emit_cpy_load_const_dec(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100162 emit_pre(emit, 1, 3);
163 if (emit->pass == PASS_3) {
164 printf("LOAD_CONST %s\n", qstr_str(qstr));
165 }
166}
167
Damien415eb6f2013-10-05 12:19:06 +0100168static void emit_cpy_load_const_id(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100169 emit_pre(emit, 1, 3);
170 if (emit->pass == PASS_3) {
171 printf("LOAD_CONST '%s'\n", qstr_str(qstr));
172 }
173}
174
Damien415eb6f2013-10-05 12:19:06 +0100175static void emit_cpy_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien429d7192013-10-04 19:53:11 +0100176 emit_pre(emit, 1, 3);
177 if (emit->pass == PASS_3) {
178 printf("LOAD_CONST ");
Damien415eb6f2013-10-05 12:19:06 +0100179 emit_cpy_load_const_verbatim_quoted_str(emit, qstr, bytes);
Damien429d7192013-10-04 19:53:11 +0100180 printf("\n");
181 }
182}
183
Damien415eb6f2013-10-05 12:19:06 +0100184static void emit_cpy_load_const_verbatim_start(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100185 emit_pre(emit, 1, 3);
186 if (emit->pass == PASS_3) {
187 printf("LOAD_CONST ");
188 }
189}
190
Damien415eb6f2013-10-05 12:19:06 +0100191static void emit_cpy_load_const_verbatim_int(emit_t *emit, int val) {
Damien429d7192013-10-04 19:53:11 +0100192 if (emit->pass == PASS_3) {
193 printf("%d", val);
194 }
195}
196
Damien415eb6f2013-10-05 12:19:06 +0100197static void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) {
Damien429d7192013-10-04 19:53:11 +0100198 if (emit->pass == PASS_3) {
199 printf("%s", str);
200 }
201}
202
Damien415eb6f2013-10-05 12:19:06 +0100203static void emit_cpy_load_const_verbatim_strn(emit_t *emit, const char *str, int len) {
Damien429d7192013-10-04 19:53:11 +0100204 if (emit->pass == PASS_3) {
205 printf("%.*s", len, str);
206 }
207}
208
Damien415eb6f2013-10-05 12:19:06 +0100209static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes) {
Damien429d7192013-10-04 19:53:11 +0100210 // TODO strings should be escaped before we get here
211 if (emit->pass == PASS_3) {
212 const char *str = qstr_str(qstr);
213 int len = strlen(str);
214 bool has_single_quote = false;
215 bool has_double_quote = false;
216 for (int i = 0; i < len; i++) {
217 if (str[i] == '\'') {
218 has_single_quote = true;
219 } else if (str[i] == '"') {
220 has_double_quote = true;
221 }
222 }
223 if (bytes) {
224 printf("b");
225 }
226 bool quote_single = false;
227 if (has_single_quote && !has_double_quote) {
228 printf("\"");
229 } else {
230 quote_single = true;
231 printf("'");
232 }
233 for (int i = 0; i < len; i++) {
234 if (str[i] == '\n') {
235 printf("\\n");
236 } else if (str[i] == '\\' && str[i + 1] == '\'') {
237 i += 1;
238 if (quote_single) {
239 printf("\\'");
240 } else {
241 printf("'");
242 }
243 } else if (str[i] == '\'' && quote_single) {
244 printf("\\'");
245 } else {
246 printf("%c", str[i]);
247 }
248 }
249 if (has_single_quote && !has_double_quote) {
250 printf("\"");
251 } else {
252 printf("'");
253 }
254 }
255}
256
Damien415eb6f2013-10-05 12:19:06 +0100257static void emit_cpy_load_const_verbatim_end(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100258 if (emit->pass == PASS_3) {
259 printf("\n");
260 }
261}
262
Damien415eb6f2013-10-05 12:19:06 +0100263static void emit_cpy_load_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100264 emit_pre(emit, 1, 3);
265 if (emit->pass == PASS_3) {
266 printf("LOAD_NAME %s\n", qstr_str(qstr));
267 }
268}
269
Damien415eb6f2013-10-05 12:19:06 +0100270static void emit_cpy_load_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100271 emit_pre(emit, 1, 3);
272 if (emit->pass == PASS_3) {
273 printf("LOAD_GLOBAL %s\n", qstr_str(qstr));
274 }
275}
276
Damien415eb6f2013-10-05 12:19:06 +0100277static void emit_cpy_load_fast(emit_t *emit, qstr qstr, int local_num) {
Damien429d7192013-10-04 19:53:11 +0100278 emit_pre(emit, 1, 3);
279 if (emit->pass == PASS_3) {
280 printf("LOAD_FAST %s\n", qstr_str(qstr));
281 }
282}
283
Damien415eb6f2013-10-05 12:19:06 +0100284static void emit_cpy_load_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100285 emit_pre(emit, 1, 3);
286 if (emit->pass == PASS_3) {
287 printf("LOAD_DEREF %s\n", qstr_str(qstr));
288 }
289}
290
Damien415eb6f2013-10-05 12:19:06 +0100291static void emit_cpy_load_closure(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100292 emit_pre(emit, 1, 3);
293 if (emit->pass == PASS_3) {
294 printf("LOAD_CLOSURE %s\n", qstr_str(qstr));
295 }
296}
297
Damien415eb6f2013-10-05 12:19:06 +0100298static void emit_cpy_load_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100299 emit_pre(emit, 0, 3);
300 if (emit->pass == PASS_3) {
301 printf("LOAD_ATTR %s\n", qstr_str(qstr));
302 }
303}
304
Damien415eb6f2013-10-05 12:19:06 +0100305static void emit_cpy_load_method(emit_t *emit, qstr qstr) {
306 emit_cpy_load_attr(emit, qstr);
Damien429d7192013-10-04 19:53:11 +0100307}
308
Damien415eb6f2013-10-05 12:19:06 +0100309static void emit_cpy_load_build_class(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100310 emit_pre(emit, 1, 1);
311 if (emit->pass == PASS_3) {
312 printf("LOAD_BUILD_CLASS\n");
313 }
314}
315
Damien415eb6f2013-10-05 12:19:06 +0100316static void emit_cpy_store_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100317 emit_pre(emit, -1, 3);
318 if (emit->pass == PASS_3) {
319 printf("STORE_NAME %s\n", qstr_str(qstr));
320 }
321}
322
Damien415eb6f2013-10-05 12:19:06 +0100323static void emit_cpy_store_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100324 emit_pre(emit, -1, 3);
325 if (emit->pass == PASS_3) {
326 printf("STORE_GLOBAL %s\n", qstr_str(qstr));
327 }
328}
329
Damien415eb6f2013-10-05 12:19:06 +0100330static void emit_cpy_store_fast(emit_t *emit, qstr qstr, int local_num) {
Damien429d7192013-10-04 19:53:11 +0100331 emit_pre(emit, -1, 3);
332 if (emit->pass == PASS_3) {
333 printf("STORE_FAST %s\n", qstr_str(qstr));
334 }
335}
336
Damien415eb6f2013-10-05 12:19:06 +0100337static void emit_cpy_store_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100338 emit_pre(emit, -1, 3);
339 if (emit->pass == PASS_3) {
340 printf("STORE_DEREF %s\n", qstr_str(qstr));
341 }
342}
343
Damien415eb6f2013-10-05 12:19:06 +0100344static void emit_cpy_store_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100345 emit_pre(emit, -2, 3);
346 if (emit->pass == PASS_3) {
347 printf("STORE_ATTR %s\n", qstr_str(qstr));
348 }
349}
350
Damien415eb6f2013-10-05 12:19:06 +0100351static void emit_cpy_store_locals(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100352 emit_pre(emit, -1, 1);
353 if (emit->pass == PASS_3) {
354 printf("STORE_LOCALS\n");
355 }
356}
357
Damien415eb6f2013-10-05 12:19:06 +0100358static void emit_cpy_store_subscr(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100359 emit_pre(emit, -3, 1);
360 if (emit->pass == PASS_3) {
361 printf("STORE_SUBSCR\n");
362 }
363}
364
Damien415eb6f2013-10-05 12:19:06 +0100365static void emit_cpy_delete_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100366 emit_pre(emit, 0, 3);
367 if (emit->pass == PASS_3) {
368 printf("DELETE_NAME %s\n", qstr_str(qstr));
369 }
370}
371
Damien415eb6f2013-10-05 12:19:06 +0100372static void emit_cpy_delete_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100373 emit_pre(emit, 0, 3);
374 if (emit->pass == PASS_3) {
375 printf("DELETE_GLOBAL %s\n", qstr_str(qstr));
376 }
377}
378
Damien415eb6f2013-10-05 12:19:06 +0100379static void emit_cpy_delete_fast(emit_t *emit, qstr qstr, int local_num) {
Damien429d7192013-10-04 19:53:11 +0100380 emit_pre(emit, 0, 3);
381 if (emit->pass == PASS_3) {
382 printf("DELETE_FAST %s\n", qstr_str(qstr));
383 }
384}
385
Damien415eb6f2013-10-05 12:19:06 +0100386static void emit_cpy_delete_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100387 emit_pre(emit, 0, 3);
388 if (emit->pass == PASS_3) {
389 printf("DELETE_DEREF %s\n", qstr_str(qstr));
390 }
391}
392
Damien415eb6f2013-10-05 12:19:06 +0100393static void emit_cpy_delete_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100394 emit_pre(emit, -1, 3);
395 if (emit->pass == PASS_3) {
396 printf("DELETE_ATTR %s\n", qstr_str(qstr));
397 }
398}
399
Damien415eb6f2013-10-05 12:19:06 +0100400static void emit_cpy_delete_subscr(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100401 emit_pre(emit, -2, 1);
402 if (emit->pass == PASS_3) {
403 printf("DELETE_SUBSCR\n");
404 }
405}
406
Damien415eb6f2013-10-05 12:19:06 +0100407static void emit_cpy_dup_top(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100408 emit_pre(emit, 1, 1);
409 if (emit->pass == PASS_3) {
410 printf("DUP_TOP\n");
411 }
412}
413
Damien415eb6f2013-10-05 12:19:06 +0100414static void emit_cpy_dup_top_two(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100415 emit_pre(emit, 2, 1);
416 if (emit->pass == PASS_3) {
417 printf("DUP_TOP_TWO\n");
418 }
419}
420
Damien415eb6f2013-10-05 12:19:06 +0100421static void emit_cpy_pop_top(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100422 emit_pre(emit, -1, 1);
423 if (emit->pass == PASS_3) {
424 printf("POP_TOP\n");
425 }
426}
427
Damien415eb6f2013-10-05 12:19:06 +0100428static void emit_cpy_rot_two(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100429 emit_pre(emit, 0, 1);
430 if (emit->pass == PASS_3) {
431 printf("ROT_TWO\n");
432 }
433}
434
Damien415eb6f2013-10-05 12:19:06 +0100435static void emit_cpy_rot_three(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100436 emit_pre(emit, 0, 1);
437 if (emit->pass == PASS_3) {
438 printf("ROT_THREE\n");
439 }
440}
441
Damien415eb6f2013-10-05 12:19:06 +0100442static void emit_cpy_jump(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100443 emit_pre(emit, 0, 3);
444 if (emit->pass == PASS_3) {
445 int dest = emit->label_offsets[label];
446 if (dest < emit->byte_code_offset) {
447 printf("JUMP_ABSOLUTE %d\n", emit->label_offsets[label]);
448 } else {
449 printf("JUMP_FORWARD %d\n", emit->label_offsets[label]);
450 }
451 }
452}
453
Damien415eb6f2013-10-05 12:19:06 +0100454static void emit_cpy_pop_jump_if_true(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100455 emit_pre(emit, -1, 3);
456 if (emit->pass == PASS_3) {
457 printf("POP_JUMP_IF_TRUE %d\n", emit->label_offsets[label]);
458 }
459}
460
Damien415eb6f2013-10-05 12:19:06 +0100461static void emit_cpy_pop_jump_if_false(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100462 emit_pre(emit, -1, 3);
463 if (emit->pass == PASS_3) {
464 printf("POP_JUMP_IF_FALSE %d\n", emit->label_offsets[label]);
465 }
466}
467
Damien415eb6f2013-10-05 12:19:06 +0100468static void emit_cpy_jump_if_true_or_pop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100469 emit_pre(emit, -1, 3);
470 if (emit->pass == PASS_3) {
471 printf("JUMP_IF_TRUE_OR_POP %d\n", emit->label_offsets[label]);
472 }
473}
474
Damien415eb6f2013-10-05 12:19:06 +0100475static void emit_cpy_jump_if_false_or_pop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100476 emit_pre(emit, -1, 3);
477 if (emit->pass == PASS_3) {
478 printf("JUMP_IF_FALSE_OR_POP %d\n", emit->label_offsets[label]);
479 }
480}
481
Damien415eb6f2013-10-05 12:19:06 +0100482static void emit_cpy_setup_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100483 emit_pre(emit, 0, 3);
484 if (emit->pass == PASS_3) {
485 printf("SETUP_LOOP %d\n", emit->label_offsets[label]);
486 }
487}
488
Damien415eb6f2013-10-05 12:19:06 +0100489static void emit_cpy_break_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100490 emit_pre(emit, 0, 1);
491 if (emit->pass == PASS_3) {
492 printf("BREAK_LOOP\n"); // CPython doesn't have label
493 //printf("BREAK_LOOP %d\n", emit->label_offsets[label]);
494 }
495}
496
Damien415eb6f2013-10-05 12:19:06 +0100497static void emit_cpy_continue_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100498 emit_pre(emit, 0, 3);
499 if (emit->pass == PASS_3) {
500 printf("CONTINUE_LOOP %d\n", emit->label_offsets[label]);
501 }
502}
503
Damien415eb6f2013-10-05 12:19:06 +0100504static void emit_cpy_setup_with(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100505 emit_pre(emit, 7, 3);
506 if (emit->pass == PASS_3) {
507 printf("SETUP_WITH %d\n", emit->label_offsets[label]);
508 }
509}
510
Damien415eb6f2013-10-05 12:19:06 +0100511static void emit_cpy_with_cleanup(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100512 emit_pre(emit, -7, 1);
513 if (emit->pass == PASS_3) {
514 printf("WITH_CLEANUP\n");
515 }
516}
517
Damien415eb6f2013-10-05 12:19:06 +0100518static void emit_cpy_setup_except(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100519 emit_pre(emit, 6, 3);
520 if (emit->pass == PASS_3) {
521 printf("SETUP_EXCEPT %d\n", emit->label_offsets[label]);
522 }
523}
524
Damien415eb6f2013-10-05 12:19:06 +0100525static void emit_cpy_setup_finally(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100526 emit_pre(emit, 6, 3);
527 if (emit->pass == PASS_3) {
528 printf("SETUP_FINALLY %d\n", emit->label_offsets[label]);
529 }
530}
531
Damien415eb6f2013-10-05 12:19:06 +0100532static void emit_cpy_end_finally(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100533 emit_pre(emit, -1, 1);
534 if (emit->pass == PASS_3) {
535 printf("END_FINALLY\n");
536 }
537}
538
Damien415eb6f2013-10-05 12:19:06 +0100539static void emit_cpy_get_iter(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100540 emit_pre(emit, 0, 1);
541 if (emit->pass == PASS_3) {
542 printf("GET_ITER\n");
543 }
544}
545
Damien415eb6f2013-10-05 12:19:06 +0100546static void emit_cpy_for_iter(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100547 emit_pre(emit, 1, 3);
548 if (emit->pass == PASS_3) {
549 printf("FOR_ITER %d\n", emit->label_offsets[label]);
550 }
551}
552
Damien415eb6f2013-10-05 12:19:06 +0100553static void emit_cpy_for_iter_end(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100554 emit_pre(emit, -1, 0);
555}
556
Damien415eb6f2013-10-05 12:19:06 +0100557static void emit_cpy_pop_block(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100558 emit_pre(emit, 0, 1);
559 if (emit->pass == PASS_3) {
560 printf("POP_BLOCK\n");
561 }
562}
563
Damien415eb6f2013-10-05 12:19:06 +0100564static void emit_cpy_pop_except(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100565 emit_pre(emit, 0, 1);
566 if (emit->pass == PASS_3) {
567 printf("POP_EXCEPT\n");
568 }
569}
570
Damien415eb6f2013-10-05 12:19:06 +0100571static void emit_cpy_unary_op(emit_t *emit, rt_unary_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100572 emit_pre(emit, 0, 1);
573 if (emit->pass == PASS_3) {
574 switch (op) {
575 case RT_UNARY_OP_NOT: printf("UNARY_NOT\n"); break;
576 case RT_UNARY_OP_POSITIVE: printf("UNARY_POSITIVE\n"); break;
577 case RT_UNARY_OP_NEGATIVE: printf("UNARY_NEGATIVE\n"); break;
578 case RT_UNARY_OP_INVERT: printf("UNARY_INVERT\n"); break;
579 default: assert(0);
580 }
581 }
582}
583
Damien415eb6f2013-10-05 12:19:06 +0100584static void emit_cpy_binary_op(emit_t *emit, rt_binary_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100585 emit_pre(emit, -1, 1);
586 if (emit->pass == PASS_3) {
587 switch (op) {
588 case RT_BINARY_OP_SUBSCR: printf("BINARY_SUBSCR\n"); break;
589 case RT_BINARY_OP_OR: printf("BINARY_OR\n"); break;
590 case RT_BINARY_OP_XOR: printf("BINARY_XOR\n"); break;
591 case RT_BINARY_OP_AND: printf("BINARY_AND\n"); break;
592 case RT_BINARY_OP_LSHIFT: printf("BINARY_LSHIFT\n"); break;
593 case RT_BINARY_OP_RSHIFT: printf("BINARY_RSHIFT\n"); break;
594 case RT_BINARY_OP_ADD: printf("BINARY_ADD\n"); break;
595 case RT_BINARY_OP_SUBTRACT: printf("BINARY_SUBTRACT\n"); break;
596 case RT_BINARY_OP_MULTIPLY: printf("BINARY_MULTIPLY\n"); break;
597 case RT_BINARY_OP_FLOOR_DIVIDE: printf("BINARY_FLOOR_DIVIDE\n"); break;
598 case RT_BINARY_OP_TRUE_DIVIDE: printf("BINARY_TRUE_DIVIDE\n"); break;
599 case RT_BINARY_OP_MODULO: printf("BINARY_MODULO\n"); break;
600 case RT_BINARY_OP_POWER: printf("BINARY_POWER\n"); break;
601 case RT_BINARY_OP_INPLACE_OR: printf("INPLACE_OR\n"); break;
602 case RT_BINARY_OP_INPLACE_XOR: printf("INPLACE_XOR\n"); break;
603 case RT_BINARY_OP_INPLACE_AND: printf("INPLACE_AND\n"); break;
604 case RT_BINARY_OP_INPLACE_LSHIFT: printf("INPLACE_LSHIFT\n"); break;
605 case RT_BINARY_OP_INPLACE_RSHIFT: printf("INPLACE_RSHIFT\n"); break;
606 case RT_BINARY_OP_INPLACE_ADD: printf("INPLACE_ADD\n"); break;
607 case RT_BINARY_OP_INPLACE_SUBTRACT: printf("INPLACE_SUBTRACT\n"); break;
608 case RT_BINARY_OP_INPLACE_MULTIPLY: printf("INPLACE_MULTIPLY\n"); break;
609 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: printf("INPLACE_FLOOR_DIVIDE\n"); break;
610 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: printf("INPLACE_TRUE_DIVIDE\n"); break;
611 case RT_BINARY_OP_INPLACE_MODULO: printf("INPLACE_MODULO\n"); break;
612 case RT_BINARY_OP_INPLACE_POWER: printf("INPLACE_POWER\n"); break;
613 default: assert(0);
614 }
615 }
616}
617
Damien415eb6f2013-10-05 12:19:06 +0100618static void emit_cpy_compare_op(emit_t *emit, rt_compare_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100619 emit_pre(emit, -1, 3);
620 if (emit->pass == PASS_3) {
621 switch (op) {
622 case RT_COMPARE_OP_LESS: printf("COMPARE_OP <\n"); break;
623 case RT_COMPARE_OP_MORE: printf("COMPARE_OP >\n"); break;
624 case RT_COMPARE_OP_EQUAL: printf("COMPARE_OP ==\n"); break;
625 case RT_COMPARE_OP_LESS_EQUAL: printf("COMPARE_OP <=\n"); break;
626 case RT_COMPARE_OP_MORE_EQUAL: printf("COMPARE_OP >=\n"); break;
627 case RT_COMPARE_OP_NOT_EQUAL: printf("COMPARE_OP !=\n"); break;
628 case RT_COMPARE_OP_IN: printf("COMPARE_OP in\n"); break;
629 case RT_COMPARE_OP_NOT_IN: printf("COMPARE_OP not in\n"); break;
630 case RT_COMPARE_OP_IS: printf("COMPARE_OP is\n"); break;
631 case RT_COMPARE_OP_IS_NOT: printf("COMPARE_OP is not\n"); break;
632 case RT_COMPARE_OP_EXCEPTION_MATCH: printf("COMPARE_OP exception match\n"); break;
633 default: assert(0);
634 }
635 }
636}
637
Damien415eb6f2013-10-05 12:19:06 +0100638static void emit_cpy_build_tuple(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100639 emit_pre(emit, 1 - n_args, 3);
640 if (emit->pass == PASS_3) {
641 printf("BUILD_TUPLE %d\n", n_args);
642 }
643}
644
Damien415eb6f2013-10-05 12:19:06 +0100645static void emit_cpy_build_list(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100646 emit_pre(emit, 1 - n_args, 3);
647 if (emit->pass == PASS_3) {
648 printf("BUILD_LIST %d\n", n_args);
649 }
650}
651
Damien415eb6f2013-10-05 12:19:06 +0100652static void emit_cpy_list_append(emit_t *emit, int list_index) {
Damien429d7192013-10-04 19:53:11 +0100653 emit_pre(emit, -1, 3);
654 if (emit->pass == PASS_3) {
655 printf("LIST_APPEND %d\n", list_index);
656 }
657}
658
Damien415eb6f2013-10-05 12:19:06 +0100659static void emit_cpy_build_map(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100660 emit_pre(emit, 1, 3);
661 if (emit->pass == PASS_3) {
662 printf("BUILD_MAP %d\n", n_args);
663 }
664}
665
Damien415eb6f2013-10-05 12:19:06 +0100666static void emit_cpy_store_map(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100667 emit_pre(emit, -2, 1);
668 if (emit->pass == PASS_3) {
669 printf("STORE_MAP\n");
670 }
671}
672
Damien415eb6f2013-10-05 12:19:06 +0100673static void emit_cpy_map_add(emit_t *emit, int map_index) {
Damien429d7192013-10-04 19:53:11 +0100674 emit_pre(emit, -2, 3);
675 if (emit->pass == PASS_3) {
676 printf("MAP_ADD %d\n", map_index);
677 }
678}
679
Damien415eb6f2013-10-05 12:19:06 +0100680static void emit_cpy_build_set(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100681 emit_pre(emit, 1 - n_args, 3);
682 if (emit->pass == PASS_3) {
683 printf("BUILD_SET %d\n", n_args);
684 }
685}
686
Damien415eb6f2013-10-05 12:19:06 +0100687static void emit_cpy_set_add(emit_t *emit, int set_index) {
Damien429d7192013-10-04 19:53:11 +0100688 emit_pre(emit, -1, 3);
689 if (emit->pass == PASS_3) {
690 printf("SET_ADD %d\n", set_index);
691 }
692}
693
Damien415eb6f2013-10-05 12:19:06 +0100694static void emit_cpy_build_slice(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100695 emit_pre(emit, 1 - n_args, 3);
696 if (emit->pass == PASS_3) {
697 printf("BUILD_SLICE %d\n", n_args);
698 }
699}
700
Damien415eb6f2013-10-05 12:19:06 +0100701static void emit_cpy_unpack_sequence(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100702 emit_pre(emit, -1 + n_args, 3);
703 if (emit->pass == PASS_3) {
704 printf("UNPACK_SEQUENCE %d\n", n_args);
705 }
706}
707
Damien415eb6f2013-10-05 12:19:06 +0100708static void emit_cpy_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien429d7192013-10-04 19:53:11 +0100709 emit_pre(emit, -1 + n_left + n_right + 1, 3);
710 if (emit->pass == PASS_3) {
711 printf("UNPACK_EX %d\n", n_left | (n_right << 8));
712 }
713}
714
Damien415eb6f2013-10-05 12:19:06 +0100715static 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 +0100716 int s = 0;
717 if (have_star_arg) {
718 s += 1;
719 }
720 if (have_dbl_star_arg) {
721 s += 1;
722 }
723 emit_pre(emit, -n_positional - 2 * n_keyword - s, 3);
724 if (emit->pass == PASS_3) {
725 if (have_star_arg) {
726 if (have_dbl_star_arg) {
727 printf("CALL_FUNCTION_VAR_KW");
728 } else {
729 printf("CALL_FUNCTION_VAR");
730 }
731 } else {
732 if (have_dbl_star_arg) {
733 printf("CALL_FUNCTION_KW");
734 } else {
735 printf("CALL_FUNCTION");
736 }
737 }
738 printf(" %d, %d\n", n_positional, n_keyword);
739 }
740}
741
Damien415eb6f2013-10-05 12:19:06 +0100742static void emit_cpy_call_method(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
743 emit_cpy_call_function(emit, n_positional, n_keyword, have_star_arg, have_dbl_star_arg);
Damien429d7192013-10-04 19:53:11 +0100744}
745
Damien415eb6f2013-10-05 12:19:06 +0100746static void emit_cpy_return_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100747 emit_pre(emit, -1, 1);
748 emit->last_emit_was_return_value = true;
749 if (emit->pass == PASS_3) {
750 printf("RETURN_VALUE\n");
751 }
752}
753
Damien415eb6f2013-10-05 12:19:06 +0100754static void emit_cpy_raise_varargs(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100755 emit_pre(emit, -n_args, 3);
756 if (emit->pass == PASS_3) {
757 printf("RAISE_VARARGS %d\n", n_args);
758 }
759}
760
Damien415eb6f2013-10-05 12:19:06 +0100761static void load_cpy_const_code_and_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100762 emit_pre(emit, 1, 3);
763 if (emit->pass == PASS_3) {
764 printf("LOAD_CONST code %s\n", qstr_str(qstr));
765 }
766 // load qualified name
767 emit_pre(emit, 1, 3);
768 if (emit->pass == PASS_3) {
769 printf("LOAD_CONST '");
770 // code just to work out the qualname (or whatever it is)
771 {
772 int depth = 0;
773 for (scope_t *s = emit->scope; s->parent != NULL; s = s->parent) {
774 depth += 1;
775 }
776 for (int wanted_depth = depth; wanted_depth >= 0; wanted_depth--) {
777 scope_t *s = emit->scope;
778 for (int i = 0; i < wanted_depth; i++) {
779 s = s->parent;
780 }
781 if (s->kind == SCOPE_FUNCTION) {
782 printf("%s.<locals>.", qstr_str(s->simple_name));
783 } else if (s->kind == SCOPE_CLASS) {
784 printf("%s.", qstr_str(s->simple_name));
785 }
786 }
787 }
788 printf("%s'\n", qstr_str(qstr));
789 }
790}
791
Damien415eb6f2013-10-05 12:19:06 +0100792static void emit_cpy_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
793 load_cpy_const_code_and_name(emit, scope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100794 emit_pre(emit, -1 - n_default_params - 2 * n_dict_params, 3);
795 if (emit->pass == PASS_3) {
796 printf("MAKE_FUNCTION %d\n", (n_dict_params << 8) | n_default_params);
797 }
798}
799
Damien415eb6f2013-10-05 12:19:06 +0100800static void emit_cpy_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
801 load_cpy_const_code_and_name(emit, scope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100802 emit_pre(emit, -2 - n_default_params - 2 * n_dict_params, 3);
803 if (emit->pass == PASS_3) {
804 printf("MAKE_CLOSURE %d\n", (n_dict_params << 8) | n_default_params);
805 }
806}
807
Damien415eb6f2013-10-05 12:19:06 +0100808static void emit_cpy_yield_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100809 emit_pre(emit, 0, 1);
810 if (emit->pass == PASS_2) {
811 emit->scope->flags |= SCOPE_FLAG_GENERATOR;
812 }
813 if (emit->pass == PASS_3) {
814 printf("YIELD_VALUE\n");
815 }
816}
817
Damien415eb6f2013-10-05 12:19:06 +0100818static void emit_cpy_yield_from(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100819 emit_pre(emit, -1, 1);
820 if (emit->pass == PASS_2) {
821 emit->scope->flags |= SCOPE_FLAG_GENERATOR;
822 }
823 if (emit->pass == PASS_3) {
824 printf("YIELD_FROM\n");
825 }
826}
827
Damien415eb6f2013-10-05 12:19:06 +0100828static const emit_method_table_t emit_cpy_method_table = {
829 emit_cpy_set_native_types,
830 emit_cpy_start_pass,
831 emit_cpy_end_pass,
832 emit_cpy_last_emit_was_return_value,
833 emit_cpy_get_stack_size,
834 emit_cpy_set_stack_size,
835
Damien4b03e772013-10-05 14:17:09 +0100836 emit_cpy_load_id,
837 emit_cpy_store_id,
838 emit_cpy_delete_id,
839
Damien415eb6f2013-10-05 12:19:06 +0100840 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
Damienb05d7072013-10-05 13:37:10 +0100924void emit_cpython_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels) {
Damien415eb6f2013-10-05 12:19:06 +0100925 emit_t *emit = m_new(emit_t, 1);
Damienb05d7072013-10-05 13:37:10 +0100926 emit->max_num_labels = max_num_labels;
927 emit->label_offsets = m_new(int, max_num_labels);
Damien415eb6f2013-10-05 12:19:06 +0100928
929 *emit_out = emit;
930 *emit_method_table_out = &emit_cpy_method_table;
931}
932
933#endif // EMIT_ENABLE_CPY