blob: 47741b8da8dd984afbce77a284f218f2667d36e2 [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"
Damiend99b0522013-12-21 18:17:45 +00009#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +000010#include "qstr.h"
Damien429d7192013-10-04 19:53:11 +010011#include "lexer.h"
Damien429d7192013-10-04 19:53:11 +010012#include "parse.h"
13#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000014#include "runtime0.h"
Damien429d7192013-10-04 19:53:11 +010015#include "emit.h"
Damien George1fb03172014-01-03 14:22:03 +000016#include "obj.h"
17#include "compile.h"
18#include "runtime.h"
Damien429d7192013-10-04 19:53:11 +010019
20// TODO need to mangle __attr names
21
Damience89a212013-10-15 22:25:17 +010022#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)
23
Damien429d7192013-10-04 19:53:11 +010024typedef enum {
25 PN_none = 0,
Damien George00208ce2014-01-23 00:00:53 +000026#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
Damien429d7192013-10-04 19:53:11 +010027#include "grammar.h"
28#undef DEF_RULE
29 PN_maximum_number_of,
30} pn_kind_t;
31
Damien Georgeb9791222014-01-23 00:34:21 +000032#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
33#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
34#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
35#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
Damien429d7192013-10-04 19:53:11 +010036
Damien6cdd3af2013-10-05 18:08:26 +010037#define EMIT_OPT_NONE (0)
38#define EMIT_OPT_BYTE_CODE (1)
39#define EMIT_OPT_NATIVE_PYTHON (2)
Damien7af3d192013-10-07 00:02:49 +010040#define EMIT_OPT_VIPER (3)
41#define EMIT_OPT_ASM_THUMB (4)
Damien6cdd3af2013-10-05 18:08:26 +010042
Damien429d7192013-10-04 19:53:11 +010043typedef struct _compiler_t {
Damien Georgecbd2f742014-01-19 11:48:48 +000044 qstr source_file;
Damien5ac1b2e2013-10-18 19:58:12 +010045 bool is_repl;
Damien429d7192013-10-04 19:53:11 +010046 pass_kind_t pass;
Damien5ac1b2e2013-10-18 19:58:12 +010047 bool had_error; // try to keep compiler clean from nlr
Damien429d7192013-10-04 19:53:11 +010048
Damienb05d7072013-10-05 13:37:10 +010049 int next_label;
Damienb05d7072013-10-05 13:37:10 +010050
Damien429d7192013-10-04 19:53:11 +010051 int break_label;
52 int continue_label;
Damien Georgecbddb272014-02-01 20:08:18 +000053 int break_continue_except_level;
54 int cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
Damien429d7192013-10-04 19:53:11 +010055
56 int n_arg_keyword;
57 bool have_star_arg;
58 bool have_dbl_star_arg;
59 bool have_bare_star;
60 int param_pass;
61 int param_pass_num_dict_params;
62 int param_pass_num_default_params;
63
64 scope_t *scope_head;
65 scope_t *scope_cur;
66
Damien6cdd3af2013-10-05 18:08:26 +010067 emit_t *emit; // current emitter
68 const emit_method_table_t *emit_method_table; // current emit method table
Damien826005c2013-10-05 23:17:28 +010069
70 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
71 const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
Damien429d7192013-10-04 19:53:11 +010072} compiler_t;
73
Damiend99b0522013-12-21 18:17:45 +000074mp_parse_node_t fold_constants(mp_parse_node_t pn) {
75 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
76 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
77 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +010078
79 // fold arguments first
80 for (int i = 0; i < n; i++) {
81 pns->nodes[i] = fold_constants(pns->nodes[i]);
82 }
83
Damiend99b0522013-12-21 18:17:45 +000084 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +010085 case PN_shift_expr:
Damiend99b0522013-12-21 18:17:45 +000086 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
87 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
88 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
89 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
Damien3ef4abb2013-10-12 16:53:13 +010090#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +010091 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +000092 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
Damien0efb3a12013-10-12 16:16:56 +010093#endif
Damiend99b0522013-12-21 18:17:45 +000094 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
95 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien429d7192013-10-04 19:53:11 +010096 } else {
97 // shouldn't happen
98 assert(0);
99 }
100 }
101 break;
102
103 case PN_arith_expr:
Damien0efb3a12013-10-12 16:16:56 +0100104 // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
Damiend99b0522013-12-21 18:17:45 +0000105 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
106 machine_int_t arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
107 machine_int_t arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
Damien0efb3a12013-10-12 16:16:56 +0100108 machine_int_t res;
Damiend99b0522013-12-21 18:17:45 +0000109 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100110 res = arg0 + arg1;
Damiend99b0522013-12-21 18:17:45 +0000111 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100112 res = arg0 - arg1;
Damien429d7192013-10-04 19:53:11 +0100113 } else {
114 // shouldn't happen
115 assert(0);
Damien0efb3a12013-10-12 16:16:56 +0100116 res = 0;
117 }
Damiend99b0522013-12-21 18:17:45 +0000118 if (MP_FIT_SMALL_INT(res)) {
119 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
Damien429d7192013-10-04 19:53:11 +0100120 }
121 }
122 break;
123
124 case PN_term:
Damiend99b0522013-12-21 18:17:45 +0000125 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
126 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
127 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
128 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien3ef4abb2013-10-12 16:53:13 +0100129#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100130 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000131 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
Damien0efb3a12013-10-12 16:16:56 +0100132#endif
Damiend99b0522013-12-21 18:17:45 +0000133 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +0100134 ; // pass
Damiend99b0522013-12-21 18:17:45 +0000135 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
Damien0efb3a12013-10-12 16:16:56 +0100136 // XXX implement this properly as Python's % operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000137 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1);
138 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
Damien0efb3a12013-10-12 16:16:56 +0100139 // XXX implement this properly as Python's // operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000140 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1);
Damien429d7192013-10-04 19:53:11 +0100141 } else {
142 // shouldn't happen
143 assert(0);
144 }
145 }
146 break;
147
148 case PN_factor_2:
Damiend99b0522013-12-21 18:17:45 +0000149 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
150 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
151 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
152 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
153 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
154 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
155 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
156 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien429d7192013-10-04 19:53:11 +0100157 } else {
158 // shouldn't happen
159 assert(0);
160 }
161 }
162 break;
163
Damien3ef4abb2013-10-12 16:53:13 +0100164#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +0100165 case PN_power:
Damien0efb3a12013-10-12 16:16:56 +0100166 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000167 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_NULL(pns->nodes[1]) && !MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
168 mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
169 if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
170 int power = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100171 if (power >= 0) {
172 int ans = 1;
Damiend99b0522013-12-21 18:17:45 +0000173 int base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100174 for (; power > 0; power--) {
175 ans *= base;
176 }
Damiend99b0522013-12-21 18:17:45 +0000177 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien429d7192013-10-04 19:53:11 +0100178 }
179 }
180 }
181 break;
Damien0efb3a12013-10-12 16:16:56 +0100182#endif
Damien429d7192013-10-04 19:53:11 +0100183 }
184 }
185
186 return pn;
187}
188
Damiend99b0522013-12-21 18:17:45 +0000189void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100190
Damienb05d7072013-10-05 13:37:10 +0100191static int comp_next_label(compiler_t *comp) {
192 return comp->next_label++;
193}
194
Damiend99b0522013-12-21 18:17:45 +0000195static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
Damien Georgecbd2f742014-01-19 11:48:48 +0000196 scope_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
Damien429d7192013-10-04 19:53:11 +0100197 scope->parent = comp->scope_cur;
198 scope->next = NULL;
199 if (comp->scope_head == NULL) {
200 comp->scope_head = scope;
201 } else {
202 scope_t *s = comp->scope_head;
203 while (s->next != NULL) {
204 s = s->next;
205 }
206 s->next = scope;
207 }
208 return scope;
209}
210
Damiend99b0522013-12-21 18:17:45 +0000211static int list_len(mp_parse_node_t pn, int pn_kind) {
212 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100213 return 0;
Damiend99b0522013-12-21 18:17:45 +0000214 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100215 return 1;
216 } else {
Damiend99b0522013-12-21 18:17:45 +0000217 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
218 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100219 return 1;
220 } else {
Damiend99b0522013-12-21 18:17:45 +0000221 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100222 }
223 }
224}
225
Damiend99b0522013-12-21 18:17:45 +0000226static void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, int pn_list_kind, void (*f)(compiler_t*, mp_parse_node_t)) {
227 if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
228 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
229 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100230 for (int i = 0; i < num_nodes; i++) {
231 f(comp, pns->nodes[i]);
232 }
Damiend99b0522013-12-21 18:17:45 +0000233 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100234 f(comp, pn);
235 }
236}
237
Damiend99b0522013-12-21 18:17:45 +0000238static int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
239 if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100240 *nodes = NULL;
241 return 0;
Damiend99b0522013-12-21 18:17:45 +0000242 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100243 *nodes = pn;
244 return 1;
245 } else {
Damiend99b0522013-12-21 18:17:45 +0000246 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
247 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100248 *nodes = pn;
249 return 1;
250 } else {
251 *nodes = pns->nodes;
Damiend99b0522013-12-21 18:17:45 +0000252 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100253 }
254 }
255}
256
Damiend99b0522013-12-21 18:17:45 +0000257void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100258}
259
Damiend99b0522013-12-21 18:17:45 +0000260void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
261 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100262 for (int i = 0; i < num_nodes; i++) {
263 compile_node(comp, pns->nodes[i]);
264 }
265}
266
Damien3ef4abb2013-10-12 16:53:13 +0100267#if MICROPY_EMIT_CPYTHON
Damiend99b0522013-12-21 18:17:45 +0000268static bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
269 if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100270 return false;
271 }
Damiend99b0522013-12-21 18:17:45 +0000272 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +0100273 return false;
274 }
275 return true;
276}
277
Damien02f89412013-12-12 15:13:36 +0000278static void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
Damien George55baff42014-01-21 21:40:13 +0000279 uint len;
280 const byte *str = qstr_data(qstr, &len);
Damien02f89412013-12-12 15:13:36 +0000281 bool has_single_quote = false;
282 bool has_double_quote = false;
283 for (int i = 0; i < len; i++) {
284 if (str[i] == '\'') {
285 has_single_quote = true;
286 } else if (str[i] == '"') {
287 has_double_quote = true;
288 }
289 }
290 if (bytes) {
291 vstr_printf(vstr, "b");
292 }
293 bool quote_single = false;
294 if (has_single_quote && !has_double_quote) {
295 vstr_printf(vstr, "\"");
296 } else {
297 quote_single = true;
298 vstr_printf(vstr, "'");
299 }
300 for (int i = 0; i < len; i++) {
301 if (str[i] == '\n') {
302 vstr_printf(vstr, "\\n");
303 } else if (str[i] == '\\') {
304 vstr_printf(vstr, "\\\\");
305 } else if (str[i] == '\'' && quote_single) {
306 vstr_printf(vstr, "\\'");
307 } else {
308 vstr_printf(vstr, "%c", str[i]);
309 }
310 }
311 if (has_single_quote && !has_double_quote) {
312 vstr_printf(vstr, "\"");
313 } else {
314 vstr_printf(vstr, "'");
315 }
316}
317
Damiend99b0522013-12-21 18:17:45 +0000318static void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
319 assert(MP_PARSE_NODE_IS_LEAF(pn));
320 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
321 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
322 case MP_PARSE_NODE_ID: assert(0);
323 case MP_PARSE_NODE_SMALL_INT: vstr_printf(vstr, "%d", arg); break;
324 case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
325 case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
326 case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
327 case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
328 case MP_PARSE_NODE_TOKEN:
Damien429d7192013-10-04 19:53:11 +0100329 switch (arg) {
Damiend99b0522013-12-21 18:17:45 +0000330 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
331 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
332 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
Damien429d7192013-10-04 19:53:11 +0100333 default: assert(0);
334 }
335 break;
336 default: assert(0);
337 }
338}
339
Damiend99b0522013-12-21 18:17:45 +0000340static void cpython_c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien429d7192013-10-04 19:53:11 +0100341 int n = 0;
342 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000343 n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien429d7192013-10-04 19:53:11 +0100344 }
345 int total = n;
346 bool is_const = true;
Damiend99b0522013-12-21 18:17:45 +0000347 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100348 total += 1;
Damien3a205172013-10-12 15:01:56 +0100349 if (!cpython_c_tuple_is_const(pn)) {
Damien429d7192013-10-04 19:53:11 +0100350 is_const = false;
351 }
352 }
353 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100354 if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien429d7192013-10-04 19:53:11 +0100355 is_const = false;
356 break;
357 }
358 }
359 if (total > 0 && is_const) {
360 bool need_comma = false;
Damien02f89412013-12-12 15:13:36 +0000361 vstr_t *vstr = vstr_new();
362 vstr_printf(vstr, "(");
Damiend99b0522013-12-21 18:17:45 +0000363 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien02f89412013-12-12 15:13:36 +0000364 cpython_c_tuple_emit_const(comp, pn, vstr);
Damien429d7192013-10-04 19:53:11 +0100365 need_comma = true;
366 }
367 for (int i = 0; i < n; i++) {
368 if (need_comma) {
Damien02f89412013-12-12 15:13:36 +0000369 vstr_printf(vstr, ", ");
Damien429d7192013-10-04 19:53:11 +0100370 }
Damien02f89412013-12-12 15:13:36 +0000371 cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien429d7192013-10-04 19:53:11 +0100372 need_comma = true;
373 }
374 if (total == 1) {
Damien02f89412013-12-12 15:13:36 +0000375 vstr_printf(vstr, ",)");
Damien429d7192013-10-04 19:53:11 +0100376 } else {
Damien02f89412013-12-12 15:13:36 +0000377 vstr_printf(vstr, ")");
Damien429d7192013-10-04 19:53:11 +0100378 }
Damien Georgeb9791222014-01-23 00:34:21 +0000379 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +0000380 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +0100381 } else {
Damiend99b0522013-12-21 18:17:45 +0000382 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100383 compile_node(comp, pn);
384 }
385 for (int i = 0; i < n; i++) {
386 compile_node(comp, pns_list->nodes[i]);
387 }
Damien Georgeb9791222014-01-23 00:34:21 +0000388 EMIT_ARG(build_tuple, total);
Damien429d7192013-10-04 19:53:11 +0100389 }
390}
Damien3a205172013-10-12 15:01:56 +0100391#endif
392
393// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
Damiend99b0522013-12-21 18:17:45 +0000394void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3ef4abb2013-10-12 16:53:13 +0100395#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100396 cpython_c_tuple(comp, pn, pns_list);
397#else
398 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000399 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100400 compile_node(comp, pn);
401 total += 1;
402 }
403 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000404 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100405 for (int i = 0; i < n; i++) {
406 compile_node(comp, pns_list->nodes[i]);
407 }
408 total += n;
409 }
Damien Georgeb9791222014-01-23 00:34:21 +0000410 EMIT_ARG(build_tuple, total);
Damien3a205172013-10-12 15:01:56 +0100411#endif
412}
Damien429d7192013-10-04 19:53:11 +0100413
Damiend99b0522013-12-21 18:17:45 +0000414void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100415 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000416 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100417}
418
Damiend99b0522013-12-21 18:17:45 +0000419static bool node_is_const_false(mp_parse_node_t pn) {
420 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
421 // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100422}
423
Damiend99b0522013-12-21 18:17:45 +0000424static bool node_is_const_true(mp_parse_node_t pn) {
425 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100426}
427
Damien3ef4abb2013-10-12 16:53:13 +0100428#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100429// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
Damiend99b0522013-12-21 18:17:45 +0000430static void cpython_c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label, bool is_nested) {
Damien429d7192013-10-04 19:53:11 +0100431 if (node_is_const_false(pn)) {
432 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000433 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100434 }
435 return;
436 } else if (node_is_const_true(pn)) {
437 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000438 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100439 }
440 return;
Damiend99b0522013-12-21 18:17:45 +0000441 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
442 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
443 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
444 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien429d7192013-10-04 19:53:11 +0100445 if (jump_if == false) {
Damienb05d7072013-10-05 13:37:10 +0100446 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100447 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100448 cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien429d7192013-10-04 19:53:11 +0100449 }
Damien3a205172013-10-12 15:01:56 +0100450 cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000451 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100452 } else {
453 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100454 cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100455 }
456 }
457 return;
Damiend99b0522013-12-21 18:17:45 +0000458 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien429d7192013-10-04 19:53:11 +0100459 if (jump_if == false) {
460 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100461 cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100462 }
463 } else {
Damienb05d7072013-10-05 13:37:10 +0100464 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100465 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100466 cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien429d7192013-10-04 19:53:11 +0100467 }
Damien3a205172013-10-12 15:01:56 +0100468 cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000469 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100470 }
471 return;
Damiend99b0522013-12-21 18:17:45 +0000472 } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100473 cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien429d7192013-10-04 19:53:11 +0100474 return;
475 }
476 }
477
478 // nothing special, fall back to default compiling for node and jump
479 compile_node(comp, pn);
480 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000481 EMIT_ARG(pop_jump_if_false, label);
Damien429d7192013-10-04 19:53:11 +0100482 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000483 EMIT_ARG(pop_jump_if_true, label);
Damien429d7192013-10-04 19:53:11 +0100484 }
485}
Damien3a205172013-10-12 15:01:56 +0100486#endif
Damien429d7192013-10-04 19:53:11 +0100487
Damiend99b0522013-12-21 18:17:45 +0000488static void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien3ef4abb2013-10-12 16:53:13 +0100489#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100490 cpython_c_if_cond(comp, pn, jump_if, label, false);
491#else
492 if (node_is_const_false(pn)) {
493 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000494 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100495 }
496 return;
497 } else if (node_is_const_true(pn)) {
498 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000499 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100500 }
501 return;
Damiend99b0522013-12-21 18:17:45 +0000502 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
503 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
504 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
505 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100506 if (jump_if == false) {
507 int label2 = comp_next_label(comp);
508 for (int i = 0; i < n - 1; i++) {
509 c_if_cond(comp, pns->nodes[i], true, label2);
510 }
511 c_if_cond(comp, pns->nodes[n - 1], false, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000512 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100513 } else {
514 for (int i = 0; i < n; i++) {
515 c_if_cond(comp, pns->nodes[i], true, label);
516 }
517 }
518 return;
Damiend99b0522013-12-21 18:17:45 +0000519 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100520 if (jump_if == false) {
521 for (int i = 0; i < n; i++) {
522 c_if_cond(comp, pns->nodes[i], false, label);
523 }
524 } else {
525 int label2 = comp_next_label(comp);
526 for (int i = 0; i < n - 1; i++) {
527 c_if_cond(comp, pns->nodes[i], false, label2);
528 }
529 c_if_cond(comp, pns->nodes[n - 1], true, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000530 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100531 }
532 return;
Damiend99b0522013-12-21 18:17:45 +0000533 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100534 c_if_cond(comp, pns->nodes[0], !jump_if, label);
535 return;
536 }
537 }
538
539 // nothing special, fall back to default compiling for node and jump
540 compile_node(comp, pn);
541 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000542 EMIT_ARG(pop_jump_if_false, label);
Damien3a205172013-10-12 15:01:56 +0100543 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000544 EMIT_ARG(pop_jump_if_true, label);
Damien3a205172013-10-12 15:01:56 +0100545 }
546#endif
Damien429d7192013-10-04 19:53:11 +0100547}
548
549typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damiend99b0522013-12-21 18:17:45 +0000550void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100551
Damiend99b0522013-12-21 18:17:45 +0000552void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100553 if (assign_kind != ASSIGN_AUG_STORE) {
554 compile_node(comp, pns->nodes[0]);
555 }
556
Damiend99b0522013-12-21 18:17:45 +0000557 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
558 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
559 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
560 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100561 if (assign_kind != ASSIGN_AUG_STORE) {
562 for (int i = 0; i < n - 1; i++) {
563 compile_node(comp, pns1->nodes[i]);
564 }
565 }
Damiend99b0522013-12-21 18:17:45 +0000566 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
567 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100568 }
Damiend99b0522013-12-21 18:17:45 +0000569 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +0100570 printf("SyntaxError: can't assign to function call\n");
571 return;
Damiend99b0522013-12-21 18:17:45 +0000572 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100573 if (assign_kind == ASSIGN_AUG_STORE) {
574 EMIT(rot_three);
575 EMIT(store_subscr);
576 } else {
577 compile_node(comp, pns1->nodes[0]);
578 if (assign_kind == ASSIGN_AUG_LOAD) {
579 EMIT(dup_top_two);
Damien Georgeb9791222014-01-23 00:34:21 +0000580 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +0100581 } else {
582 EMIT(store_subscr);
583 }
584 }
Damiend99b0522013-12-21 18:17:45 +0000585 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
586 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100587 if (assign_kind == ASSIGN_AUG_LOAD) {
588 EMIT(dup_top);
Damien Georgeb9791222014-01-23 00:34:21 +0000589 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100590 } else {
591 if (assign_kind == ASSIGN_AUG_STORE) {
592 EMIT(rot_two);
593 }
Damien Georgeb9791222014-01-23 00:34:21 +0000594 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100595 }
596 } else {
597 // shouldn't happen
598 assert(0);
599 }
600 } else {
601 // shouldn't happen
602 assert(0);
603 }
604
Damiend99b0522013-12-21 18:17:45 +0000605 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100606 // SyntaxError, cannot assign
607 assert(0);
608 }
609}
610
Damiend99b0522013-12-21 18:17:45 +0000611void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
Damien429d7192013-10-04 19:53:11 +0100612 assert(n >= 0);
613 int have_star_index = -1;
614 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000615 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) {
Damien429d7192013-10-04 19:53:11 +0100616 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000617 EMIT_ARG(unpack_ex, i, n - i - 1);
Damien429d7192013-10-04 19:53:11 +0100618 have_star_index = i;
619 } else {
620 printf("SyntaxError: two starred expressions in assignment\n");
621 return;
622 }
623 }
624 }
625 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000626 EMIT_ARG(unpack_sequence, n);
Damien429d7192013-10-04 19:53:11 +0100627 }
628 for (int i = 0; i < n; i++) {
629 if (i == have_star_index) {
Damiend99b0522013-12-21 18:17:45 +0000630 c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100631 } else {
632 c_assign(comp, nodes[i], ASSIGN_STORE);
633 }
634 }
635}
636
637// assigns top of stack to pn
Damiend99b0522013-12-21 18:17:45 +0000638void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100639 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +0000640 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100641 assert(0);
Damiend99b0522013-12-21 18:17:45 +0000642 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
643 if (MP_PARSE_NODE_IS_ID(pn)) {
644 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100645 switch (assign_kind) {
646 case ASSIGN_STORE:
647 case ASSIGN_AUG_STORE:
Damien Georgeb9791222014-01-23 00:34:21 +0000648 EMIT_ARG(store_id, arg);
Damien429d7192013-10-04 19:53:11 +0100649 break;
650 case ASSIGN_AUG_LOAD:
Damien Georgeb9791222014-01-23 00:34:21 +0000651 EMIT_ARG(load_id, arg);
Damien429d7192013-10-04 19:53:11 +0100652 break;
653 }
654 } else {
655 printf("SyntaxError: can't assign to literal\n");
656 return;
657 }
658 } else {
Damiend99b0522013-12-21 18:17:45 +0000659 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
660 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +0100661 case PN_power:
662 // lhs is an index or attribute
663 c_assign_power(comp, pns, assign_kind);
664 break;
665
666 case PN_testlist_star_expr:
667 case PN_exprlist:
668 // lhs is a tuple
669 if (assign_kind != ASSIGN_STORE) {
670 goto bad_aug;
671 }
Damiend99b0522013-12-21 18:17:45 +0000672 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100673 break;
674
675 case PN_atom_paren:
676 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000677 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100678 // empty tuple
679 printf("SyntaxError: can't assign to ()\n");
680 return;
Damiend99b0522013-12-21 18:17:45 +0000681 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
682 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100683 goto testlist_comp;
684 } else {
685 // parenthesis around 1 item, is just that item
686 pn = pns->nodes[0];
687 goto tail_recursion;
688 }
689 break;
690
691 case PN_atom_bracket:
692 // lhs is something in brackets
693 if (assign_kind != ASSIGN_STORE) {
694 goto bad_aug;
695 }
Damiend99b0522013-12-21 18:17:45 +0000696 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100697 // empty list, assignment allowed
698 c_assign_tuple(comp, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000699 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
700 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100701 goto testlist_comp;
702 } else {
703 // brackets around 1 item
704 c_assign_tuple(comp, 1, &pns->nodes[0]);
705 }
706 break;
707
708 default:
Damiend99b0522013-12-21 18:17:45 +0000709 printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien429d7192013-10-04 19:53:11 +0100710 assert(0);
711 }
712 return;
713
714 testlist_comp:
715 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000716 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
717 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
718 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100719 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000720 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100721 c_assign_tuple(comp, 1, &pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000722 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100723 // sequence of many items
724 // TODO call c_assign_tuple instead
Damiend99b0522013-12-21 18:17:45 +0000725 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
Damien Georgeb9791222014-01-23 00:34:21 +0000726 EMIT_ARG(unpack_sequence, 1 + n);
Damien429d7192013-10-04 19:53:11 +0100727 c_assign(comp, pns->nodes[0], ASSIGN_STORE);
728 for (int i = 0; i < n; i++) {
729 c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
730 }
Damiend99b0522013-12-21 18:17:45 +0000731 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +0100732 // TODO not implemented
733 assert(0);
734 } else {
735 // sequence with 2 items
736 goto sequence_with_2_items;
737 }
738 } else {
739 // sequence with 2 items
740 sequence_with_2_items:
741 c_assign_tuple(comp, 2, pns->nodes);
742 }
743 return;
744 }
745 return;
746
747 bad_aug:
748 printf("SyntaxError: illegal expression for augmented assignment\n");
749}
750
751// stuff for lambda and comprehensions and generators
752void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
753 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000754 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100755 int nfree = 0;
756 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000757 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
758 id_info_t *id = &comp->scope_cur->id_info[i];
759 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
760 for (int j = 0; j < this_scope->id_info_len; j++) {
761 id_info_t *id2 = &this_scope->id_info[j];
762 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +0000763#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +0000764 EMIT_ARG(load_closure, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000765#else
766 // in Micro Python we load closures using LOAD_FAST
Damien Georgeb9791222014-01-23 00:34:21 +0000767 EMIT_ARG(load_fast, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000768#endif
Damien318aec62013-12-10 18:28:17 +0000769 nfree += 1;
770 }
771 }
Damien429d7192013-10-04 19:53:11 +0100772 }
773 }
774 }
775 if (nfree > 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000776 EMIT_ARG(build_tuple, nfree);
Damien429d7192013-10-04 19:53:11 +0100777 }
778
779 // make the function/closure
780 if (nfree == 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000781 EMIT_ARG(make_function, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100782 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000783 EMIT_ARG(make_closure, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100784 }
785}
786
Damiend99b0522013-12-21 18:17:45 +0000787void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
788 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
789 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
790 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100791 // this parameter has a default value
792 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
793 if (comp->have_bare_star) {
794 comp->param_pass_num_dict_params += 1;
795 if (comp->param_pass == 1) {
Damien Georgeb9791222014-01-23 00:34:21 +0000796 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100797 compile_node(comp, pns->nodes[2]);
798 }
799 } else {
800 comp->param_pass_num_default_params += 1;
801 if (comp->param_pass == 2) {
802 compile_node(comp, pns->nodes[2]);
803 }
804 }
805 }
Damiend99b0522013-12-21 18:17:45 +0000806 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
807 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
808 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100809 // bare star
810 comp->have_bare_star = true;
811 }
812 }
813}
814
815// leaves function object on stack
816// returns function name
Damiend99b0522013-12-21 18:17:45 +0000817qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100818 if (comp->pass == PASS_1) {
819 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000820 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100821 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000822 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100823 }
824
825 // save variables (probably don't need to do this, since we can't have nested definitions..?)
826 bool old_have_bare_star = comp->have_bare_star;
827 int old_param_pass = comp->param_pass;
828 int old_param_pass_num_dict_params = comp->param_pass_num_dict_params;
829 int old_param_pass_num_default_params = comp->param_pass_num_default_params;
830
831 // compile default parameters
832 comp->have_bare_star = false;
833 comp->param_pass = 1; // pass 1 does any default parameters after bare star
834 comp->param_pass_num_dict_params = 0;
835 comp->param_pass_num_default_params = 0;
836 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
837 comp->have_bare_star = false;
838 comp->param_pass = 2; // pass 2 does any default parameters before bare star
839 comp->param_pass_num_dict_params = 0;
840 comp->param_pass_num_default_params = 0;
841 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
842
843 // get the scope for this function
844 scope_t *fscope = (scope_t*)pns->nodes[4];
845
846 // make the function
847 close_over_variables_etc(comp, fscope, comp->param_pass_num_dict_params, comp->param_pass_num_default_params);
848
849 // restore variables
850 comp->have_bare_star = old_have_bare_star;
851 comp->param_pass = old_param_pass;
852 comp->param_pass_num_dict_params = old_param_pass_num_dict_params;
853 comp->param_pass_num_default_params = old_param_pass_num_default_params;
854
855 // return its name (the 'f' in "def f(...):")
856 return fscope->simple_name;
857}
858
859// leaves class object on stack
860// returns class name
Damiend99b0522013-12-21 18:17:45 +0000861qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100862 if (comp->pass == PASS_1) {
863 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000864 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100865 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000866 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100867 }
868
869 EMIT(load_build_class);
870
871 // scope for this class
872 scope_t *cscope = (scope_t*)pns->nodes[3];
873
874 // compile the class
875 close_over_variables_etc(comp, cscope, 0, 0);
876
877 // get its name
Damien Georgeb9791222014-01-23 00:34:21 +0000878 EMIT_ARG(load_const_id, cscope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100879
880 // nodes[1] has parent classes, if any
Damiend99b0522013-12-21 18:17:45 +0000881 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +0100882 // no parent classes
Damien Georgeb9791222014-01-23 00:34:21 +0000883 EMIT_ARG(call_function, 2, 0, false, false);
Damien429d7192013-10-04 19:53:11 +0100884 } else {
885 // have a parent class or classes
886 // TODO what if we have, eg, *a or **a in the parent list?
887 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +0000888 EMIT_ARG(call_function, 2 + list_len(pns->nodes[1], PN_arglist), 0, false, false);
Damien429d7192013-10-04 19:53:11 +0100889 }
890
891 // return its name (the 'C' in class C(...):")
892 return cscope->simple_name;
893}
894
Damien6cdd3af2013-10-05 18:08:26 +0100895// returns true if it was a built-in decorator (even if the built-in had an error)
Damiend99b0522013-12-21 18:17:45 +0000896static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000897 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100898 return false;
899 }
900
901 if (name_len != 2) {
902 printf("SyntaxError: invalid micropython decorator\n");
903 return true;
904 }
905
Damiend99b0522013-12-21 18:17:45 +0000906 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000907 if (attr == MP_QSTR_byte_code) {
Damien5ac1b2e2013-10-18 19:58:12 +0100908 *emit_options = EMIT_OPT_BYTE_CODE;
Damience89a212013-10-15 22:25:17 +0100909#if MICROPY_EMIT_NATIVE
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000910 } else if (attr == MP_QSTR_native) {
Damien6cdd3af2013-10-05 18:08:26 +0100911 *emit_options = EMIT_OPT_NATIVE_PYTHON;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000912 } else if (attr == MP_QSTR_viper) {
Damien7af3d192013-10-07 00:02:49 +0100913 *emit_options = EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100914#endif
Damien3ef4abb2013-10-12 16:53:13 +0100915#if MICROPY_EMIT_INLINE_THUMB
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000916 } else if (attr == MP_QSTR_asm_thumb) {
Damien5bfb7592013-10-05 18:41:24 +0100917 *emit_options = EMIT_OPT_ASM_THUMB;
Damienc025ebb2013-10-12 14:30:21 +0100918#endif
Damien6cdd3af2013-10-05 18:08:26 +0100919 } else {
Damience89a212013-10-15 22:25:17 +0100920 printf("SyntaxError: invalid micropython decorator '%s'\n", qstr_str(attr));
Damien6cdd3af2013-10-05 18:08:26 +0100921 }
922
923 return true;
924}
925
Damiend99b0522013-12-21 18:17:45 +0000926void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100927 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000928 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +0100929 int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
930
Damien6cdd3af2013-10-05 18:08:26 +0100931 // inherit emit options for this function/class definition
932 uint emit_options = comp->scope_cur->emit_options;
933
934 // compile each decorator
935 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100936 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000937 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
938 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100939
940 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +0000941 mp_parse_node_t *name_nodes;
Damien6cdd3af2013-10-05 18:08:26 +0100942 int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
943
944 // check for built-in decorators
945 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
946 // this was a built-in
947 num_built_in_decorators += 1;
948
949 } else {
950 // not a built-in, compile normally
951
952 // compile the decorator function
953 compile_node(comp, name_nodes[0]);
954 for (int i = 1; i < name_len; i++) {
Damiend99b0522013-12-21 18:17:45 +0000955 assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be
Damien Georgeb9791222014-01-23 00:34:21 +0000956 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i]));
Damien6cdd3af2013-10-05 18:08:26 +0100957 }
958
959 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +0000960 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +0100961 // call the decorator function with the arguments in nodes[1]
962 compile_node(comp, pns_decorator->nodes[1]);
963 }
Damien429d7192013-10-04 19:53:11 +0100964 }
965 }
966
967 // compile the body (funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +0000968 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +0100969 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +0000970 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100971 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Damiend99b0522013-12-21 18:17:45 +0000972 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100973 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +0100974 } else {
975 // shouldn't happen
976 assert(0);
977 }
978
979 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +0100980 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +0000981 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +0100982 }
983
984 // store func/class object into name
Damien Georgeb9791222014-01-23 00:34:21 +0000985 EMIT_ARG(store_id, body_name);
Damien429d7192013-10-04 19:53:11 +0100986}
987
Damiend99b0522013-12-21 18:17:45 +0000988void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +0100989 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +0100990 // store function object into function name
Damien Georgeb9791222014-01-23 00:34:21 +0000991 EMIT_ARG(store_id, fname);
Damien429d7192013-10-04 19:53:11 +0100992}
993
Damiend99b0522013-12-21 18:17:45 +0000994void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
995 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +0000996 EMIT_ARG(delete_id, MP_PARSE_NODE_LEAF_ARG(pn));
Damiend99b0522013-12-21 18:17:45 +0000997 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
998 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +0100999
1000 compile_node(comp, pns->nodes[0]); // base of the power node
1001
Damiend99b0522013-12-21 18:17:45 +00001002 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1003 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1004 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
1005 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001006 for (int i = 0; i < n - 1; i++) {
1007 compile_node(comp, pns1->nodes[i]);
1008 }
Damiend99b0522013-12-21 18:17:45 +00001009 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
1010 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +01001011 }
Damiend99b0522013-12-21 18:17:45 +00001012 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +01001013 // SyntaxError: can't delete a function call
1014 assert(0);
Damiend99b0522013-12-21 18:17:45 +00001015 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +01001016 compile_node(comp, pns1->nodes[0]);
1017 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +00001018 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
1019 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien Georgeb9791222014-01-23 00:34:21 +00001020 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001021 } else {
1022 // shouldn't happen
1023 assert(0);
1024 }
1025 } else {
1026 // shouldn't happen
1027 assert(0);
1028 }
1029
Damiend99b0522013-12-21 18:17:45 +00001030 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001031 // SyntaxError, cannot delete
1032 assert(0);
1033 }
Damiend99b0522013-12-21 18:17:45 +00001034 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
1035 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
1036 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) {
1037 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001038 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
1039
Damiend99b0522013-12-21 18:17:45 +00001040 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1041 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1042 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01001043 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00001044 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001045 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00001046 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01001047 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +00001048 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001049 c_del_stmt(comp, pns->nodes[0]);
1050 for (int i = 0; i < n; i++) {
1051 c_del_stmt(comp, pns1->nodes[i]);
1052 }
Damiend99b0522013-12-21 18:17:45 +00001053 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01001054 // TODO not implemented; can't del comprehension?
1055 assert(0);
1056 } else {
1057 // sequence with 2 items
1058 goto sequence_with_2_items;
1059 }
1060 } else {
1061 // sequence with 2 items
1062 sequence_with_2_items:
1063 c_del_stmt(comp, pns->nodes[0]);
1064 c_del_stmt(comp, pns->nodes[1]);
1065 }
1066 } else {
1067 // tuple with 1 element
1068 c_del_stmt(comp, pn);
1069 }
1070 } else {
1071 // not implemented
1072 assert(0);
1073 }
1074}
1075
Damiend99b0522013-12-21 18:17:45 +00001076void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001077 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
1078}
1079
Damiend99b0522013-12-21 18:17:45 +00001080void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001081 if (comp->break_label == 0) {
1082 printf("ERROR: cannot break from here\n");
1083 }
Damien Georgecbddb272014-02-01 20:08:18 +00001084 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001085}
1086
Damiend99b0522013-12-21 18:17:45 +00001087void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001088 if (comp->continue_label == 0) {
1089 printf("ERROR: cannot continue from here\n");
1090 }
Damien Georgecbddb272014-02-01 20:08:18 +00001091 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001092}
1093
Damiend99b0522013-12-21 18:17:45 +00001094void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +01001095 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
1096 printf("SyntaxError: 'return' outside function\n");
1097 comp->had_error = true;
1098 return;
1099 }
Damiend99b0522013-12-21 18:17:45 +00001100 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001101 // no argument to 'return', so return None
Damien Georgeb9791222014-01-23 00:34:21 +00001102 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damiend99b0522013-12-21 18:17:45 +00001103 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +01001104 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +00001105 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
1106 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001107
Damienb05d7072013-10-05 13:37:10 +01001108 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001109 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1110 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
1111 EMIT(return_value);
Damien Georgeb9791222014-01-23 00:34:21 +00001112 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001113 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1114 } else {
1115 compile_node(comp, pns->nodes[0]);
1116 }
1117 EMIT(return_value);
1118}
1119
Damiend99b0522013-12-21 18:17:45 +00001120void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001121 compile_node(comp, pns->nodes[0]);
1122 EMIT(pop_top);
1123}
1124
Damiend99b0522013-12-21 18:17:45 +00001125void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1126 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001127 // raise
Damien Georgeb9791222014-01-23 00:34:21 +00001128 EMIT_ARG(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001129 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001130 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001131 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001132 compile_node(comp, pns->nodes[0]);
1133 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001134 EMIT_ARG(raise_varargs, 2);
Damien429d7192013-10-04 19:53:11 +01001135 } else {
1136 // raise x
1137 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001138 EMIT_ARG(raise_varargs, 1);
Damien429d7192013-10-04 19:53:11 +01001139 }
1140}
1141
1142// q1 holds the base, q2 the full name
1143// eg a -> q1=q2=a
1144// a.b.c -> q1=a, q2=a.b.c
Damiend99b0522013-12-21 18:17:45 +00001145void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
Damien429d7192013-10-04 19:53:11 +01001146 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001147 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1148 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001149 // a name of the form x as y; unwrap it
Damiend99b0522013-12-21 18:17:45 +00001150 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001151 pn = pns->nodes[0];
1152 is_as = true;
1153 }
Damiend99b0522013-12-21 18:17:45 +00001154 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001155 // just a simple name
Damiend99b0522013-12-21 18:17:45 +00001156 *q2 = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001157 if (!is_as) {
1158 *q1 = *q2;
1159 }
Damien Georgeb9791222014-01-23 00:34:21 +00001160 EMIT_ARG(import_name, *q2);
Damiend99b0522013-12-21 18:17:45 +00001161 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
1162 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
1163 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) {
Damien429d7192013-10-04 19:53:11 +01001164 // a name of the form a.b.c
1165 if (!is_as) {
Damiend99b0522013-12-21 18:17:45 +00001166 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001167 }
Damiend99b0522013-12-21 18:17:45 +00001168 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001169 int len = n - 1;
1170 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00001171 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001172 }
Damien George55baff42014-01-21 21:40:13 +00001173 byte *q_ptr;
1174 byte *str_dest = qstr_build_start(len, &q_ptr);
Damien429d7192013-10-04 19:53:11 +01001175 for (int i = 0; i < n; i++) {
1176 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001177 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001178 }
Damien George55baff42014-01-21 21:40:13 +00001179 uint str_src_len;
1180 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00001181 memcpy(str_dest, str_src, str_src_len);
1182 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001183 }
Damien George55baff42014-01-21 21:40:13 +00001184 *q2 = qstr_build_end(q_ptr);
Damien Georgeb9791222014-01-23 00:34:21 +00001185 EMIT_ARG(import_name, *q2);
Damien429d7192013-10-04 19:53:11 +01001186 if (is_as) {
1187 for (int i = 1; i < n; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001188 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001189 }
1190 }
1191 } else {
1192 // TODO not implemented
1193 assert(0);
1194 }
1195 } else {
1196 // TODO not implemented
1197 assert(0);
1198 }
1199}
1200
Damiend99b0522013-12-21 18:17:45 +00001201void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgeb9791222014-01-23 00:34:21 +00001202 EMIT_ARG(load_const_small_int, 0); // ??
1203 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001204 qstr q1, q2;
1205 do_import_name(comp, pn, &q1, &q2);
Damien Georgeb9791222014-01-23 00:34:21 +00001206 EMIT_ARG(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001207}
1208
Damiend99b0522013-12-21 18:17:45 +00001209void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001210 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1211}
1212
Damiend99b0522013-12-21 18:17:45 +00001213void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1214 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001215 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001216
1217 // build the "fromlist" tuple
1218#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001219 EMIT_ARG(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001220#else
Damien Georgeb9791222014-01-23 00:34:21 +00001221 EMIT_ARG(load_const_str, QSTR_FROM_STR_STATIC("*"), false);
1222 EMIT_ARG(build_tuple, 1);
Damiendb4c3612013-12-10 17:27:24 +00001223#endif
1224
1225 // do the import
Damien429d7192013-10-04 19:53:11 +01001226 qstr dummy_q, id1;
1227 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1228 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001229
Damien429d7192013-10-04 19:53:11 +01001230 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001231 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001232
1233 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001234 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001235 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001236#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001237 {
1238 vstr_t *vstr = vstr_new();
1239 vstr_printf(vstr, "(");
1240 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001241 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1242 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1243 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001244 if (i > 0) {
1245 vstr_printf(vstr, ", ");
1246 }
1247 vstr_printf(vstr, "'");
Damien George55baff42014-01-21 21:40:13 +00001248 uint len;
1249 const byte *str = qstr_data(id2, &len);
1250 vstr_add_strn(vstr, (const char*)str, len);
Damien02f89412013-12-12 15:13:36 +00001251 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001252 }
Damien02f89412013-12-12 15:13:36 +00001253 if (n == 1) {
1254 vstr_printf(vstr, ",");
1255 }
1256 vstr_printf(vstr, ")");
Damien Georgeb9791222014-01-23 00:34:21 +00001257 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001258 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001259 }
Damiendb4c3612013-12-10 17:27:24 +00001260#else
1261 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001262 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1263 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1264 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001265 EMIT_ARG(load_const_str, id2, false);
Damiendb4c3612013-12-10 17:27:24 +00001266 }
Damien Georgeb9791222014-01-23 00:34:21 +00001267 EMIT_ARG(build_tuple, n);
Damiendb4c3612013-12-10 17:27:24 +00001268#endif
1269
1270 // do the import
Damien429d7192013-10-04 19:53:11 +01001271 qstr dummy_q, id1;
1272 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1273 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001274 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1275 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1276 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001277 EMIT_ARG(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001278 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001279 EMIT_ARG(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001280 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001281 EMIT_ARG(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001282 }
1283 }
1284 EMIT(pop_top);
1285 }
1286}
1287
Damiend99b0522013-12-21 18:17:45 +00001288void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001289 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001290 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1291 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001292 } else {
Damiend99b0522013-12-21 18:17:45 +00001293 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1294 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001295 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001296 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001297 }
Damien429d7192013-10-04 19:53:11 +01001298 }
1299 }
1300}
1301
Damiend99b0522013-12-21 18:17:45 +00001302void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001303 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001304 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1305 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001306 } else {
Damiend99b0522013-12-21 18:17:45 +00001307 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1308 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001309 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001310 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001311 }
Damien429d7192013-10-04 19:53:11 +01001312 }
1313 }
1314}
1315
Damiend99b0522013-12-21 18:17:45 +00001316void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001317 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001318 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien Georgeb9791222014-01-23 00:34:21 +00001319 EMIT_ARG(load_global, MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
Damiend99b0522013-12-21 18:17:45 +00001320 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001321 // assertion message
1322 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001323 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001324 }
Damien Georgeb9791222014-01-23 00:34:21 +00001325 EMIT_ARG(raise_varargs, 1);
1326 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001327}
1328
Damiend99b0522013-12-21 18:17:45 +00001329void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001330 // TODO proper and/or short circuiting
1331
Damienb05d7072013-10-05 13:37:10 +01001332 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001333
Damienb05d7072013-10-05 13:37:10 +01001334 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001335 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1336
1337 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001338 //if (!(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))) { // optimisation; doesn't align with CPython
Damien429d7192013-10-04 19:53:11 +01001339 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001340 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001341 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001342 }
1343 //}
Damien Georgeb9791222014-01-23 00:34:21 +00001344 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001345
Damiend99b0522013-12-21 18:17:45 +00001346 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001347 // compile elif blocks
1348
Damiend99b0522013-12-21 18:17:45 +00001349 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001350
Damiend99b0522013-12-21 18:17:45 +00001351 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001352 // multiple elif blocks
1353
Damiend99b0522013-12-21 18:17:45 +00001354 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001355 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001356 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
Damienb05d7072013-10-05 13:37:10 +01001357 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001358 c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition
1359
1360 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001361 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001362 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001363 }
Damien Georgeb9791222014-01-23 00:34:21 +00001364 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001365 }
1366
1367 } else {
1368 // a single elif block
1369
Damienb05d7072013-10-05 13:37:10 +01001370 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001371 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1372
1373 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001374 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001375 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001376 }
Damien Georgeb9791222014-01-23 00:34:21 +00001377 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001378 }
1379 }
1380
1381 // compile else block
1382 compile_node(comp, pns->nodes[3]); // can be null
1383
Damien Georgeb9791222014-01-23 00:34:21 +00001384 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001385}
1386
Damien Georgecbddb272014-02-01 20:08:18 +00001387#define START_BREAK_CONTINUE_BLOCK \
1388 int old_break_label = comp->break_label; \
1389 int old_continue_label = comp->continue_label; \
1390 int break_label = comp_next_label(comp); \
1391 int continue_label = comp_next_label(comp); \
1392 comp->break_label = break_label; \
1393 comp->continue_label = continue_label; \
1394 comp->break_continue_except_level = comp->cur_except_level;
1395
1396#define END_BREAK_CONTINUE_BLOCK \
1397 comp->break_label = old_break_label; \
1398 comp->continue_label = old_continue_label; \
1399 comp->break_continue_except_level = comp->cur_except_level;
1400
Damiend99b0522013-12-21 18:17:45 +00001401void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgecbddb272014-02-01 20:08:18 +00001402 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001403
Damience89a212013-10-15 22:25:17 +01001404 // compared to CPython, we have an optimised version of while loops
1405#if MICROPY_EMIT_CPYTHON
1406 int done_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001407 EMIT_ARG(setup_loop, break_label);
1408 EMIT_ARG(label_assign, continue_label);
Damien429d7192013-10-04 19:53:11 +01001409 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1410 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001411 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001412 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001413 }
Damien Georgeb9791222014-01-23 00:34:21 +00001414 EMIT_ARG(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001415 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1416 // this is a small hack to agree with CPython
1417 if (!node_is_const_true(pns->nodes[0])) {
1418 EMIT(pop_block);
1419 }
Damience89a212013-10-15 22:25:17 +01001420#else
1421 int top_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001422 EMIT_ARG(jump, continue_label);
1423 EMIT_ARG(label_assign, top_label);
Damience89a212013-10-15 22:25:17 +01001424 compile_node(comp, pns->nodes[1]); // body
Damien Georgeb9791222014-01-23 00:34:21 +00001425 EMIT_ARG(label_assign, continue_label);
Damience89a212013-10-15 22:25:17 +01001426 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1427#endif
1428
1429 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001430 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001431
1432 compile_node(comp, pns->nodes[2]); // else
1433
Damien Georgeb9791222014-01-23 00:34:21 +00001434 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001435}
1436
Damienf72fd0e2013-11-06 20:20:49 +00001437// TODO preload end and step onto stack if they are not constants
1438// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001439void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) {
Damien Georgecbddb272014-02-01 20:08:18 +00001440 START_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001441
1442 int top_label = comp_next_label(comp);
Damien George600ae732014-01-21 23:48:04 +00001443 int entry_label = comp_next_label(comp);
Damienf72fd0e2013-11-06 20:20:49 +00001444
1445 // compile: var = start
1446 compile_node(comp, pn_start);
1447 c_assign(comp, pn_var, ASSIGN_STORE);
1448
Damien Georgeb9791222014-01-23 00:34:21 +00001449 EMIT_ARG(jump, entry_label);
1450 EMIT_ARG(label_assign, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001451
Damienf3822fc2013-11-09 20:12:03 +00001452 // compile body
1453 compile_node(comp, pn_body);
1454
Damien Georgeb9791222014-01-23 00:34:21 +00001455 EMIT_ARG(label_assign, continue_label);
Damien George600ae732014-01-21 23:48:04 +00001456
Damienf72fd0e2013-11-06 20:20:49 +00001457 // compile: var += step
1458 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1459 compile_node(comp, pn_step);
Damien Georgeb9791222014-01-23 00:34:21 +00001460 EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_ADD);
Damienf72fd0e2013-11-06 20:20:49 +00001461 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1462
Damien Georgeb9791222014-01-23 00:34:21 +00001463 EMIT_ARG(label_assign, entry_label);
Damienf72fd0e2013-11-06 20:20:49 +00001464
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001465 // compile: if var <cond> end: goto top
Damienf72fd0e2013-11-06 20:20:49 +00001466 compile_node(comp, pn_var);
1467 compile_node(comp, pn_end);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001468 if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) {
Damien George9aa2a522014-02-01 23:04:09 +00001469 EMIT_ARG(binary_op, RT_BINARY_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001470 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001471 EMIT_ARG(binary_op, RT_BINARY_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001472 }
Damien Georgeb9791222014-01-23 00:34:21 +00001473 EMIT_ARG(pop_jump_if_true, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001474
1475 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001476 END_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001477
1478 compile_node(comp, pn_else);
1479
Damien Georgeb9791222014-01-23 00:34:21 +00001480 EMIT_ARG(label_assign, break_label);
Damienf72fd0e2013-11-06 20:20:49 +00001481}
1482
Damiend99b0522013-12-21 18:17:45 +00001483void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001484#if !MICROPY_EMIT_CPYTHON
1485 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1486 // this is actually slower, but uses no heap memory
1487 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001488 if (/*comp->scope_cur->emit_options == EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_power)) {
1489 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001490 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1491 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1492 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
1493 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
Damiend99b0522013-12-21 18:17:45 +00001494 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1495 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001496 int n_args = list_get(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001497 mp_parse_node_t pn_range_start;
1498 mp_parse_node_t pn_range_end;
1499 mp_parse_node_t pn_range_step;
1500 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001501 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001502 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001503 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001504 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001505 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001506 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001507 } else if (n_args == 2) {
1508 pn_range_start = args[0];
1509 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001510 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001511 } else {
1512 pn_range_start = args[0];
1513 pn_range_end = args[1];
1514 pn_range_step = args[2];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001515 // We need to know sign of step. This is possible only if it's constant
1516 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
1517 optimize = false;
1518 }
Damienf72fd0e2013-11-06 20:20:49 +00001519 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001520 }
1521 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001522 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1523 return;
1524 }
1525 }
1526 }
1527#endif
1528
Damien Georgecbddb272014-02-01 20:08:18 +00001529 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001530
Damienb05d7072013-10-05 13:37:10 +01001531 int pop_label = comp_next_label(comp);
1532 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001533
Damience89a212013-10-15 22:25:17 +01001534 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1535#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001536 EMIT_ARG(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001537#endif
1538
Damien429d7192013-10-04 19:53:11 +01001539 compile_node(comp, pns->nodes[1]); // iterator
1540 EMIT(get_iter);
Damien Georgecbddb272014-02-01 20:08:18 +00001541 EMIT_ARG(label_assign, continue_label);
Damien Georgeb9791222014-01-23 00:34:21 +00001542 EMIT_ARG(for_iter, pop_label);
Damien429d7192013-10-04 19:53:11 +01001543 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1544 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001545 if (!EMIT(last_emit_was_return_value)) {
Damien Georgecbddb272014-02-01 20:08:18 +00001546 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001547 }
Damien Georgeb9791222014-01-23 00:34:21 +00001548 EMIT_ARG(label_assign, pop_label);
Damien429d7192013-10-04 19:53:11 +01001549 EMIT(for_iter_end);
1550
1551 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001552 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001553
Damience89a212013-10-15 22:25:17 +01001554#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001555 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001556#endif
Damien429d7192013-10-04 19:53:11 +01001557
1558 compile_node(comp, pns->nodes[3]); // else (not tested)
1559
Damien Georgeb9791222014-01-23 00:34:21 +00001560 EMIT_ARG(label_assign, break_label);
1561 EMIT_ARG(label_assign, end_label);
Damien429d7192013-10-04 19:53:11 +01001562}
1563
Damiend99b0522013-12-21 18:17:45 +00001564void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) {
Damien429d7192013-10-04 19:53:11 +01001565 // this function is a bit of a hack at the moment
1566 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1567
1568 // setup code
1569 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001570 int l1 = comp_next_label(comp);
1571 int success_label = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001572
Damien Georgeb9791222014-01-23 00:34:21 +00001573 EMIT_ARG(setup_except, l1);
Damien Georgecbddb272014-02-01 20:08:18 +00001574 comp->cur_except_level += 1;
1575
Damien429d7192013-10-04 19:53:11 +01001576 compile_node(comp, pn_body); // body
1577 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001578 EMIT_ARG(jump, success_label);
1579 EMIT_ARG(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001580 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001581
1582 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001583 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1584 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001585
1586 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001587 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001588
Damiend99b0522013-12-21 18:17:45 +00001589 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001590 // this is a catch all exception handler
1591 if (i + 1 != n_except) {
1592 printf("SyntaxError: default 'except:' must be last\n");
1593 return;
1594 }
1595 } else {
1596 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001597 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1598 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1599 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1600 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001601 // handler binds the exception to a local
1602 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001603 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001604 }
1605 }
1606 EMIT(dup_top);
1607 compile_node(comp, pns_exception_expr);
Damien George9aa2a522014-02-01 23:04:09 +00001608 EMIT_ARG(binary_op, RT_BINARY_OP_EXCEPTION_MATCH);
Damien Georgeb9791222014-01-23 00:34:21 +00001609 EMIT_ARG(pop_jump_if_false, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001610 }
1611
1612 EMIT(pop_top);
1613
1614 if (qstr_exception_local == 0) {
1615 EMIT(pop_top);
1616 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001617 EMIT_ARG(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001618 }
1619
1620 EMIT(pop_top);
1621
Damiene2880aa2013-12-20 14:22:59 +00001622 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001623 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001624 l3 = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001625 EMIT_ARG(setup_finally, l3);
Damien Georgecbddb272014-02-01 20:08:18 +00001626 comp->cur_except_level += 1;
Damien429d7192013-10-04 19:53:11 +01001627 }
1628 compile_node(comp, pns_except->nodes[1]);
1629 if (qstr_exception_local != 0) {
1630 EMIT(pop_block);
1631 }
1632 EMIT(pop_except);
1633 if (qstr_exception_local != 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001634 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1635 EMIT_ARG(label_assign, l3);
1636 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1637 EMIT_ARG(store_id, qstr_exception_local);
1638 EMIT_ARG(delete_id, qstr_exception_local);
Damien Georgecbddb272014-02-01 20:08:18 +00001639
1640 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001641 EMIT(end_finally);
1642 }
Damien Georgeb9791222014-01-23 00:34:21 +00001643 EMIT_ARG(jump, l2);
1644 EMIT_ARG(label_assign, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001645 }
1646
Damien Georgecbddb272014-02-01 20:08:18 +00001647 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001648 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001649
Damien Georgeb9791222014-01-23 00:34:21 +00001650 EMIT_ARG(label_assign, success_label);
Damien429d7192013-10-04 19:53:11 +01001651 compile_node(comp, pn_else); // else block, can be null
Damien Georgeb9791222014-01-23 00:34:21 +00001652 EMIT_ARG(label_assign, l2);
1653 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001654}
1655
Damiend99b0522013-12-21 18:17:45 +00001656void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) {
Damien429d7192013-10-04 19:53:11 +01001657 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1658 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001659 int l_finally_block = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001660
Damien Georgeb9791222014-01-23 00:34:21 +00001661 EMIT_ARG(setup_finally, l_finally_block);
Damien Georgecbddb272014-02-01 20:08:18 +00001662 comp->cur_except_level += 1;
1663
Damien429d7192013-10-04 19:53:11 +01001664 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001665 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001666 compile_node(comp, pn_body);
1667 } else {
1668 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1669 }
1670 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001671 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1672 EMIT_ARG(label_assign, l_finally_block);
Damien429d7192013-10-04 19:53:11 +01001673 compile_node(comp, pn_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001674
1675 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001676 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001677
Damien Georgeb9791222014-01-23 00:34:21 +00001678 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001679}
1680
Damiend99b0522013-12-21 18:17:45 +00001681void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1682 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1683 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1684 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001685 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001686 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1687 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001688 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001689 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001690 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001691 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001692 // no finally
1693 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1694 } else {
1695 // have finally
Damiend99b0522013-12-21 18:17:45 +00001696 compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((mp_parse_node_struct_t*)pns2->nodes[2])->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001697 }
1698 } else {
1699 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001700 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001701 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001702 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001703 }
1704 } else {
1705 // shouldn't happen
1706 assert(0);
1707 }
1708}
1709
Damiend99b0522013-12-21 18:17:45 +00001710void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) {
Damien429d7192013-10-04 19:53:11 +01001711 if (n == 0) {
1712 // no more pre-bits, compile the body of the with
1713 compile_node(comp, body);
1714 } else {
Damienb05d7072013-10-05 13:37:10 +01001715 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001716 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001717 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001718 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001719 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001720 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001721 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1722 } else {
1723 // this pre-bit is just an expression
1724 compile_node(comp, nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001725 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001726 EMIT(pop_top);
1727 }
1728 // compile additional pre-bits and the body
1729 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1730 // finish this with block
1731 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001732 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1733 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001734 EMIT(with_cleanup);
1735 EMIT(end_finally);
1736 }
1737}
1738
Damiend99b0522013-12-21 18:17:45 +00001739void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001740 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001741 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001742 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1743 assert(n > 0);
1744
1745 // compile in a nested fashion
1746 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1747}
1748
Damiend99b0522013-12-21 18:17:45 +00001749void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1750 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001751 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1752 // for REPL, evaluate then print the expression
Damien Georgeb9791222014-01-23 00:34:21 +00001753 EMIT_ARG(load_id, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001754 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001755 EMIT_ARG(call_function, 1, 0, false, false);
Damien5ac1b2e2013-10-18 19:58:12 +01001756 EMIT(pop_top);
1757
Damien429d7192013-10-04 19:53:11 +01001758 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001759 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001760 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001761 // do nothing with a lonely constant
1762 } else {
1763 compile_node(comp, pns->nodes[0]); // just an expression
1764 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1765 }
Damien429d7192013-10-04 19:53:11 +01001766 }
1767 } else {
Damiend99b0522013-12-21 18:17:45 +00001768 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1769 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001770 if (kind == PN_expr_stmt_augassign) {
1771 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1772 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001773 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien George7e5fb242014-02-01 22:18:47 +00001774 rt_binary_op_t op;
Damiend99b0522013-12-21 18:17:45 +00001775 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
Damien George7e5fb242014-02-01 22:18:47 +00001776 case MP_TOKEN_DEL_PIPE_EQUAL: op = RT_BINARY_OP_INPLACE_OR; break;
1777 case MP_TOKEN_DEL_CARET_EQUAL: op = RT_BINARY_OP_INPLACE_XOR; break;
1778 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = RT_BINARY_OP_INPLACE_AND; break;
1779 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = RT_BINARY_OP_INPLACE_LSHIFT; break;
1780 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = RT_BINARY_OP_INPLACE_RSHIFT; break;
1781 case MP_TOKEN_DEL_PLUS_EQUAL: op = RT_BINARY_OP_INPLACE_ADD; break;
1782 case MP_TOKEN_DEL_MINUS_EQUAL: op = RT_BINARY_OP_INPLACE_SUBTRACT; break;
1783 case MP_TOKEN_DEL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_MULTIPLY; break;
1784 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
1785 case MP_TOKEN_DEL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
1786 case MP_TOKEN_DEL_PERCENT_EQUAL: op = RT_BINARY_OP_INPLACE_MODULO; break;
1787 case MP_TOKEN_DEL_DBL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_POWER; break;
1788 default: assert(0); op = RT_BINARY_OP_INPLACE_OR; // shouldn't happen
Damien429d7192013-10-04 19:53:11 +01001789 }
Damien George7e5fb242014-02-01 22:18:47 +00001790 EMIT_ARG(binary_op, op);
Damien429d7192013-10-04 19:53:11 +01001791 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1792 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001793 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1794 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001795 // following CPython, we store left-most first
1796 if (rhs > 0) {
1797 EMIT(dup_top);
1798 }
1799 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1800 for (int i = 0; i < rhs; i++) {
1801 if (i + 1 < rhs) {
1802 EMIT(dup_top);
1803 }
Damiend99b0522013-12-21 18:17:45 +00001804 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001805 }
1806 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001807 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1808 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1809 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1810 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001811 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001812 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1813 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001814 compile_node(comp, pns10->nodes[0]); // rhs
1815 compile_node(comp, pns10->nodes[1]); // rhs
1816 EMIT(rot_two);
1817 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1818 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001819 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1820 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1821 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1822 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001823 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001824 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1825 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001826 compile_node(comp, pns10->nodes[0]); // rhs
1827 compile_node(comp, pns10->nodes[1]); // rhs
1828 compile_node(comp, pns10->nodes[2]); // rhs
1829 EMIT(rot_three);
1830 EMIT(rot_two);
1831 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1832 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1833 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1834 } else {
1835 compile_node(comp, pns1->nodes[0]); // rhs
1836 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1837 }
1838 } else {
1839 // shouldn't happen
1840 assert(0);
1841 }
1842 }
1843}
1844
Damiend99b0522013-12-21 18:17:45 +00001845void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1846 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001847 compile_node(comp, pns->nodes[0]);
1848 for (int i = 1; i < num_nodes; i += 1) {
1849 compile_node(comp, pns->nodes[i]);
Damien Georgeb9791222014-01-23 00:34:21 +00001850 EMIT_ARG(binary_op, binary_op);
Damien429d7192013-10-04 19:53:11 +01001851 }
1852}
1853
Damiend99b0522013-12-21 18:17:45 +00001854void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1855 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1856 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001857
1858 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001859 int l_fail = comp_next_label(comp);
1860 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001861 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1862 compile_node(comp, pns->nodes[0]); // success value
Damien Georgeb9791222014-01-23 00:34:21 +00001863 EMIT_ARG(jump, l_end);
1864 EMIT_ARG(label_assign, l_fail);
1865 EMIT_ARG(set_stack_size, stack_size); // force stack size reset
Damien429d7192013-10-04 19:53:11 +01001866 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
Damien Georgeb9791222014-01-23 00:34:21 +00001867 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001868}
1869
Damiend99b0522013-12-21 18:17:45 +00001870void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001871 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001872 //mp_parse_node_t pn_params = pns->nodes[0];
1873 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001874
1875 if (comp->pass == PASS_1) {
1876 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001877 scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01001878 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001879 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001880 }
1881
1882 // get the scope for this lambda
1883 scope_t *this_scope = (scope_t*)pns->nodes[2];
1884
1885 // make the lambda
1886 close_over_variables_etc(comp, this_scope, 0, 0);
1887}
1888
Damiend99b0522013-12-21 18:17:45 +00001889void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001890 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001891 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001892 for (int i = 0; i < n; i += 1) {
1893 compile_node(comp, pns->nodes[i]);
1894 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001895 EMIT_ARG(jump_if_true_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001896 }
1897 }
Damien Georgeb9791222014-01-23 00:34:21 +00001898 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001899}
1900
Damiend99b0522013-12-21 18:17:45 +00001901void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001902 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001903 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001904 for (int i = 0; i < n; i += 1) {
1905 compile_node(comp, pns->nodes[i]);
1906 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001907 EMIT_ARG(jump_if_false_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001908 }
1909 }
Damien Georgeb9791222014-01-23 00:34:21 +00001910 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001911}
1912
Damiend99b0522013-12-21 18:17:45 +00001913void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001914 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001915 EMIT_ARG(unary_op, RT_UNARY_OP_NOT);
Damien429d7192013-10-04 19:53:11 +01001916}
1917
Damiend99b0522013-12-21 18:17:45 +00001918void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001919 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001920 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001921 compile_node(comp, pns->nodes[0]);
1922 bool multi = (num_nodes > 3);
1923 int l_fail = 0;
1924 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001925 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001926 }
1927 for (int i = 1; i + 1 < num_nodes; i += 2) {
1928 compile_node(comp, pns->nodes[i + 1]);
1929 if (i + 2 < num_nodes) {
1930 EMIT(dup_top);
1931 EMIT(rot_three);
1932 }
Damien George7e5fb242014-02-01 22:18:47 +00001933 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
1934 rt_binary_op_t op;
1935 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
Damien George9aa2a522014-02-01 23:04:09 +00001936 case MP_TOKEN_OP_LESS: op = RT_BINARY_OP_LESS; break;
1937 case MP_TOKEN_OP_MORE: op = RT_BINARY_OP_MORE; break;
1938 case MP_TOKEN_OP_DBL_EQUAL: op = RT_BINARY_OP_EQUAL; break;
1939 case MP_TOKEN_OP_LESS_EQUAL: op = RT_BINARY_OP_LESS_EQUAL; break;
1940 case MP_TOKEN_OP_MORE_EQUAL: op = RT_BINARY_OP_MORE_EQUAL; break;
1941 case MP_TOKEN_OP_NOT_EQUAL: op = RT_BINARY_OP_NOT_EQUAL; break;
1942 case MP_TOKEN_KW_IN: op = RT_BINARY_OP_IN; break;
1943 default: assert(0); op = RT_BINARY_OP_LESS; // shouldn't happen
Damien George7e5fb242014-02-01 22:18:47 +00001944 }
1945 EMIT_ARG(binary_op, op);
Damiend99b0522013-12-21 18:17:45 +00001946 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
1947 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
1948 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01001949 if (kind == PN_comp_op_not_in) {
Damien George9aa2a522014-02-01 23:04:09 +00001950 EMIT_ARG(binary_op, RT_BINARY_OP_NOT_IN);
Damien429d7192013-10-04 19:53:11 +01001951 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00001952 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien George9aa2a522014-02-01 23:04:09 +00001953 EMIT_ARG(binary_op, RT_BINARY_OP_IS);
Damien429d7192013-10-04 19:53:11 +01001954 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001955 EMIT_ARG(binary_op, RT_BINARY_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01001956 }
1957 } else {
1958 // shouldn't happen
1959 assert(0);
1960 }
1961 } else {
1962 // shouldn't happen
1963 assert(0);
1964 }
1965 if (i + 2 < num_nodes) {
Damien Georgeb9791222014-01-23 00:34:21 +00001966 EMIT_ARG(jump_if_false_or_pop, l_fail);
Damien429d7192013-10-04 19:53:11 +01001967 }
1968 }
1969 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001970 int l_end = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001971 EMIT_ARG(jump, l_end);
1972 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001973 EMIT(rot_two);
1974 EMIT(pop_top);
Damien Georgeb9791222014-01-23 00:34:21 +00001975 EMIT_ARG(label_assign, l_end);
1976 EMIT_ARG(set_stack_size, stack_size + 1); // force stack size
Damien429d7192013-10-04 19:53:11 +01001977 }
1978}
1979
Damiend99b0522013-12-21 18:17:45 +00001980void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001981 // TODO
1982 assert(0);
1983 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001984 //EMIT_ARG(unary_op, "UNARY_STAR");
Damien429d7192013-10-04 19:53:11 +01001985}
1986
Damiend99b0522013-12-21 18:17:45 +00001987void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001988 c_binary_op(comp, pns, RT_BINARY_OP_OR);
1989}
1990
Damiend99b0522013-12-21 18:17:45 +00001991void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001992 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
1993}
1994
Damiend99b0522013-12-21 18:17:45 +00001995void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001996 c_binary_op(comp, pns, RT_BINARY_OP_AND);
1997}
1998
Damiend99b0522013-12-21 18:17:45 +00001999void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2000 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002001 compile_node(comp, pns->nodes[0]);
2002 for (int i = 1; i + 1 < num_nodes; i += 2) {
2003 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002004 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002005 EMIT_ARG(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00002006 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002007 EMIT_ARG(binary_op, RT_BINARY_OP_RSHIFT);
Damien429d7192013-10-04 19:53:11 +01002008 } else {
2009 // shouldn't happen
2010 assert(0);
2011 }
2012 }
2013}
2014
Damiend99b0522013-12-21 18:17:45 +00002015void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2016 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002017 compile_node(comp, pns->nodes[0]);
2018 for (int i = 1; i + 1 < num_nodes; i += 2) {
2019 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002020 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002021 EMIT_ARG(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002022 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002023 EMIT_ARG(binary_op, RT_BINARY_OP_SUBTRACT);
Damien429d7192013-10-04 19:53:11 +01002024 } else {
2025 // shouldn't happen
2026 assert(0);
2027 }
2028 }
2029}
2030
Damiend99b0522013-12-21 18:17:45 +00002031void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2032 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002033 compile_node(comp, pns->nodes[0]);
2034 for (int i = 1; i + 1 < num_nodes; i += 2) {
2035 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002036 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002037 EMIT_ARG(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002038 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002039 EMIT_ARG(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002040 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002041 EMIT_ARG(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002042 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002043 EMIT_ARG(binary_op, RT_BINARY_OP_MODULO);
Damien429d7192013-10-04 19:53:11 +01002044 } else {
2045 // shouldn't happen
2046 assert(0);
2047 }
2048 }
2049}
2050
Damiend99b0522013-12-21 18:17:45 +00002051void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002052 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002053 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002054 EMIT_ARG(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002055 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002056 EMIT_ARG(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002057 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002058 EMIT_ARG(unary_op, RT_UNARY_OP_INVERT);
Damien429d7192013-10-04 19:53:11 +01002059 } else {
2060 // shouldn't happen
2061 assert(0);
2062 }
2063}
2064
Damiend99b0522013-12-21 18:17:45 +00002065void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool is_method_call) {
Damien429d7192013-10-04 19:53:11 +01002066 // function to call is on top of stack
2067
2068 int old_n_arg_keyword = comp->n_arg_keyword;
2069 bool old_have_star_arg = comp->have_star_arg;
2070 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2071 comp->n_arg_keyword = 0;
2072 comp->have_star_arg = false;
2073 comp->have_dbl_star_arg = false;
2074
2075 compile_node(comp, pns->nodes[0]); // arguments to function call; can be null
2076
2077 // compute number of positional arguments
2078 int n_positional = list_len(pns->nodes[0], PN_arglist) - comp->n_arg_keyword;
2079 if (comp->have_star_arg) {
2080 n_positional -= 1;
2081 }
2082 if (comp->have_dbl_star_arg) {
2083 n_positional -= 1;
2084 }
2085
2086 if (is_method_call) {
Damien Georgeb9791222014-01-23 00:34:21 +00002087 EMIT_ARG(call_method, n_positional, comp->n_arg_keyword, comp->have_star_arg, comp->have_dbl_star_arg);
Damien429d7192013-10-04 19:53:11 +01002088 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002089 EMIT_ARG(call_function, n_positional, comp->n_arg_keyword, comp->have_star_arg, comp->have_dbl_star_arg);
Damien429d7192013-10-04 19:53:11 +01002090 }
2091
2092 comp->n_arg_keyword = old_n_arg_keyword;
2093 comp->have_star_arg = old_have_star_arg;
2094 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2095}
2096
Damiend99b0522013-12-21 18:17:45 +00002097void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2098 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002099 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002100 if (i + 1 < num_nodes && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i], PN_trailer_period) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i + 1], PN_trailer_paren)) {
Damien429d7192013-10-04 19:53:11 +01002101 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002102 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2103 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
Damien Georgeb9791222014-01-23 00:34:21 +00002104 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien429d7192013-10-04 19:53:11 +01002105 compile_trailer_paren_helper(comp, pns_paren, true);
2106 i += 1;
2107 } else {
2108 compile_node(comp, pns->nodes[i]);
2109 }
2110 }
2111}
2112
Damiend99b0522013-12-21 18:17:45 +00002113void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002114 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002115 EMIT_ARG(binary_op, RT_BINARY_OP_POWER);
Damien429d7192013-10-04 19:53:11 +01002116}
2117
Damiend99b0522013-12-21 18:17:45 +00002118void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002119 // a list of strings
Damien63321742013-12-10 17:41:49 +00002120
2121 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002122 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002123 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002124 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002125 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002126 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2127 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2128 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002129 if (i == 0) {
2130 string_kind = pn_kind;
2131 } else if (pn_kind != string_kind) {
2132 printf("SyntaxError: cannot mix bytes and nonbytes literals\n");
2133 return;
2134 }
Damien George55baff42014-01-21 21:40:13 +00002135 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01002136 }
Damien63321742013-12-10 17:41:49 +00002137
Damien63321742013-12-10 17:41:49 +00002138 // concatenate string/bytes
Damien George55baff42014-01-21 21:40:13 +00002139 byte *q_ptr;
2140 byte *s_dest = qstr_build_start(n_bytes, &q_ptr);
Damien63321742013-12-10 17:41:49 +00002141 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00002142 uint s_len;
2143 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00002144 memcpy(s_dest, s, s_len);
2145 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002146 }
Damien George55baff42014-01-21 21:40:13 +00002147 qstr q = qstr_build_end(q_ptr);
Damien63321742013-12-10 17:41:49 +00002148
Damien Georgeb9791222014-01-23 00:34:21 +00002149 EMIT_ARG(load_const_str, q, string_kind == MP_PARSE_NODE_BYTES);
Damien429d7192013-10-04 19:53:11 +01002150}
2151
2152// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002153void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2154 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2155 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2156 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002157
2158 if (comp->pass == PASS_1) {
2159 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002160 scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002161 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002162 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002163 }
2164
2165 // get the scope for this comprehension
2166 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2167
2168 // compile the comprehension
2169 close_over_variables_etc(comp, this_scope, 0, 0);
2170
2171 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2172 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002173 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01002174}
2175
Damiend99b0522013-12-21 18:17:45 +00002176void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2177 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002178 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002179 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2180 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2181 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2182 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2183 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2184 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2185 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002186 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002187 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002188 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002189 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002190 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002191 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002192 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002193 // generator expression
2194 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2195 } else {
2196 // tuple with 2 items
2197 goto tuple_with_2_items;
2198 }
2199 } else {
2200 // tuple with 2 items
2201 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002202 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002203 }
2204 } else {
2205 // parenthesis around a single item, is just that item
2206 compile_node(comp, pns->nodes[0]);
2207 }
2208}
2209
Damiend99b0522013-12-21 18:17:45 +00002210void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2211 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002212 // empty list
Damien Georgeb9791222014-01-23 00:34:21 +00002213 EMIT_ARG(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002214 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2215 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2216 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2217 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2218 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002219 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002220 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002221 compile_node(comp, pns2->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002222 EMIT_ARG(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002223 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002224 // list of many items
2225 compile_node(comp, pns2->nodes[0]);
2226 compile_generic_all_nodes(comp, pns3);
Damien Georgeb9791222014-01-23 00:34:21 +00002227 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
Damiend99b0522013-12-21 18:17:45 +00002228 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002229 // list comprehension
2230 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2231 } else {
2232 // list with 2 items
2233 goto list_with_2_items;
2234 }
2235 } else {
2236 // list with 2 items
2237 list_with_2_items:
2238 compile_node(comp, pns2->nodes[0]);
2239 compile_node(comp, pns2->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00002240 EMIT_ARG(build_list, 2);
Damien429d7192013-10-04 19:53:11 +01002241 }
2242 } else {
2243 // list with 1 item
2244 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002245 EMIT_ARG(build_list, 1);
Damien429d7192013-10-04 19:53:11 +01002246 }
2247}
2248
Damiend99b0522013-12-21 18:17:45 +00002249void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2250 mp_parse_node_t pn = pns->nodes[0];
2251 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002252 // empty dict
Damien Georgeb9791222014-01-23 00:34:21 +00002253 EMIT_ARG(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002254 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2255 pns = (mp_parse_node_struct_t*)pn;
2256 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002257 // dict with one element
Damien Georgeb9791222014-01-23 00:34:21 +00002258 EMIT_ARG(build_map, 1);
Damien429d7192013-10-04 19:53:11 +01002259 compile_node(comp, pn);
2260 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002261 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2262 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2263 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2264 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002265 // dict/set with multiple elements
2266
2267 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002268 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002269 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2270
2271 // first element sets whether it's a dict or set
2272 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002273 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002274 // a dictionary
Damien Georgeb9791222014-01-23 00:34:21 +00002275 EMIT_ARG(build_map, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002276 compile_node(comp, pns->nodes[0]);
2277 EMIT(store_map);
2278 is_dict = true;
2279 } else {
2280 // a set
2281 compile_node(comp, pns->nodes[0]); // 1st value of set
2282 is_dict = false;
2283 }
2284
2285 // process rest of elements
2286 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002287 mp_parse_node_t pn = nodes[i];
2288 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002289 compile_node(comp, pn);
2290 if (is_dict) {
2291 if (!is_key_value) {
2292 printf("SyntaxError?: expecting key:value for dictionary");
2293 return;
2294 }
2295 EMIT(store_map);
2296 } else {
2297 if (is_key_value) {
2298 printf("SyntaxError?: expecting just a value for set");
2299 return;
2300 }
2301 }
2302 }
2303
2304 // if it's a set, build it
2305 if (!is_dict) {
Damien Georgeb9791222014-01-23 00:34:21 +00002306 EMIT_ARG(build_set, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002307 }
Damiend99b0522013-12-21 18:17:45 +00002308 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002309 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002310 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002311 // a dictionary comprehension
2312 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2313 } else {
2314 // a set comprehension
2315 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2316 }
2317 } else {
2318 // shouldn't happen
2319 assert(0);
2320 }
2321 } else {
2322 // set with one element
2323 goto set_with_one_element;
2324 }
2325 } else {
2326 // set with one element
2327 set_with_one_element:
2328 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002329 EMIT_ARG(build_set, 1);
Damien429d7192013-10-04 19:53:11 +01002330 }
2331}
2332
Damiend99b0522013-12-21 18:17:45 +00002333void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002334 compile_trailer_paren_helper(comp, pns, false);
2335}
2336
Damiend99b0522013-12-21 18:17:45 +00002337void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002338 // object who's index we want is on top of stack
2339 compile_node(comp, pns->nodes[0]); // the index
Damien Georgeb9791222014-01-23 00:34:21 +00002340 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +01002341}
2342
Damiend99b0522013-12-21 18:17:45 +00002343void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002344 // object who's attribute we want is on top of stack
Damien Georgeb9791222014-01-23 00:34:21 +00002345 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002346}
2347
Damiend99b0522013-12-21 18:17:45 +00002348void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2349 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2350 mp_parse_node_t pn = pns->nodes[0];
2351 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002352 // [?:]
Damien Georgeb9791222014-01-23 00:34:21 +00002353 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
2354 EMIT_ARG(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002355 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2356 pns = (mp_parse_node_struct_t*)pn;
2357 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
Damien Georgeb9791222014-01-23 00:34:21 +00002358 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002359 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002360 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002361 // [?::]
Damien Georgeb9791222014-01-23 00:34:21 +00002362 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002363 } else {
2364 // [?::x]
2365 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002366 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002367 }
Damiend99b0522013-12-21 18:17:45 +00002368 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002369 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002370 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2371 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2372 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2373 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002374 // [?:x:]
Damien Georgeb9791222014-01-23 00:34:21 +00002375 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002376 } else {
2377 // [?:x:x]
2378 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002379 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002380 }
2381 } else {
2382 // [?:x]
2383 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002384 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002385 }
2386 } else {
2387 // [?:x]
2388 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002389 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002390 }
2391}
2392
Damiend99b0522013-12-21 18:17:45 +00002393void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002394 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002395 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2396 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002397}
2398
Damiend99b0522013-12-21 18:17:45 +00002399void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgeb9791222014-01-23 00:34:21 +00002400 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002401 compile_subscript_3_helper(comp, pns);
2402}
2403
Damiend99b0522013-12-21 18:17:45 +00002404void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002405 // if this is called then we are compiling a dict key:value pair
2406 compile_node(comp, pns->nodes[1]); // value
2407 compile_node(comp, pns->nodes[0]); // key
2408}
2409
Damiend99b0522013-12-21 18:17:45 +00002410void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002411 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002412 // store class object into class name
Damien Georgeb9791222014-01-23 00:34:21 +00002413 EMIT_ARG(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002414}
2415
Damiend99b0522013-12-21 18:17:45 +00002416void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002417 if (comp->have_star_arg) {
2418 printf("SyntaxError?: can't have multiple *x\n");
2419 return;
2420 }
2421 comp->have_star_arg = true;
2422 compile_node(comp, pns->nodes[0]);
2423}
2424
Damiend99b0522013-12-21 18:17:45 +00002425void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002426 if (comp->have_dbl_star_arg) {
2427 printf("SyntaxError?: can't have multiple **x\n");
2428 return;
2429 }
2430 comp->have_dbl_star_arg = true;
2431 compile_node(comp, pns->nodes[0]);
2432}
2433
Damiend99b0522013-12-21 18:17:45 +00002434void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2435 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2436 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2437 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2438 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002439 printf("SyntaxError?: lhs of keyword argument must be an id\n");
2440 return;
2441 }
Damien Georgeb9791222014-01-23 00:34:21 +00002442 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002443 compile_node(comp, pns2->nodes[0]);
2444 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002445 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002446 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2447 } else {
2448 // shouldn't happen
2449 assert(0);
2450 }
2451}
2452
Damiend99b0522013-12-21 18:17:45 +00002453void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002454 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
2455 printf("SyntaxError: 'yield' outside function\n");
2456 return;
2457 }
Damiend99b0522013-12-21 18:17:45 +00002458 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00002459 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002460 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002461 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2462 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002463 compile_node(comp, pns->nodes[0]);
2464 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002465 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002466 EMIT(yield_from);
2467 } else {
2468 compile_node(comp, pns->nodes[0]);
2469 EMIT(yield_value);
2470 }
2471}
2472
Damiend99b0522013-12-21 18:17:45 +00002473typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Damien429d7192013-10-04 19:53:11 +01002474static compile_function_t compile_function[] = {
2475 NULL,
2476#define nc NULL
2477#define c(f) compile_##f
2478#define DEF_RULE(rule, comp, kind, arg...) comp,
2479#include "grammar.h"
2480#undef nc
2481#undef c
2482#undef DEF_RULE
2483};
2484
Damiend99b0522013-12-21 18:17:45 +00002485void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2486 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002487 // pass
Damiend99b0522013-12-21 18:17:45 +00002488 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien George08d07552014-01-29 18:58:52 +00002489 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +00002490 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002491 case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
2492 case MP_PARSE_NODE_SMALL_INT: EMIT_ARG(load_const_small_int, arg); break;
2493 case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
2494 case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
2495 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
2496 case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
Damiend99b0522013-12-21 18:17:45 +00002497 case MP_PARSE_NODE_TOKEN:
2498 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002499 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002500 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002501 // do nothing
2502 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002503 EMIT_ARG(load_const_tok, arg);
Damien91d387d2013-10-09 15:09:52 +01002504 }
2505 break;
Damien429d7192013-10-04 19:53:11 +01002506 default: assert(0);
2507 }
2508 } else {
Damiend99b0522013-12-21 18:17:45 +00002509 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien Georgeb9791222014-01-23 00:34:21 +00002510 EMIT_ARG(set_line_number, pns->source_line);
Damiend99b0522013-12-21 18:17:45 +00002511 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002512 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002513 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien Georgecbd2f742014-01-19 11:48:48 +00002514#if MICROPY_DEBUG_PRINTERS
2515 mp_parse_node_print(pn, 0);
2516#endif
Damien429d7192013-10-04 19:53:11 +01002517 assert(0);
2518 } else {
2519 f(comp, pns);
2520 }
2521 }
2522}
2523
Damiend99b0522013-12-21 18:17:45 +00002524void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star, bool allow_annotations) {
Damien429d7192013-10-04 19:53:11 +01002525 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002526 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002527 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2528 if (MP_PARSE_NODE_IS_ID(pn)) {
2529 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002530 if (comp->have_bare_star) {
2531 // comes after a bare star, so doesn't count as a parameter
2532 } else {
2533 comp->scope_cur->num_params += 1;
2534 }
Damienb14de212013-10-06 00:28:28 +01002535 } else {
Damiend99b0522013-12-21 18:17:45 +00002536 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2537 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2538 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2539 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002540 //int node_index = 1; unused
2541 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002542 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002543 // this parameter has an annotation
2544 pn_annotation = pns->nodes[1];
2545 }
2546 //node_index = 2; unused
2547 }
2548 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002549 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002550 // this parameter has a default value
2551 if (comp->have_bare_star) {
2552 comp->scope_cur->num_dict_params += 1;
2553 } else {
2554 comp->scope_cur->num_default_params += 1;
2555 }
2556 }
2557 */
2558 if (comp->have_bare_star) {
2559 // comes after a bare star, so doesn't count as a parameter
2560 } else {
2561 comp->scope_cur->num_params += 1;
2562 }
Damiend99b0522013-12-21 18:17:45 +00002563 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2564 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002565 // bare star
2566 // TODO see http://www.python.org/dev/peps/pep-3102/
2567 comp->have_bare_star = true;
2568 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002569 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002570 // named star
2571 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002572 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2573 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002574 // named star with annotation
2575 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002576 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2577 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002578 pn_annotation = pns->nodes[1];
2579 } else {
2580 // shouldn't happen
2581 assert(0);
2582 }
Damiend99b0522013-12-21 18:17:45 +00002583 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2584 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2585 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002586 // this parameter has an annotation
2587 pn_annotation = pns->nodes[1];
2588 }
2589 comp->scope_cur->flags |= SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002590 } else {
Damienb14de212013-10-06 00:28:28 +01002591 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002592 assert(0);
2593 }
Damien429d7192013-10-04 19:53:11 +01002594 }
2595
2596 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002597 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002598 // TODO this parameter has an annotation
2599 }
2600 bool added;
2601 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2602 if (!added) {
2603 printf("SyntaxError?: same name used for parameter; %s\n", qstr_str(param_name));
2604 return;
2605 }
2606 id_info->param = true;
2607 id_info->kind = ID_INFO_KIND_LOCAL;
2608 }
2609}
2610
Damiend99b0522013-12-21 18:17:45 +00002611void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002612 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2613}
2614
Damiend99b0522013-12-21 18:17:45 +00002615void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002616 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2617}
2618
Damiend99b0522013-12-21 18:17:45 +00002619void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_t pn_iter, mp_parse_node_t pn_inner_expr, int l_top, int for_depth) {
Damien429d7192013-10-04 19:53:11 +01002620 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002621 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002622 // no more nested if/for; compile inner expression
2623 compile_node(comp, pn_inner_expr);
2624 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002625 EMIT_ARG(list_append, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002626 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002627 EMIT_ARG(map_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002628 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002629 EMIT_ARG(set_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002630 } else {
2631 EMIT(yield_value);
2632 EMIT(pop_top);
2633 }
Damiend99b0522013-12-21 18:17:45 +00002634 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002635 // if condition
Damiend99b0522013-12-21 18:17:45 +00002636 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002637 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2638 pn_iter = pns_comp_if->nodes[1];
2639 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002640 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002641 // for loop
Damiend99b0522013-12-21 18:17:45 +00002642 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002643 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002644 int l_end2 = comp_next_label(comp);
2645 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002646 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002647 EMIT_ARG(label_assign, l_top2);
2648 EMIT_ARG(for_iter, l_end2);
Damien429d7192013-10-04 19:53:11 +01002649 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2650 compile_scope_comp_iter(comp, pns_comp_for2->nodes[2], pn_inner_expr, l_top2, for_depth + 1);
Damien Georgeb9791222014-01-23 00:34:21 +00002651 EMIT_ARG(jump, l_top2);
2652 EMIT_ARG(label_assign, l_end2);
Damien429d7192013-10-04 19:53:11 +01002653 EMIT(for_iter_end);
2654 } else {
2655 // shouldn't happen
2656 assert(0);
2657 }
2658}
2659
Damiend99b0522013-12-21 18:17:45 +00002660void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002661 // see http://www.python.org/dev/peps/pep-0257/
2662
2663 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002664 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002665 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002666 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002667 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002668 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2669 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002670 for (int i = 0; i < num_nodes; i++) {
2671 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002672 if (!(MP_PARSE_NODE_IS_LEAF(pn) && MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN && MP_PARSE_NODE_LEAF_ARG(pn) == MP_TOKEN_NEWLINE)) {
Damiene388f102013-12-12 15:24:38 +00002673 // not a newline, so this is the first statement; finish search
2674 break;
2675 }
2676 }
2677 // if we didn't find a non-newline then it's okay to fall through; pn will be a newline and so doc-string test below will fail gracefully
Damiend99b0522013-12-21 18:17:45 +00002678 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002679 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002680 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002681 } else {
2682 return;
2683 }
2684
2685 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002686 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2687 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2688 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2689 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2690 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002691 compile_node(comp, pns->nodes[0]); // a doc string
2692 // store doc string
Damien Georgeb9791222014-01-23 00:34:21 +00002693 EMIT_ARG(store_id, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002694 }
2695 }
2696 }
2697}
2698
2699void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2700 comp->pass = pass;
2701 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002702 comp->next_label = 1;
Damien Georgeb9791222014-01-23 00:34:21 +00002703 EMIT_ARG(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002704
2705 if (comp->pass == PASS_1) {
2706 scope->stack_size = 0;
2707 }
2708
Damien5ac1b2e2013-10-18 19:58:12 +01002709#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002710 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002711 scope_print_info(scope);
2712 }
Damien5ac1b2e2013-10-18 19:58:12 +01002713#endif
Damien429d7192013-10-04 19:53:11 +01002714
2715 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002716 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2717 assert(scope->kind == SCOPE_MODULE);
2718 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2719 compile_node(comp, pns->nodes[0]); // compile the expression
2720 EMIT(return_value);
2721 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002722 if (!comp->is_repl) {
2723 check_for_doc_string(comp, scope->pn);
2724 }
Damien429d7192013-10-04 19:53:11 +01002725 compile_node(comp, scope->pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002726 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002727 EMIT(return_value);
2728 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002729 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2730 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2731 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002732
2733 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002734 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002735 if (comp->pass == PASS_1) {
2736 comp->have_bare_star = false;
2737 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2738 }
2739
Damiend99b0522013-12-21 18:17:45 +00002740 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // 2 is something...
Damien429d7192013-10-04 19:53:11 +01002741
2742 compile_node(comp, pns->nodes[3]); // 3 is function body
2743 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002744 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002745 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002746 EMIT(return_value);
2747 }
2748 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002749 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2750 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2751 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002752
2753 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002754 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002755 if (comp->pass == PASS_1) {
2756 comp->have_bare_star = false;
2757 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2758 }
2759
2760 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2761 EMIT(return_value);
2762 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2763 // a bit of a hack at the moment
2764
Damiend99b0522013-12-21 18:17:45 +00002765 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2766 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2767 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2768 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2769 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002770
Damien George55baff42014-01-21 21:40:13 +00002771 qstr qstr_arg = QSTR_FROM_STR_STATIC(".0");
Damien429d7192013-10-04 19:53:11 +01002772 if (comp->pass == PASS_1) {
2773 bool added;
2774 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2775 assert(added);
2776 id_info->kind = ID_INFO_KIND_LOCAL;
2777 scope->num_params = 1;
2778 }
2779
2780 if (scope->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002781 EMIT_ARG(build_list, 0);
Damien429d7192013-10-04 19:53:11 +01002782 } else if (scope->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002783 EMIT_ARG(build_map, 0);
Damien429d7192013-10-04 19:53:11 +01002784 } else if (scope->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002785 EMIT_ARG(build_set, 0);
Damien429d7192013-10-04 19:53:11 +01002786 }
2787
Damienb05d7072013-10-05 13:37:10 +01002788 int l_end = comp_next_label(comp);
2789 int l_top = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002790 EMIT_ARG(load_id, qstr_arg);
2791 EMIT_ARG(label_assign, l_top);
2792 EMIT_ARG(for_iter, l_end);
Damien429d7192013-10-04 19:53:11 +01002793 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2794 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
Damien Georgeb9791222014-01-23 00:34:21 +00002795 EMIT_ARG(jump, l_top);
2796 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002797 EMIT(for_iter_end);
2798
2799 if (scope->kind == SCOPE_GEN_EXPR) {
Damien Georgeb9791222014-01-23 00:34:21 +00002800 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002801 }
2802 EMIT(return_value);
2803 } else {
2804 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00002805 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2806 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2807 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01002808
2809 if (comp->pass == PASS_1) {
2810 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002811 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01002812 assert(added);
2813 id_info->kind = ID_INFO_KIND_LOCAL;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002814 id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
Damien429d7192013-10-04 19:53:11 +01002815 assert(added);
2816 id_info->kind = ID_INFO_KIND_LOCAL;
2817 id_info->param = true;
2818 scope->num_params = 1; // __locals__ is the parameter
2819 }
2820
Damien Georgeb9791222014-01-23 00:34:21 +00002821 EMIT_ARG(load_id, MP_QSTR___locals__);
Damien429d7192013-10-04 19:53:11 +01002822 EMIT(store_locals);
Damien Georgeb9791222014-01-23 00:34:21 +00002823 EMIT_ARG(load_id, MP_QSTR___name__);
2824 EMIT_ARG(store_id, MP_QSTR___module__);
2825 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
2826 EMIT_ARG(store_id, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01002827
2828 check_for_doc_string(comp, pns->nodes[2]);
2829 compile_node(comp, pns->nodes[2]); // 2 is class body
2830
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002831 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01002832 assert(id != NULL);
2833 if (id->kind == ID_INFO_KIND_LOCAL) {
Damien Georgeb9791222014-01-23 00:34:21 +00002834 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002835 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002836#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00002837 EMIT_ARG(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002838#else
Damien Georgeb9791222014-01-23 00:34:21 +00002839 EMIT_ARG(load_fast, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002840#endif
Damien429d7192013-10-04 19:53:11 +01002841 }
2842 EMIT(return_value);
2843 }
2844
Damien415eb6f2013-10-05 12:19:06 +01002845 EMIT(end_pass);
Damien826005c2013-10-05 23:17:28 +01002846}
2847
2848void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2849 comp->pass = pass;
2850 comp->scope_cur = scope;
2851 comp->next_label = 1;
2852
2853 if (scope->kind != SCOPE_FUNCTION) {
2854 printf("Error: inline assembler must be a function\n");
2855 return;
2856 }
2857
Damiena2f2f7d2013-10-06 00:14:13 +01002858 if (comp->pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002859 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur);
Damiena2f2f7d2013-10-06 00:14:13 +01002860 }
2861
Damien826005c2013-10-05 23:17:28 +01002862 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002863 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2864 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2865 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002866
Damiend99b0522013-12-21 18:17:45 +00002867 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002868
Damiena2f2f7d2013-10-06 00:14:13 +01002869 // parameters are in pns->nodes[1]
2870 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002871 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002872 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
Damien Georgeb9791222014-01-23 00:34:21 +00002873 scope->num_params = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
Damiena2f2f7d2013-10-06 00:14:13 +01002874 }
2875
Damiend99b0522013-12-21 18:17:45 +00002876 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002877
Damiend99b0522013-12-21 18:17:45 +00002878 mp_parse_node_t pn_body = pns->nodes[3]; // body
2879 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002880 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2881
Damien Georgecbd2f742014-01-19 11:48:48 +00002882 /*
Damien826005c2013-10-05 23:17:28 +01002883 if (comp->pass == PASS_3) {
2884 //printf("----\n");
2885 scope_print_info(scope);
2886 }
Damien Georgecbd2f742014-01-19 11:48:48 +00002887 */
Damien826005c2013-10-05 23:17:28 +01002888
2889 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002890 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2891 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2892 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2893 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2894 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2895 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2896 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2897 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2898 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2899 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2900 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2901 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2902 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002903 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2904
2905 // emit instructions
2906 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00002907 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien826005c2013-10-05 23:17:28 +01002908 printf("SyntaxError: inline assembler 'label' requires 1 argument\n");
2909 return;
2910 }
2911 int lab = comp_next_label(comp);
2912 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002913 EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01002914 }
2915 } else {
2916 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002917 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
Damien826005c2013-10-05 23:17:28 +01002918 }
2919 }
2920 }
2921
2922 if (comp->pass > PASS_1) {
2923 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01002924 }
Damien429d7192013-10-04 19:53:11 +01002925}
2926
2927void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
2928 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00002929 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01002930 scope->num_locals = 0;
2931 for (int i = 0; i < scope->id_info_len; i++) {
2932 id_info_t *id = &scope->id_info[i];
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002933 if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01002934 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
2935 continue;
2936 }
2937 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
2938 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
2939 }
Damien9ecbcff2013-12-11 00:41:43 +00002940 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01002941 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
2942 id->local_num = scope->num_locals;
2943 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002944 }
2945 }
2946
2947 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00002948#if MICROPY_EMIT_CPYTHON
2949 int num_cell = 0;
2950#endif
Damien9ecbcff2013-12-11 00:41:43 +00002951 for (int i = 0; i < scope->id_info_len; i++) {
2952 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00002953#if MICROPY_EMIT_CPYTHON
2954 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00002955 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00002956 id->local_num = num_cell;
2957 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002958 }
Damien George6baf76e2013-12-30 22:32:17 +00002959#else
2960 // in Micro Python the cells come right after the fast locals
2961 // parameters are not counted here, since they remain at the start
2962 // of the locals, even if they are cell vars
2963 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
2964 id->local_num = scope->num_locals;
2965 scope->num_locals += 1;
2966 }
2967#endif
Damien9ecbcff2013-12-11 00:41:43 +00002968 }
Damien9ecbcff2013-12-11 00:41:43 +00002969
2970 // compute the index of free vars (freevars[idx] in CPython)
2971 // make sure they are in the order of the parent scope
2972 if (scope->parent != NULL) {
2973 int num_free = 0;
2974 for (int i = 0; i < scope->parent->id_info_len; i++) {
2975 id_info_t *id = &scope->parent->id_info[i];
2976 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
2977 for (int j = 0; j < scope->id_info_len; j++) {
2978 id_info_t *id2 = &scope->id_info[j];
2979 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00002980 assert(!id2->param); // free vars should not be params
2981#if MICROPY_EMIT_CPYTHON
2982 // in CPython the frees are numbered after the cells
2983 id2->local_num = num_cell + num_free;
2984#else
2985 // in Micro Python the frees come first, before the params
2986 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00002987#endif
2988 num_free += 1;
2989 }
2990 }
2991 }
Damien429d7192013-10-04 19:53:11 +01002992 }
Damien George6baf76e2013-12-30 22:32:17 +00002993#if !MICROPY_EMIT_CPYTHON
2994 // in Micro Python shift all other locals after the free locals
2995 if (num_free > 0) {
2996 for (int i = 0; i < scope->id_info_len; i++) {
2997 id_info_t *id = &scope->id_info[i];
2998 if (id->param || id->kind != ID_INFO_KIND_FREE) {
2999 id->local_num += num_free;
3000 }
3001 }
3002 scope->num_params += num_free; // free vars are counted as params for passing them into the function
3003 scope->num_locals += num_free;
3004 }
3005#endif
Damien429d7192013-10-04 19:53:11 +01003006 }
3007
3008 // compute flags
3009 //scope->flags = 0; since we set some things in parameters
3010 if (scope->kind != SCOPE_MODULE) {
3011 scope->flags |= SCOPE_FLAG_NEWLOCALS;
3012 }
3013 if (scope->kind == SCOPE_FUNCTION || scope->kind == SCOPE_LAMBDA || scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
3014 assert(scope->parent != NULL);
3015 scope->flags |= SCOPE_FLAG_OPTIMISED;
3016
3017 // TODO possibly other ways it can be nested
Damien George08d07552014-01-29 18:58:52 +00003018 // Note that we don't actually use this information at the moment (for CPython compat only)
3019 if ((SCOPE_FUNCTION <= scope->parent->kind && scope->parent->kind <= SCOPE_SET_COMP) || (scope->parent->kind == SCOPE_CLASS && scope->parent->parent->kind == SCOPE_FUNCTION)) {
Damien429d7192013-10-04 19:53:11 +01003020 scope->flags |= SCOPE_FLAG_NESTED;
3021 }
3022 }
3023 int num_free = 0;
3024 for (int i = 0; i < scope->id_info_len; i++) {
3025 id_info_t *id = &scope->id_info[i];
3026 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3027 num_free += 1;
3028 }
3029 }
3030 if (num_free == 0) {
3031 scope->flags |= SCOPE_FLAG_NOFREE;
3032 }
3033}
3034
Damien George08335002014-01-18 23:24:36 +00003035mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003036 compiler_t *comp = m_new(compiler_t, 1);
3037
Damien Georgecbd2f742014-01-19 11:48:48 +00003038 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003039 comp->is_repl = is_repl;
3040 comp->had_error = false;
3041
Damien429d7192013-10-04 19:53:11 +01003042 comp->break_label = 0;
3043 comp->continue_label = 0;
Damien Georgecbddb272014-02-01 20:08:18 +00003044 comp->break_continue_except_level = 0;
3045 comp->cur_except_level = 0;
3046
Damien429d7192013-10-04 19:53:11 +01003047 comp->scope_head = NULL;
3048 comp->scope_cur = NULL;
3049
Damien826005c2013-10-05 23:17:28 +01003050 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003051 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003052
3053 // set the outer scope
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003054 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003055
Damien826005c2013-10-05 23:17:28 +01003056 // compile pass 1
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003057 comp->emit = emit_pass1_new(MP_QSTR___class__);
Damien826005c2013-10-05 23:17:28 +01003058 comp->emit_method_table = &emit_pass1_method_table;
3059 comp->emit_inline_asm = NULL;
3060 comp->emit_inline_asm_method_table = NULL;
3061 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003062 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003063 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003064#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003065 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003066 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003067#endif
Damien826005c2013-10-05 23:17:28 +01003068 } else {
3069 compile_scope(comp, s, PASS_1);
3070 }
3071
3072 // update maximim number of labels needed
3073 if (comp->next_label > max_num_labels) {
3074 max_num_labels = comp->next_label;
3075 }
Damien429d7192013-10-04 19:53:11 +01003076 }
3077
Damien826005c2013-10-05 23:17:28 +01003078 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003079 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003080 compile_scope_compute_things(comp, s);
3081 }
3082
Damien826005c2013-10-05 23:17:28 +01003083 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003084 emit_pass1_free(comp->emit);
3085
Damien826005c2013-10-05 23:17:28 +01003086 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003087#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003088 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003089#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003090 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003091#endif
Damien3ef4abb2013-10-12 16:53:13 +01003092#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003093 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003094#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003095#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003096 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003097 if (false) {
3098 // dummy
3099
Damien3ef4abb2013-10-12 16:53:13 +01003100#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003101 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3102 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003103 if (emit_inline_thumb == NULL) {
3104 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3105 }
3106 comp->emit = NULL;
3107 comp->emit_method_table = NULL;
3108 comp->emit_inline_asm = emit_inline_thumb;
3109 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3110 compile_scope_inline_asm(comp, s, PASS_2);
3111 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003112#endif
3113
Damien826005c2013-10-05 23:17:28 +01003114 } else {
Damienc025ebb2013-10-12 14:30:21 +01003115
3116 // choose the emit type
3117
Damien3ef4abb2013-10-12 16:53:13 +01003118#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003119 comp->emit = emit_cpython_new(max_num_labels);
3120 comp->emit_method_table = &emit_cpython_method_table;
3121#else
Damien826005c2013-10-05 23:17:28 +01003122 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003123
3124#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003125 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003126 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003127#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003128 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003129 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003130 }
Damien13ed3a62013-10-08 09:05:10 +01003131 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003132#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003133 if (emit_native == NULL) {
3134 emit_native = emit_native_thumb_new(max_num_labels);
3135 }
3136 comp->emit_method_table = &emit_native_thumb_method_table;
3137#endif
3138 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003139 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003140 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003141#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003142
Damien826005c2013-10-05 23:17:28 +01003143 default:
3144 if (emit_bc == NULL) {
Damien Georgecbd2f742014-01-19 11:48:48 +00003145 emit_bc = emit_bc_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003146 }
3147 comp->emit = emit_bc;
3148 comp->emit_method_table = &emit_bc_method_table;
3149 break;
3150 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003151#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003152
3153 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003154 compile_scope(comp, s, PASS_2);
3155 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003156 }
Damien429d7192013-10-04 19:53:11 +01003157 }
3158
Damien George41d02b62014-01-24 22:42:28 +00003159 // free the emitters
3160#if !MICROPY_EMIT_CPYTHON
3161 if (emit_bc != NULL) {
3162 emit_bc_free(emit_bc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +02003163 }
Damien George41d02b62014-01-24 22:42:28 +00003164#if MICROPY_EMIT_NATIVE
3165 if (emit_native != NULL) {
3166#if MICROPY_EMIT_X64
3167 emit_native_x64_free(emit_native);
3168#elif MICROPY_EMIT_THUMB
3169 emit_native_thumb_free(emit_native);
3170#endif
3171 }
3172#endif
3173#if MICROPY_EMIT_INLINE_THUMB
3174 if (emit_inline_thumb != NULL) {
3175 emit_inline_thumb_free(emit_inline_thumb);
3176 }
3177#endif
3178#endif // !MICROPY_EMIT_CPYTHON
3179
3180 // free the scopes
Paul Sokolovskyfd313582014-01-23 23:05:47 +02003181 uint unique_code_id = module_scope->unique_code_id;
3182 for (scope_t *s = module_scope; s;) {
3183 scope_t *next = s->next;
3184 scope_free(s);
3185 s = next;
3186 }
Damien5ac1b2e2013-10-18 19:58:12 +01003187
Damien George41d02b62014-01-24 22:42:28 +00003188 // free the compiler
3189 bool had_error = comp->had_error;
3190 m_del_obj(compiler_t, comp);
3191
Damien George1fb03172014-01-03 14:22:03 +00003192 if (had_error) {
3193 // TODO return a proper error message
3194 return mp_const_none;
3195 } else {
3196#if MICROPY_EMIT_CPYTHON
3197 // can't create code, so just return true
Damien George41d02b62014-01-24 22:42:28 +00003198 (void)unique_code_id; // to suppress warning that unique_code_id is unused
Damien George1fb03172014-01-03 14:22:03 +00003199 return mp_const_true;
3200#else
3201 // return function that executes the outer module
Paul Sokolovsky90750022014-02-01 15:05:04 +02003202 return rt_make_function_from_id(unique_code_id, MP_OBJ_NULL);
Damien George1fb03172014-01-03 14:22:03 +00003203#endif
3204 }
Damien429d7192013-10-04 19:53:11 +01003205}