blob: db5c1186736bff3a86134e82972cdf3e8d9bf475 [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
Damien6cdd3af2013-10-05 18:08:26 +010032// forward declaration
Damien4b03e772013-10-05 14:17:09 +010033static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes);
34
Damien6cdd3af2013-10-05 18:08:26 +010035emit_t *emit_cpython_new(uint max_num_labels) {
36 emit_t *emit = m_new(emit_t, 1);
37 emit->max_num_labels = max_num_labels;
38 emit->label_offsets = m_new(int, max_num_labels);
39 return emit;
40}
41
Damien415eb6f2013-10-05 12:19:06 +010042static void emit_cpy_set_native_types(emit_t *emit, bool do_native_types) {
Damien429d7192013-10-04 19:53:11 +010043}
44
Damien415eb6f2013-10-05 12:19:06 +010045static void emit_cpy_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
Damien429d7192013-10-04 19:53:11 +010046 emit->pass = pass;
47 emit->next_label = 1;
48 emit->byte_code_offset = 0;
49 emit->stack_size = 0;
50 emit->last_emit_was_return_value = false;
51 emit->scope = scope;
Damienb05d7072013-10-05 13:37:10 +010052 if (pass == PASS_2) {
53 memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(int));
Damien429d7192013-10-04 19:53:11 +010054 }
55}
56
Damien415eb6f2013-10-05 12:19:06 +010057static void emit_cpy_end_pass(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010058 // check stack is back to zero size
59 if (emit->stack_size != 0) {
60 printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
61 }
Damien429d7192013-10-04 19:53:11 +010062}
63
Damien415eb6f2013-10-05 12:19:06 +010064static bool emit_cpy_last_emit_was_return_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010065 return emit->last_emit_was_return_value;
66}
67
Damien415eb6f2013-10-05 12:19:06 +010068static int emit_cpy_get_stack_size(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +010069 return emit->stack_size;
70}
71
Damien415eb6f2013-10-05 12:19:06 +010072static void emit_cpy_set_stack_size(emit_t *emit, int size) {
Damien429d7192013-10-04 19:53:11 +010073 emit->stack_size = size;
74}
75
Damien4b03e772013-10-05 14:17:09 +010076static void emit_cpy_load_id(emit_t *emit, qstr qstr) {
Damien6cdd3af2013-10-05 18:08:26 +010077 emit_common_load_id(emit, &emit_cpython_method_table, emit->scope, qstr);
Damien4b03e772013-10-05 14:17:09 +010078}
79
80static void emit_cpy_store_id(emit_t *emit, qstr qstr) {
Damien6cdd3af2013-10-05 18:08:26 +010081 emit_common_store_id(emit, &emit_cpython_method_table, emit->scope, qstr);
Damien4b03e772013-10-05 14:17:09 +010082}
83
84static void emit_cpy_delete_id(emit_t *emit, qstr qstr) {
Damien6cdd3af2013-10-05 18:08:26 +010085 emit_common_delete_id(emit, &emit_cpython_method_table, emit->scope, qstr);
Damien4b03e772013-10-05 14:17:09 +010086}
87
Damien415eb6f2013-10-05 12:19:06 +010088static void emit_pre(emit_t *emit, int stack_size_delta, int byte_code_size) {
Damien429d7192013-10-04 19:53:11 +010089 emit->stack_size += stack_size_delta;
Damienb05d7072013-10-05 13:37:10 +010090 if (emit->stack_size > emit->scope->stack_size) {
Damien429d7192013-10-04 19:53:11 +010091 emit->scope->stack_size = emit->stack_size;
92 }
93 emit->last_emit_was_return_value = false;
94 if (emit->pass == PASS_3 && byte_code_size > 0) {
95 if (emit->byte_code_offset >= 1000) {
96 printf("%d ", emit->byte_code_offset);
97 } else {
98 printf("% 4d ", emit->byte_code_offset);
99 }
100 }
101 emit->byte_code_offset += byte_code_size;
102}
103
Damien415eb6f2013-10-05 12:19:06 +0100104static void emit_cpy_label_assign(emit_t *emit, int l) {
Damien429d7192013-10-04 19:53:11 +0100105 emit_pre(emit, 0, 0);
Damienb05d7072013-10-05 13:37:10 +0100106 assert(l < emit->max_num_labels);
107 if (emit->pass == PASS_2) {
108 // assign label offset
109 assert(emit->label_offsets[l] == -1);
110 emit->label_offsets[l] = emit->byte_code_offset;
111 } else if (emit->pass == PASS_3) {
112 // ensure label offset has not changed from PASS_2 to PASS_3
113 assert(emit->label_offsets[l] == emit->byte_code_offset);
114 //printf("l%d: (at %d)\n", l, emit->byte_code_offset);
Damien429d7192013-10-04 19:53:11 +0100115 }
116}
117
Damien415eb6f2013-10-05 12:19:06 +0100118static void emit_cpy_import_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100119 emit_pre(emit, -1, 3);
120 if (emit->pass == PASS_3) {
121 printf("IMPORT_NAME %s\n", qstr_str(qstr));
122 }
123}
124
Damien415eb6f2013-10-05 12:19:06 +0100125static void emit_cpy_import_from(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100126 emit_pre(emit, 1, 3);
127 if (emit->pass == PASS_3) {
128 printf("IMPORT_FROM %s\n", qstr_str(qstr));
129 }
130}
131
Damien415eb6f2013-10-05 12:19:06 +0100132static void emit_cpy_import_star(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100133 emit_pre(emit, -1, 1);
134 if (emit->pass == PASS_3) {
135 printf("IMPORT_STAR\n");
136 }
137}
138
Damien415eb6f2013-10-05 12:19:06 +0100139static void emit_cpy_load_const_tok(emit_t *emit, py_token_kind_t tok) {
Damien429d7192013-10-04 19:53:11 +0100140 emit_pre(emit, 1, 3);
141 if (emit->pass == PASS_3) {
142 printf("LOAD_CONST ");
143 switch (tok) {
144 case PY_TOKEN_KW_FALSE: printf("False"); break;
145 case PY_TOKEN_KW_NONE: printf("None"); break;
146 case PY_TOKEN_KW_TRUE: printf("True"); break;
147 default: printf("?=%d\n", tok); return; assert(0);
148 }
149 printf("\n");
150 }
151}
152
Damien415eb6f2013-10-05 12:19:06 +0100153static void emit_cpy_load_const_small_int(emit_t *emit, int arg) {
Damien429d7192013-10-04 19:53:11 +0100154 emit_pre(emit, 1, 3);
155 if (emit->pass == PASS_3) {
156 printf("LOAD_CONST %d\n", arg);
157 }
158}
159
Damien415eb6f2013-10-05 12:19:06 +0100160static void emit_cpy_load_const_int(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100161 emit_pre(emit, 1, 3);
162 if (emit->pass == PASS_3) {
163 printf("LOAD_CONST %s\n", qstr_str(qstr));
164 }
165}
166
Damien415eb6f2013-10-05 12:19:06 +0100167static void emit_cpy_load_const_dec(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100168 emit_pre(emit, 1, 3);
169 if (emit->pass == PASS_3) {
170 printf("LOAD_CONST %s\n", qstr_str(qstr));
171 }
172}
173
Damien415eb6f2013-10-05 12:19:06 +0100174static void emit_cpy_load_const_id(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100175 emit_pre(emit, 1, 3);
176 if (emit->pass == PASS_3) {
177 printf("LOAD_CONST '%s'\n", qstr_str(qstr));
178 }
179}
180
Damien415eb6f2013-10-05 12:19:06 +0100181static void emit_cpy_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
Damien429d7192013-10-04 19:53:11 +0100182 emit_pre(emit, 1, 3);
183 if (emit->pass == PASS_3) {
184 printf("LOAD_CONST ");
Damien415eb6f2013-10-05 12:19:06 +0100185 emit_cpy_load_const_verbatim_quoted_str(emit, qstr, bytes);
Damien429d7192013-10-04 19:53:11 +0100186 printf("\n");
187 }
188}
189
Damien415eb6f2013-10-05 12:19:06 +0100190static void emit_cpy_load_const_verbatim_start(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100191 emit_pre(emit, 1, 3);
192 if (emit->pass == PASS_3) {
193 printf("LOAD_CONST ");
194 }
195}
196
Damien415eb6f2013-10-05 12:19:06 +0100197static void emit_cpy_load_const_verbatim_int(emit_t *emit, int val) {
Damien429d7192013-10-04 19:53:11 +0100198 if (emit->pass == PASS_3) {
199 printf("%d", val);
200 }
201}
202
Damien415eb6f2013-10-05 12:19:06 +0100203static void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) {
Damien429d7192013-10-04 19:53:11 +0100204 if (emit->pass == PASS_3) {
205 printf("%s", str);
206 }
207}
208
Damien415eb6f2013-10-05 12:19:06 +0100209static void emit_cpy_load_const_verbatim_strn(emit_t *emit, const char *str, int len) {
Damien429d7192013-10-04 19:53:11 +0100210 if (emit->pass == PASS_3) {
211 printf("%.*s", len, str);
212 }
213}
214
Damien415eb6f2013-10-05 12:19:06 +0100215static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes) {
Damien429d7192013-10-04 19:53:11 +0100216 // TODO strings should be escaped before we get here
217 if (emit->pass == PASS_3) {
218 const char *str = qstr_str(qstr);
219 int len = strlen(str);
220 bool has_single_quote = false;
221 bool has_double_quote = false;
222 for (int i = 0; i < len; i++) {
223 if (str[i] == '\'') {
224 has_single_quote = true;
225 } else if (str[i] == '"') {
226 has_double_quote = true;
227 }
228 }
229 if (bytes) {
230 printf("b");
231 }
232 bool quote_single = false;
233 if (has_single_quote && !has_double_quote) {
234 printf("\"");
235 } else {
236 quote_single = true;
237 printf("'");
238 }
239 for (int i = 0; i < len; i++) {
240 if (str[i] == '\n') {
241 printf("\\n");
242 } else if (str[i] == '\\' && str[i + 1] == '\'') {
243 i += 1;
244 if (quote_single) {
245 printf("\\'");
246 } else {
247 printf("'");
248 }
249 } else if (str[i] == '\'' && quote_single) {
250 printf("\\'");
251 } else {
252 printf("%c", str[i]);
253 }
254 }
255 if (has_single_quote && !has_double_quote) {
256 printf("\"");
257 } else {
258 printf("'");
259 }
260 }
261}
262
Damien415eb6f2013-10-05 12:19:06 +0100263static void emit_cpy_load_const_verbatim_end(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100264 if (emit->pass == PASS_3) {
265 printf("\n");
266 }
267}
268
Damien6cdd3af2013-10-05 18:08:26 +0100269static void emit_cpy_load_fast(emit_t *emit, qstr qstr, int local_num) {
270 emit_pre(emit, 1, 3);
271 if (emit->pass == PASS_3) {
272 printf("LOAD_FAST %d %s\n", local_num, qstr_str(qstr));
273 }
274}
275
Damien415eb6f2013-10-05 12:19:06 +0100276static void emit_cpy_load_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100277 emit_pre(emit, 1, 3);
278 if (emit->pass == PASS_3) {
279 printf("LOAD_NAME %s\n", qstr_str(qstr));
280 }
281}
282
Damien415eb6f2013-10-05 12:19:06 +0100283static void emit_cpy_load_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100284 emit_pre(emit, 1, 3);
285 if (emit->pass == PASS_3) {
286 printf("LOAD_GLOBAL %s\n", qstr_str(qstr));
287 }
288}
289
Damien415eb6f2013-10-05 12:19:06 +0100290static void emit_cpy_load_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100291 emit_pre(emit, 1, 3);
292 if (emit->pass == PASS_3) {
293 printf("LOAD_DEREF %s\n", qstr_str(qstr));
294 }
295}
296
Damien415eb6f2013-10-05 12:19:06 +0100297static void emit_cpy_load_closure(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100298 emit_pre(emit, 1, 3);
299 if (emit->pass == PASS_3) {
300 printf("LOAD_CLOSURE %s\n", qstr_str(qstr));
301 }
302}
303
Damien415eb6f2013-10-05 12:19:06 +0100304static void emit_cpy_load_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100305 emit_pre(emit, 0, 3);
306 if (emit->pass == PASS_3) {
307 printf("LOAD_ATTR %s\n", qstr_str(qstr));
308 }
309}
310
Damien415eb6f2013-10-05 12:19:06 +0100311static void emit_cpy_load_method(emit_t *emit, qstr qstr) {
312 emit_cpy_load_attr(emit, qstr);
Damien429d7192013-10-04 19:53:11 +0100313}
314
Damien415eb6f2013-10-05 12:19:06 +0100315static void emit_cpy_load_build_class(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100316 emit_pre(emit, 1, 1);
317 if (emit->pass == PASS_3) {
318 printf("LOAD_BUILD_CLASS\n");
319 }
320}
321
Damien6cdd3af2013-10-05 18:08:26 +0100322static void emit_cpy_store_fast(emit_t *emit, qstr qstr, int local_num) {
323 emit_pre(emit, -1, 3);
324 if (emit->pass == PASS_3) {
325 printf("STORE_FAST %d %s\n", local_num, qstr_str(qstr));
326 }
327}
328
Damien415eb6f2013-10-05 12:19:06 +0100329static void emit_cpy_store_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100330 emit_pre(emit, -1, 3);
331 if (emit->pass == PASS_3) {
332 printf("STORE_NAME %s\n", qstr_str(qstr));
333 }
334}
335
Damien415eb6f2013-10-05 12:19:06 +0100336static void emit_cpy_store_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100337 emit_pre(emit, -1, 3);
338 if (emit->pass == PASS_3) {
339 printf("STORE_GLOBAL %s\n", qstr_str(qstr));
340 }
341}
342
Damien415eb6f2013-10-05 12:19:06 +0100343static void emit_cpy_store_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100344 emit_pre(emit, -1, 3);
345 if (emit->pass == PASS_3) {
346 printf("STORE_DEREF %s\n", qstr_str(qstr));
347 }
348}
349
Damien415eb6f2013-10-05 12:19:06 +0100350static void emit_cpy_store_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100351 emit_pre(emit, -2, 3);
352 if (emit->pass == PASS_3) {
353 printf("STORE_ATTR %s\n", qstr_str(qstr));
354 }
355}
356
Damien415eb6f2013-10-05 12:19:06 +0100357static void emit_cpy_store_locals(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100358 emit_pre(emit, -1, 1);
359 if (emit->pass == PASS_3) {
360 printf("STORE_LOCALS\n");
361 }
362}
363
Damien415eb6f2013-10-05 12:19:06 +0100364static void emit_cpy_store_subscr(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100365 emit_pre(emit, -3, 1);
366 if (emit->pass == PASS_3) {
367 printf("STORE_SUBSCR\n");
368 }
369}
370
Damien6cdd3af2013-10-05 18:08:26 +0100371static void emit_cpy_delete_fast(emit_t *emit, qstr qstr, int local_num) {
372 emit_pre(emit, 0, 3);
373 if (emit->pass == PASS_3) {
374 printf("DELETE_FAST %d %s\n", local_num, qstr_str(qstr));
375 }
376}
377
Damien415eb6f2013-10-05 12:19:06 +0100378static void emit_cpy_delete_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100379 emit_pre(emit, 0, 3);
380 if (emit->pass == PASS_3) {
381 printf("DELETE_NAME %s\n", qstr_str(qstr));
382 }
383}
384
Damien415eb6f2013-10-05 12:19:06 +0100385static void emit_cpy_delete_global(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100386 emit_pre(emit, 0, 3);
387 if (emit->pass == PASS_3) {
388 printf("DELETE_GLOBAL %s\n", qstr_str(qstr));
389 }
390}
391
Damien415eb6f2013-10-05 12:19:06 +0100392static void emit_cpy_delete_deref(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100393 emit_pre(emit, 0, 3);
394 if (emit->pass == PASS_3) {
395 printf("DELETE_DEREF %s\n", qstr_str(qstr));
396 }
397}
398
Damien415eb6f2013-10-05 12:19:06 +0100399static void emit_cpy_delete_attr(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100400 emit_pre(emit, -1, 3);
401 if (emit->pass == PASS_3) {
402 printf("DELETE_ATTR %s\n", qstr_str(qstr));
403 }
404}
405
Damien415eb6f2013-10-05 12:19:06 +0100406static void emit_cpy_delete_subscr(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100407 emit_pre(emit, -2, 1);
408 if (emit->pass == PASS_3) {
409 printf("DELETE_SUBSCR\n");
410 }
411}
412
Damien415eb6f2013-10-05 12:19:06 +0100413static void emit_cpy_dup_top(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100414 emit_pre(emit, 1, 1);
415 if (emit->pass == PASS_3) {
416 printf("DUP_TOP\n");
417 }
418}
419
Damien415eb6f2013-10-05 12:19:06 +0100420static void emit_cpy_dup_top_two(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100421 emit_pre(emit, 2, 1);
422 if (emit->pass == PASS_3) {
423 printf("DUP_TOP_TWO\n");
424 }
425}
426
Damien415eb6f2013-10-05 12:19:06 +0100427static void emit_cpy_pop_top(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100428 emit_pre(emit, -1, 1);
429 if (emit->pass == PASS_3) {
430 printf("POP_TOP\n");
431 }
432}
433
Damien415eb6f2013-10-05 12:19:06 +0100434static void emit_cpy_rot_two(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100435 emit_pre(emit, 0, 1);
436 if (emit->pass == PASS_3) {
437 printf("ROT_TWO\n");
438 }
439}
440
Damien415eb6f2013-10-05 12:19:06 +0100441static void emit_cpy_rot_three(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100442 emit_pre(emit, 0, 1);
443 if (emit->pass == PASS_3) {
444 printf("ROT_THREE\n");
445 }
446}
447
Damien415eb6f2013-10-05 12:19:06 +0100448static void emit_cpy_jump(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100449 emit_pre(emit, 0, 3);
450 if (emit->pass == PASS_3) {
451 int dest = emit->label_offsets[label];
452 if (dest < emit->byte_code_offset) {
453 printf("JUMP_ABSOLUTE %d\n", emit->label_offsets[label]);
454 } else {
455 printf("JUMP_FORWARD %d\n", emit->label_offsets[label]);
456 }
457 }
458}
459
Damien415eb6f2013-10-05 12:19:06 +0100460static void emit_cpy_pop_jump_if_true(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100461 emit_pre(emit, -1, 3);
462 if (emit->pass == PASS_3) {
463 printf("POP_JUMP_IF_TRUE %d\n", emit->label_offsets[label]);
464 }
465}
466
Damien415eb6f2013-10-05 12:19:06 +0100467static void emit_cpy_pop_jump_if_false(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100468 emit_pre(emit, -1, 3);
469 if (emit->pass == PASS_3) {
470 printf("POP_JUMP_IF_FALSE %d\n", emit->label_offsets[label]);
471 }
472}
473
Damien415eb6f2013-10-05 12:19:06 +0100474static void emit_cpy_jump_if_true_or_pop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100475 emit_pre(emit, -1, 3);
476 if (emit->pass == PASS_3) {
477 printf("JUMP_IF_TRUE_OR_POP %d\n", emit->label_offsets[label]);
478 }
479}
480
Damien415eb6f2013-10-05 12:19:06 +0100481static void emit_cpy_jump_if_false_or_pop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100482 emit_pre(emit, -1, 3);
483 if (emit->pass == PASS_3) {
484 printf("JUMP_IF_FALSE_OR_POP %d\n", emit->label_offsets[label]);
485 }
486}
487
Damien415eb6f2013-10-05 12:19:06 +0100488static void emit_cpy_setup_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100489 emit_pre(emit, 0, 3);
490 if (emit->pass == PASS_3) {
491 printf("SETUP_LOOP %d\n", emit->label_offsets[label]);
492 }
493}
494
Damien415eb6f2013-10-05 12:19:06 +0100495static void emit_cpy_break_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100496 emit_pre(emit, 0, 1);
497 if (emit->pass == PASS_3) {
498 printf("BREAK_LOOP\n"); // CPython doesn't have label
499 //printf("BREAK_LOOP %d\n", emit->label_offsets[label]);
500 }
501}
502
Damien415eb6f2013-10-05 12:19:06 +0100503static void emit_cpy_continue_loop(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100504 emit_pre(emit, 0, 3);
505 if (emit->pass == PASS_3) {
506 printf("CONTINUE_LOOP %d\n", emit->label_offsets[label]);
507 }
508}
509
Damien415eb6f2013-10-05 12:19:06 +0100510static void emit_cpy_setup_with(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100511 emit_pre(emit, 7, 3);
512 if (emit->pass == PASS_3) {
513 printf("SETUP_WITH %d\n", emit->label_offsets[label]);
514 }
515}
516
Damien415eb6f2013-10-05 12:19:06 +0100517static void emit_cpy_with_cleanup(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100518 emit_pre(emit, -7, 1);
519 if (emit->pass == PASS_3) {
520 printf("WITH_CLEANUP\n");
521 }
522}
523
Damien415eb6f2013-10-05 12:19:06 +0100524static void emit_cpy_setup_except(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100525 emit_pre(emit, 6, 3);
526 if (emit->pass == PASS_3) {
527 printf("SETUP_EXCEPT %d\n", emit->label_offsets[label]);
528 }
529}
530
Damien415eb6f2013-10-05 12:19:06 +0100531static void emit_cpy_setup_finally(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100532 emit_pre(emit, 6, 3);
533 if (emit->pass == PASS_3) {
534 printf("SETUP_FINALLY %d\n", emit->label_offsets[label]);
535 }
536}
537
Damien415eb6f2013-10-05 12:19:06 +0100538static void emit_cpy_end_finally(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100539 emit_pre(emit, -1, 1);
540 if (emit->pass == PASS_3) {
541 printf("END_FINALLY\n");
542 }
543}
544
Damien415eb6f2013-10-05 12:19:06 +0100545static void emit_cpy_get_iter(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100546 emit_pre(emit, 0, 1);
547 if (emit->pass == PASS_3) {
548 printf("GET_ITER\n");
549 }
550}
551
Damien415eb6f2013-10-05 12:19:06 +0100552static void emit_cpy_for_iter(emit_t *emit, int label) {
Damien429d7192013-10-04 19:53:11 +0100553 emit_pre(emit, 1, 3);
554 if (emit->pass == PASS_3) {
555 printf("FOR_ITER %d\n", emit->label_offsets[label]);
556 }
557}
558
Damien415eb6f2013-10-05 12:19:06 +0100559static void emit_cpy_for_iter_end(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100560 emit_pre(emit, -1, 0);
561}
562
Damien415eb6f2013-10-05 12:19:06 +0100563static void emit_cpy_pop_block(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100564 emit_pre(emit, 0, 1);
565 if (emit->pass == PASS_3) {
566 printf("POP_BLOCK\n");
567 }
568}
569
Damien415eb6f2013-10-05 12:19:06 +0100570static void emit_cpy_pop_except(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100571 emit_pre(emit, 0, 1);
572 if (emit->pass == PASS_3) {
573 printf("POP_EXCEPT\n");
574 }
575}
576
Damien415eb6f2013-10-05 12:19:06 +0100577static void emit_cpy_unary_op(emit_t *emit, rt_unary_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100578 emit_pre(emit, 0, 1);
579 if (emit->pass == PASS_3) {
580 switch (op) {
581 case RT_UNARY_OP_NOT: printf("UNARY_NOT\n"); break;
582 case RT_UNARY_OP_POSITIVE: printf("UNARY_POSITIVE\n"); break;
583 case RT_UNARY_OP_NEGATIVE: printf("UNARY_NEGATIVE\n"); break;
584 case RT_UNARY_OP_INVERT: printf("UNARY_INVERT\n"); break;
585 default: assert(0);
586 }
587 }
588}
589
Damien415eb6f2013-10-05 12:19:06 +0100590static void emit_cpy_binary_op(emit_t *emit, rt_binary_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100591 emit_pre(emit, -1, 1);
592 if (emit->pass == PASS_3) {
593 switch (op) {
594 case RT_BINARY_OP_SUBSCR: printf("BINARY_SUBSCR\n"); break;
595 case RT_BINARY_OP_OR: printf("BINARY_OR\n"); break;
596 case RT_BINARY_OP_XOR: printf("BINARY_XOR\n"); break;
597 case RT_BINARY_OP_AND: printf("BINARY_AND\n"); break;
598 case RT_BINARY_OP_LSHIFT: printf("BINARY_LSHIFT\n"); break;
599 case RT_BINARY_OP_RSHIFT: printf("BINARY_RSHIFT\n"); break;
600 case RT_BINARY_OP_ADD: printf("BINARY_ADD\n"); break;
601 case RT_BINARY_OP_SUBTRACT: printf("BINARY_SUBTRACT\n"); break;
602 case RT_BINARY_OP_MULTIPLY: printf("BINARY_MULTIPLY\n"); break;
603 case RT_BINARY_OP_FLOOR_DIVIDE: printf("BINARY_FLOOR_DIVIDE\n"); break;
604 case RT_BINARY_OP_TRUE_DIVIDE: printf("BINARY_TRUE_DIVIDE\n"); break;
605 case RT_BINARY_OP_MODULO: printf("BINARY_MODULO\n"); break;
606 case RT_BINARY_OP_POWER: printf("BINARY_POWER\n"); break;
607 case RT_BINARY_OP_INPLACE_OR: printf("INPLACE_OR\n"); break;
608 case RT_BINARY_OP_INPLACE_XOR: printf("INPLACE_XOR\n"); break;
609 case RT_BINARY_OP_INPLACE_AND: printf("INPLACE_AND\n"); break;
610 case RT_BINARY_OP_INPLACE_LSHIFT: printf("INPLACE_LSHIFT\n"); break;
611 case RT_BINARY_OP_INPLACE_RSHIFT: printf("INPLACE_RSHIFT\n"); break;
612 case RT_BINARY_OP_INPLACE_ADD: printf("INPLACE_ADD\n"); break;
613 case RT_BINARY_OP_INPLACE_SUBTRACT: printf("INPLACE_SUBTRACT\n"); break;
614 case RT_BINARY_OP_INPLACE_MULTIPLY: printf("INPLACE_MULTIPLY\n"); break;
615 case RT_BINARY_OP_INPLACE_FLOOR_DIVIDE: printf("INPLACE_FLOOR_DIVIDE\n"); break;
616 case RT_BINARY_OP_INPLACE_TRUE_DIVIDE: printf("INPLACE_TRUE_DIVIDE\n"); break;
617 case RT_BINARY_OP_INPLACE_MODULO: printf("INPLACE_MODULO\n"); break;
618 case RT_BINARY_OP_INPLACE_POWER: printf("INPLACE_POWER\n"); break;
619 default: assert(0);
620 }
621 }
622}
623
Damien415eb6f2013-10-05 12:19:06 +0100624static void emit_cpy_compare_op(emit_t *emit, rt_compare_op_t op) {
Damien429d7192013-10-04 19:53:11 +0100625 emit_pre(emit, -1, 3);
626 if (emit->pass == PASS_3) {
627 switch (op) {
628 case RT_COMPARE_OP_LESS: printf("COMPARE_OP <\n"); break;
629 case RT_COMPARE_OP_MORE: printf("COMPARE_OP >\n"); break;
630 case RT_COMPARE_OP_EQUAL: printf("COMPARE_OP ==\n"); break;
631 case RT_COMPARE_OP_LESS_EQUAL: printf("COMPARE_OP <=\n"); break;
632 case RT_COMPARE_OP_MORE_EQUAL: printf("COMPARE_OP >=\n"); break;
633 case RT_COMPARE_OP_NOT_EQUAL: printf("COMPARE_OP !=\n"); break;
634 case RT_COMPARE_OP_IN: printf("COMPARE_OP in\n"); break;
635 case RT_COMPARE_OP_NOT_IN: printf("COMPARE_OP not in\n"); break;
636 case RT_COMPARE_OP_IS: printf("COMPARE_OP is\n"); break;
637 case RT_COMPARE_OP_IS_NOT: printf("COMPARE_OP is not\n"); break;
638 case RT_COMPARE_OP_EXCEPTION_MATCH: printf("COMPARE_OP exception match\n"); break;
639 default: assert(0);
640 }
641 }
642}
643
Damien415eb6f2013-10-05 12:19:06 +0100644static void emit_cpy_build_tuple(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100645 emit_pre(emit, 1 - n_args, 3);
646 if (emit->pass == PASS_3) {
647 printf("BUILD_TUPLE %d\n", n_args);
648 }
649}
650
Damien415eb6f2013-10-05 12:19:06 +0100651static void emit_cpy_build_list(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100652 emit_pre(emit, 1 - n_args, 3);
653 if (emit->pass == PASS_3) {
654 printf("BUILD_LIST %d\n", n_args);
655 }
656}
657
Damien415eb6f2013-10-05 12:19:06 +0100658static void emit_cpy_list_append(emit_t *emit, int list_index) {
Damien429d7192013-10-04 19:53:11 +0100659 emit_pre(emit, -1, 3);
660 if (emit->pass == PASS_3) {
661 printf("LIST_APPEND %d\n", list_index);
662 }
663}
664
Damien415eb6f2013-10-05 12:19:06 +0100665static void emit_cpy_build_map(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100666 emit_pre(emit, 1, 3);
667 if (emit->pass == PASS_3) {
668 printf("BUILD_MAP %d\n", n_args);
669 }
670}
671
Damien415eb6f2013-10-05 12:19:06 +0100672static void emit_cpy_store_map(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100673 emit_pre(emit, -2, 1);
674 if (emit->pass == PASS_3) {
675 printf("STORE_MAP\n");
676 }
677}
678
Damien415eb6f2013-10-05 12:19:06 +0100679static void emit_cpy_map_add(emit_t *emit, int map_index) {
Damien429d7192013-10-04 19:53:11 +0100680 emit_pre(emit, -2, 3);
681 if (emit->pass == PASS_3) {
682 printf("MAP_ADD %d\n", map_index);
683 }
684}
685
Damien415eb6f2013-10-05 12:19:06 +0100686static void emit_cpy_build_set(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100687 emit_pre(emit, 1 - n_args, 3);
688 if (emit->pass == PASS_3) {
689 printf("BUILD_SET %d\n", n_args);
690 }
691}
692
Damien415eb6f2013-10-05 12:19:06 +0100693static void emit_cpy_set_add(emit_t *emit, int set_index) {
Damien429d7192013-10-04 19:53:11 +0100694 emit_pre(emit, -1, 3);
695 if (emit->pass == PASS_3) {
696 printf("SET_ADD %d\n", set_index);
697 }
698}
699
Damien415eb6f2013-10-05 12:19:06 +0100700static void emit_cpy_build_slice(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100701 emit_pre(emit, 1 - n_args, 3);
702 if (emit->pass == PASS_3) {
703 printf("BUILD_SLICE %d\n", n_args);
704 }
705}
706
Damien415eb6f2013-10-05 12:19:06 +0100707static void emit_cpy_unpack_sequence(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100708 emit_pre(emit, -1 + n_args, 3);
709 if (emit->pass == PASS_3) {
710 printf("UNPACK_SEQUENCE %d\n", n_args);
711 }
712}
713
Damien415eb6f2013-10-05 12:19:06 +0100714static void emit_cpy_unpack_ex(emit_t *emit, int n_left, int n_right) {
Damien429d7192013-10-04 19:53:11 +0100715 emit_pre(emit, -1 + n_left + n_right + 1, 3);
716 if (emit->pass == PASS_3) {
717 printf("UNPACK_EX %d\n", n_left | (n_right << 8));
718 }
719}
720
Damien415eb6f2013-10-05 12:19:06 +0100721static 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 +0100722 int s = 0;
723 if (have_star_arg) {
724 s += 1;
725 }
726 if (have_dbl_star_arg) {
727 s += 1;
728 }
729 emit_pre(emit, -n_positional - 2 * n_keyword - s, 3);
730 if (emit->pass == PASS_3) {
731 if (have_star_arg) {
732 if (have_dbl_star_arg) {
733 printf("CALL_FUNCTION_VAR_KW");
734 } else {
735 printf("CALL_FUNCTION_VAR");
736 }
737 } else {
738 if (have_dbl_star_arg) {
739 printf("CALL_FUNCTION_KW");
740 } else {
741 printf("CALL_FUNCTION");
742 }
743 }
744 printf(" %d, %d\n", n_positional, n_keyword);
745 }
746}
747
Damien415eb6f2013-10-05 12:19:06 +0100748static void emit_cpy_call_method(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
749 emit_cpy_call_function(emit, n_positional, n_keyword, have_star_arg, have_dbl_star_arg);
Damien429d7192013-10-04 19:53:11 +0100750}
751
Damien415eb6f2013-10-05 12:19:06 +0100752static void emit_cpy_return_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100753 emit_pre(emit, -1, 1);
754 emit->last_emit_was_return_value = true;
755 if (emit->pass == PASS_3) {
756 printf("RETURN_VALUE\n");
757 }
758}
759
Damien415eb6f2013-10-05 12:19:06 +0100760static void emit_cpy_raise_varargs(emit_t *emit, int n_args) {
Damien429d7192013-10-04 19:53:11 +0100761 emit_pre(emit, -n_args, 3);
762 if (emit->pass == PASS_3) {
763 printf("RAISE_VARARGS %d\n", n_args);
764 }
765}
766
Damien415eb6f2013-10-05 12:19:06 +0100767static void load_cpy_const_code_and_name(emit_t *emit, qstr qstr) {
Damien429d7192013-10-04 19:53:11 +0100768 emit_pre(emit, 1, 3);
769 if (emit->pass == PASS_3) {
770 printf("LOAD_CONST code %s\n", qstr_str(qstr));
771 }
772 // load qualified name
773 emit_pre(emit, 1, 3);
774 if (emit->pass == PASS_3) {
775 printf("LOAD_CONST '");
776 // code just to work out the qualname (or whatever it is)
777 {
778 int depth = 0;
779 for (scope_t *s = emit->scope; s->parent != NULL; s = s->parent) {
780 depth += 1;
781 }
782 for (int wanted_depth = depth; wanted_depth >= 0; wanted_depth--) {
783 scope_t *s = emit->scope;
784 for (int i = 0; i < wanted_depth; i++) {
785 s = s->parent;
786 }
787 if (s->kind == SCOPE_FUNCTION) {
788 printf("%s.<locals>.", qstr_str(s->simple_name));
789 } else if (s->kind == SCOPE_CLASS) {
790 printf("%s.", qstr_str(s->simple_name));
791 }
792 }
793 }
794 printf("%s'\n", qstr_str(qstr));
795 }
796}
797
Damien415eb6f2013-10-05 12:19:06 +0100798static void emit_cpy_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
799 load_cpy_const_code_and_name(emit, scope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100800 emit_pre(emit, -1 - n_default_params - 2 * n_dict_params, 3);
801 if (emit->pass == PASS_3) {
802 printf("MAKE_FUNCTION %d\n", (n_dict_params << 8) | n_default_params);
803 }
804}
805
Damien415eb6f2013-10-05 12:19:06 +0100806static void emit_cpy_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
807 load_cpy_const_code_and_name(emit, scope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100808 emit_pre(emit, -2 - n_default_params - 2 * n_dict_params, 3);
809 if (emit->pass == PASS_3) {
810 printf("MAKE_CLOSURE %d\n", (n_dict_params << 8) | n_default_params);
811 }
812}
813
Damien415eb6f2013-10-05 12:19:06 +0100814static void emit_cpy_yield_value(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100815 emit_pre(emit, 0, 1);
816 if (emit->pass == PASS_2) {
817 emit->scope->flags |= SCOPE_FLAG_GENERATOR;
818 }
819 if (emit->pass == PASS_3) {
820 printf("YIELD_VALUE\n");
821 }
822}
823
Damien415eb6f2013-10-05 12:19:06 +0100824static void emit_cpy_yield_from(emit_t *emit) {
Damien429d7192013-10-04 19:53:11 +0100825 emit_pre(emit, -1, 1);
826 if (emit->pass == PASS_2) {
827 emit->scope->flags |= SCOPE_FLAG_GENERATOR;
828 }
829 if (emit->pass == PASS_3) {
830 printf("YIELD_FROM\n");
831 }
832}
833
Damien6cdd3af2013-10-05 18:08:26 +0100834const emit_method_table_t emit_cpython_method_table = {
Damien415eb6f2013-10-05 12:19:06 +0100835 emit_cpy_set_native_types,
836 emit_cpy_start_pass,
837 emit_cpy_end_pass,
838 emit_cpy_last_emit_was_return_value,
839 emit_cpy_get_stack_size,
840 emit_cpy_set_stack_size,
841
Damien4b03e772013-10-05 14:17:09 +0100842 emit_cpy_load_id,
843 emit_cpy_store_id,
844 emit_cpy_delete_id,
845
Damien415eb6f2013-10-05 12:19:06 +0100846 emit_cpy_label_assign,
847 emit_cpy_import_name,
848 emit_cpy_import_from,
849 emit_cpy_import_star,
850 emit_cpy_load_const_tok,
851 emit_cpy_load_const_small_int,
852 emit_cpy_load_const_int,
853 emit_cpy_load_const_dec,
854 emit_cpy_load_const_id,
855 emit_cpy_load_const_str,
856 emit_cpy_load_const_verbatim_start,
857 emit_cpy_load_const_verbatim_int,
858 emit_cpy_load_const_verbatim_str,
859 emit_cpy_load_const_verbatim_strn,
860 emit_cpy_load_const_verbatim_quoted_str,
861 emit_cpy_load_const_verbatim_end,
862 emit_cpy_load_fast,
863 emit_cpy_load_name,
864 emit_cpy_load_global,
865 emit_cpy_load_deref,
866 emit_cpy_load_closure,
867 emit_cpy_load_attr,
868 emit_cpy_load_method,
869 emit_cpy_load_build_class,
870 emit_cpy_store_fast,
871 emit_cpy_store_name,
872 emit_cpy_store_global,
873 emit_cpy_store_deref,
874 emit_cpy_store_attr,
875 emit_cpy_store_locals,
876 emit_cpy_store_subscr,
877 emit_cpy_delete_fast,
878 emit_cpy_delete_name,
879 emit_cpy_delete_global,
880 emit_cpy_delete_deref,
881 emit_cpy_delete_attr,
882 emit_cpy_delete_subscr,
883 emit_cpy_dup_top,
884 emit_cpy_dup_top_two,
885 emit_cpy_pop_top,
886 emit_cpy_rot_two,
887 emit_cpy_rot_three,
888 emit_cpy_jump,
889 emit_cpy_pop_jump_if_true,
890 emit_cpy_pop_jump_if_false,
891 emit_cpy_jump_if_true_or_pop,
892 emit_cpy_jump_if_false_or_pop,
893 emit_cpy_setup_loop,
894 emit_cpy_break_loop,
895 emit_cpy_continue_loop,
896 emit_cpy_setup_with,
897 emit_cpy_with_cleanup,
898 emit_cpy_setup_except,
899 emit_cpy_setup_finally,
900 emit_cpy_end_finally,
901 emit_cpy_get_iter,
902 emit_cpy_for_iter,
903 emit_cpy_for_iter_end,
904 emit_cpy_pop_block,
905 emit_cpy_pop_except,
906 emit_cpy_unary_op,
907 emit_cpy_binary_op,
908 emit_cpy_compare_op,
909 emit_cpy_build_tuple,
910 emit_cpy_build_list,
911 emit_cpy_list_append,
912 emit_cpy_build_map,
913 emit_cpy_store_map,
914 emit_cpy_map_add,
915 emit_cpy_build_set,
916 emit_cpy_set_add,
917 emit_cpy_build_slice,
918 emit_cpy_unpack_sequence,
919 emit_cpy_unpack_ex,
920 emit_cpy_make_function,
921 emit_cpy_make_closure,
922 emit_cpy_call_function,
923 emit_cpy_call_method,
924 emit_cpy_return_value,
925 emit_cpy_raise_varargs,
926 emit_cpy_yield_value,
927 emit_cpy_yield_from,
928};
929
Damien415eb6f2013-10-05 12:19:06 +0100930#endif // EMIT_ENABLE_CPY