blob: 8db7c6d942a4e982b1512d8933d870a09ce76b0a [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"
Damien429d7192013-10-04 19:53:11 +010010#include "lexer.h"
Damien429d7192013-10-04 19:53:11 +010011#include "parse.h"
12#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000013#include "runtime0.h"
Damien429d7192013-10-04 19:53:11 +010014#include "emit.h"
Damien George1fb03172014-01-03 14:22:03 +000015#include "obj.h"
16#include "compile.h"
17#include "runtime.h"
Damien429d7192013-10-04 19:53:11 +010018
19// TODO need to mangle __attr names
20
Damience89a212013-10-15 22:25:17 +010021#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)
22
Damien429d7192013-10-04 19:53:11 +010023typedef enum {
24 PN_none = 0,
25#define DEF_RULE(rule, comp, kind, arg...) PN_##rule,
26#include "grammar.h"
27#undef DEF_RULE
28 PN_maximum_number_of,
29} pn_kind_t;
30
Damien415eb6f2013-10-05 12:19:06 +010031#define EMIT(fun, arg...) (comp->emit_method_table->fun(comp->emit, ##arg))
Damien826005c2013-10-05 23:17:28 +010032#define EMIT_INLINE_ASM(fun, arg...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, ##arg))
Damien429d7192013-10-04 19:53:11 +010033
Damien6cdd3af2013-10-05 18:08:26 +010034#define EMIT_OPT_NONE (0)
35#define EMIT_OPT_BYTE_CODE (1)
36#define EMIT_OPT_NATIVE_PYTHON (2)
Damien7af3d192013-10-07 00:02:49 +010037#define EMIT_OPT_VIPER (3)
38#define EMIT_OPT_ASM_THUMB (4)
Damien6cdd3af2013-10-05 18:08:26 +010039
Damien429d7192013-10-04 19:53:11 +010040typedef struct _compiler_t {
41 qstr qstr___class__;
42 qstr qstr___locals__;
43 qstr qstr___name__;
44 qstr qstr___module__;
45 qstr qstr___qualname__;
46 qstr qstr___doc__;
47 qstr qstr_assertion_error;
Damien6cdd3af2013-10-05 18:08:26 +010048 qstr qstr_micropython;
Damien5ac1b2e2013-10-18 19:58:12 +010049 qstr qstr_byte_code;
Damien6cdd3af2013-10-05 18:08:26 +010050 qstr qstr_native;
Damien7af3d192013-10-07 00:02:49 +010051 qstr qstr_viper;
Damien5bfb7592013-10-05 18:41:24 +010052 qstr qstr_asm_thumb;
Damiend7933892013-11-28 19:12:18 +000053 qstr qstr_range;
Damien429d7192013-10-04 19:53:11 +010054
Damien5ac1b2e2013-10-18 19:58:12 +010055 bool is_repl;
Damien429d7192013-10-04 19:53:11 +010056 pass_kind_t pass;
Damien5ac1b2e2013-10-18 19:58:12 +010057 bool had_error; // try to keep compiler clean from nlr
Damien429d7192013-10-04 19:53:11 +010058
Damienb05d7072013-10-05 13:37:10 +010059 int next_label;
Damienb05d7072013-10-05 13:37:10 +010060
Damien429d7192013-10-04 19:53:11 +010061 int break_label;
62 int continue_label;
63 int except_nest_level;
64
65 int n_arg_keyword;
66 bool have_star_arg;
67 bool have_dbl_star_arg;
68 bool have_bare_star;
69 int param_pass;
70 int param_pass_num_dict_params;
71 int param_pass_num_default_params;
72
73 scope_t *scope_head;
74 scope_t *scope_cur;
75
Damien6cdd3af2013-10-05 18:08:26 +010076 emit_t *emit; // current emitter
77 const emit_method_table_t *emit_method_table; // current emit method table
Damien826005c2013-10-05 23:17:28 +010078
79 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
80 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 +010081} compiler_t;
82
Damiend99b0522013-12-21 18:17:45 +000083mp_parse_node_t fold_constants(mp_parse_node_t pn) {
84 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
85 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
86 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +010087
88 // fold arguments first
89 for (int i = 0; i < n; i++) {
90 pns->nodes[i] = fold_constants(pns->nodes[i]);
91 }
92
Damiend99b0522013-12-21 18:17:45 +000093 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +010094 case PN_shift_expr:
Damiend99b0522013-12-21 18:17:45 +000095 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
96 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
97 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
98 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
Damien3ef4abb2013-10-12 16:53:13 +010099#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100100 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000101 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
Damien0efb3a12013-10-12 16:16:56 +0100102#endif
Damiend99b0522013-12-21 18:17:45 +0000103 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
104 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien429d7192013-10-04 19:53:11 +0100105 } else {
106 // shouldn't happen
107 assert(0);
108 }
109 }
110 break;
111
112 case PN_arith_expr:
Damien0efb3a12013-10-12 16:16:56 +0100113 // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
Damiend99b0522013-12-21 18:17:45 +0000114 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
115 machine_int_t arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
116 machine_int_t arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
Damien0efb3a12013-10-12 16:16:56 +0100117 machine_int_t res;
Damiend99b0522013-12-21 18:17:45 +0000118 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100119 res = arg0 + arg1;
Damiend99b0522013-12-21 18:17:45 +0000120 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100121 res = arg0 - arg1;
Damien429d7192013-10-04 19:53:11 +0100122 } else {
123 // shouldn't happen
124 assert(0);
Damien0efb3a12013-10-12 16:16:56 +0100125 res = 0;
126 }
Damiend99b0522013-12-21 18:17:45 +0000127 if (MP_FIT_SMALL_INT(res)) {
128 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
Damien429d7192013-10-04 19:53:11 +0100129 }
130 }
131 break;
132
133 case PN_term:
Damiend99b0522013-12-21 18:17:45 +0000134 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
135 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
136 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
137 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien3ef4abb2013-10-12 16:53:13 +0100138#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100139 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000140 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
Damien0efb3a12013-10-12 16:16:56 +0100141#endif
Damiend99b0522013-12-21 18:17:45 +0000142 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +0100143 ; // pass
Damiend99b0522013-12-21 18:17:45 +0000144 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
Damien0efb3a12013-10-12 16:16:56 +0100145 // XXX implement this properly as Python's % operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000146 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1);
147 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
Damien0efb3a12013-10-12 16:16:56 +0100148 // XXX implement this properly as Python's // operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000149 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1);
Damien429d7192013-10-04 19:53:11 +0100150 } else {
151 // shouldn't happen
152 assert(0);
153 }
154 }
155 break;
156
157 case PN_factor_2:
Damiend99b0522013-12-21 18:17:45 +0000158 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
159 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
160 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
161 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
162 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
163 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
164 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
165 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien429d7192013-10-04 19:53:11 +0100166 } else {
167 // shouldn't happen
168 assert(0);
169 }
170 }
171 break;
172
Damien3ef4abb2013-10-12 16:53:13 +0100173#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +0100174 case PN_power:
Damien0efb3a12013-10-12 16:16:56 +0100175 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000176 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])) {
177 mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
178 if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
179 int power = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100180 if (power >= 0) {
181 int ans = 1;
Damiend99b0522013-12-21 18:17:45 +0000182 int base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100183 for (; power > 0; power--) {
184 ans *= base;
185 }
Damiend99b0522013-12-21 18:17:45 +0000186 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien429d7192013-10-04 19:53:11 +0100187 }
188 }
189 }
190 break;
Damien0efb3a12013-10-12 16:16:56 +0100191#endif
Damien429d7192013-10-04 19:53:11 +0100192 }
193 }
194
195 return pn;
196}
197
Damiend99b0522013-12-21 18:17:45 +0000198void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100199
Damienb05d7072013-10-05 13:37:10 +0100200static int comp_next_label(compiler_t *comp) {
201 return comp->next_label++;
202}
203
Damiend99b0522013-12-21 18:17:45 +0000204static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
Damien5ac1b2e2013-10-18 19:58:12 +0100205 scope_t *scope = scope_new(kind, pn, rt_get_unique_code_id(kind == SCOPE_MODULE), emit_options);
Damien429d7192013-10-04 19:53:11 +0100206 scope->parent = comp->scope_cur;
207 scope->next = NULL;
208 if (comp->scope_head == NULL) {
209 comp->scope_head = scope;
210 } else {
211 scope_t *s = comp->scope_head;
212 while (s->next != NULL) {
213 s = s->next;
214 }
215 s->next = scope;
216 }
217 return scope;
218}
219
Damiend99b0522013-12-21 18:17:45 +0000220static int list_len(mp_parse_node_t pn, int pn_kind) {
221 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100222 return 0;
Damiend99b0522013-12-21 18:17:45 +0000223 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100224 return 1;
225 } else {
Damiend99b0522013-12-21 18:17:45 +0000226 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
227 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100228 return 1;
229 } else {
Damiend99b0522013-12-21 18:17:45 +0000230 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100231 }
232 }
233}
234
Damiend99b0522013-12-21 18:17:45 +0000235static 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)) {
236 if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
237 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
238 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100239 for (int i = 0; i < num_nodes; i++) {
240 f(comp, pns->nodes[i]);
241 }
Damiend99b0522013-12-21 18:17:45 +0000242 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100243 f(comp, pn);
244 }
245}
246
Damiend99b0522013-12-21 18:17:45 +0000247static int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
248 if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100249 *nodes = NULL;
250 return 0;
Damiend99b0522013-12-21 18:17:45 +0000251 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100252 *nodes = pn;
253 return 1;
254 } else {
Damiend99b0522013-12-21 18:17:45 +0000255 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
256 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100257 *nodes = pn;
258 return 1;
259 } else {
260 *nodes = pns->nodes;
Damiend99b0522013-12-21 18:17:45 +0000261 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100262 }
263 }
264}
265
Damiend99b0522013-12-21 18:17:45 +0000266void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100267}
268
Damiend99b0522013-12-21 18:17:45 +0000269void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
270 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100271 for (int i = 0; i < num_nodes; i++) {
272 compile_node(comp, pns->nodes[i]);
273 }
274}
275
Damien3ef4abb2013-10-12 16:53:13 +0100276#if MICROPY_EMIT_CPYTHON
Damiend99b0522013-12-21 18:17:45 +0000277static bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
278 if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100279 return false;
280 }
Damiend99b0522013-12-21 18:17:45 +0000281 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +0100282 return false;
283 }
284 return true;
285}
286
Damien02f89412013-12-12 15:13:36 +0000287static void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
288 const char *str = qstr_str(qstr);
289 int len = strlen(str);
290 bool has_single_quote = false;
291 bool has_double_quote = false;
292 for (int i = 0; i < len; i++) {
293 if (str[i] == '\'') {
294 has_single_quote = true;
295 } else if (str[i] == '"') {
296 has_double_quote = true;
297 }
298 }
299 if (bytes) {
300 vstr_printf(vstr, "b");
301 }
302 bool quote_single = false;
303 if (has_single_quote && !has_double_quote) {
304 vstr_printf(vstr, "\"");
305 } else {
306 quote_single = true;
307 vstr_printf(vstr, "'");
308 }
309 for (int i = 0; i < len; i++) {
310 if (str[i] == '\n') {
311 vstr_printf(vstr, "\\n");
312 } else if (str[i] == '\\') {
313 vstr_printf(vstr, "\\\\");
314 } else if (str[i] == '\'' && quote_single) {
315 vstr_printf(vstr, "\\'");
316 } else {
317 vstr_printf(vstr, "%c", str[i]);
318 }
319 }
320 if (has_single_quote && !has_double_quote) {
321 vstr_printf(vstr, "\"");
322 } else {
323 vstr_printf(vstr, "'");
324 }
325}
326
Damiend99b0522013-12-21 18:17:45 +0000327static void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
328 assert(MP_PARSE_NODE_IS_LEAF(pn));
329 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
330 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
331 case MP_PARSE_NODE_ID: assert(0);
332 case MP_PARSE_NODE_SMALL_INT: vstr_printf(vstr, "%d", arg); break;
333 case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
334 case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
335 case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
336 case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
337 case MP_PARSE_NODE_TOKEN:
Damien429d7192013-10-04 19:53:11 +0100338 switch (arg) {
Damiend99b0522013-12-21 18:17:45 +0000339 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
340 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
341 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
Damien429d7192013-10-04 19:53:11 +0100342 default: assert(0);
343 }
344 break;
345 default: assert(0);
346 }
347}
348
Damiend99b0522013-12-21 18:17:45 +0000349static 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 +0100350 int n = 0;
351 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000352 n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien429d7192013-10-04 19:53:11 +0100353 }
354 int total = n;
355 bool is_const = true;
Damiend99b0522013-12-21 18:17:45 +0000356 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100357 total += 1;
Damien3a205172013-10-12 15:01:56 +0100358 if (!cpython_c_tuple_is_const(pn)) {
Damien429d7192013-10-04 19:53:11 +0100359 is_const = false;
360 }
361 }
362 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100363 if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien429d7192013-10-04 19:53:11 +0100364 is_const = false;
365 break;
366 }
367 }
368 if (total > 0 && is_const) {
369 bool need_comma = false;
Damien02f89412013-12-12 15:13:36 +0000370 vstr_t *vstr = vstr_new();
371 vstr_printf(vstr, "(");
Damiend99b0522013-12-21 18:17:45 +0000372 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien02f89412013-12-12 15:13:36 +0000373 cpython_c_tuple_emit_const(comp, pn, vstr);
Damien429d7192013-10-04 19:53:11 +0100374 need_comma = true;
375 }
376 for (int i = 0; i < n; i++) {
377 if (need_comma) {
Damien02f89412013-12-12 15:13:36 +0000378 vstr_printf(vstr, ", ");
Damien429d7192013-10-04 19:53:11 +0100379 }
Damien02f89412013-12-12 15:13:36 +0000380 cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien429d7192013-10-04 19:53:11 +0100381 need_comma = true;
382 }
383 if (total == 1) {
Damien02f89412013-12-12 15:13:36 +0000384 vstr_printf(vstr, ",)");
Damien429d7192013-10-04 19:53:11 +0100385 } else {
Damien02f89412013-12-12 15:13:36 +0000386 vstr_printf(vstr, ")");
Damien429d7192013-10-04 19:53:11 +0100387 }
Damien02f89412013-12-12 15:13:36 +0000388 EMIT(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +0000389 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +0100390 } else {
Damiend99b0522013-12-21 18:17:45 +0000391 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100392 compile_node(comp, pn);
393 }
394 for (int i = 0; i < n; i++) {
395 compile_node(comp, pns_list->nodes[i]);
396 }
397 EMIT(build_tuple, total);
398 }
399}
Damien3a205172013-10-12 15:01:56 +0100400#endif
401
402// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
Damiend99b0522013-12-21 18:17:45 +0000403void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3ef4abb2013-10-12 16:53:13 +0100404#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100405 cpython_c_tuple(comp, pn, pns_list);
406#else
407 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000408 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100409 compile_node(comp, pn);
410 total += 1;
411 }
412 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000413 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100414 for (int i = 0; i < n; i++) {
415 compile_node(comp, pns_list->nodes[i]);
416 }
417 total += n;
418 }
419 EMIT(build_tuple, total);
420#endif
421}
Damien429d7192013-10-04 19:53:11 +0100422
Damiend99b0522013-12-21 18:17:45 +0000423void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100424 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000425 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100426}
427
Damiend99b0522013-12-21 18:17:45 +0000428static bool node_is_const_false(mp_parse_node_t pn) {
429 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
430 // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100431}
432
Damiend99b0522013-12-21 18:17:45 +0000433static bool node_is_const_true(mp_parse_node_t pn) {
434 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 +0100435}
436
Damien3ef4abb2013-10-12 16:53:13 +0100437#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100438// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
Damiend99b0522013-12-21 18:17:45 +0000439static 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 +0100440 if (node_is_const_false(pn)) {
441 if (jump_if == false) {
442 EMIT(jump, label);
443 }
444 return;
445 } else if (node_is_const_true(pn)) {
446 if (jump_if == true) {
447 EMIT(jump, label);
448 }
449 return;
Damiend99b0522013-12-21 18:17:45 +0000450 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
451 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
452 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
453 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien429d7192013-10-04 19:53:11 +0100454 if (jump_if == false) {
Damienb05d7072013-10-05 13:37:10 +0100455 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100456 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100457 cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien429d7192013-10-04 19:53:11 +0100458 }
Damien3a205172013-10-12 15:01:56 +0100459 cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100460 EMIT(label_assign, label2);
461 } else {
462 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100463 cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100464 }
465 }
466 return;
Damiend99b0522013-12-21 18:17:45 +0000467 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien429d7192013-10-04 19:53:11 +0100468 if (jump_if == false) {
469 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100470 cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100471 }
472 } else {
Damienb05d7072013-10-05 13:37:10 +0100473 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100474 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100475 cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien429d7192013-10-04 19:53:11 +0100476 }
Damien3a205172013-10-12 15:01:56 +0100477 cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100478 EMIT(label_assign, label2);
479 }
480 return;
Damiend99b0522013-12-21 18:17:45 +0000481 } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100482 cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien429d7192013-10-04 19:53:11 +0100483 return;
484 }
485 }
486
487 // nothing special, fall back to default compiling for node and jump
488 compile_node(comp, pn);
489 if (jump_if == false) {
490 EMIT(pop_jump_if_false, label);
491 } else {
492 EMIT(pop_jump_if_true, label);
493 }
494}
Damien3a205172013-10-12 15:01:56 +0100495#endif
Damien429d7192013-10-04 19:53:11 +0100496
Damiend99b0522013-12-21 18:17:45 +0000497static void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien3ef4abb2013-10-12 16:53:13 +0100498#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100499 cpython_c_if_cond(comp, pn, jump_if, label, false);
500#else
501 if (node_is_const_false(pn)) {
502 if (jump_if == false) {
503 EMIT(jump, label);
504 }
505 return;
506 } else if (node_is_const_true(pn)) {
507 if (jump_if == true) {
508 EMIT(jump, label);
509 }
510 return;
Damiend99b0522013-12-21 18:17:45 +0000511 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
512 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
513 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
514 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100515 if (jump_if == false) {
516 int label2 = comp_next_label(comp);
517 for (int i = 0; i < n - 1; i++) {
518 c_if_cond(comp, pns->nodes[i], true, label2);
519 }
520 c_if_cond(comp, pns->nodes[n - 1], false, label);
521 EMIT(label_assign, label2);
522 } else {
523 for (int i = 0; i < n; i++) {
524 c_if_cond(comp, pns->nodes[i], true, label);
525 }
526 }
527 return;
Damiend99b0522013-12-21 18:17:45 +0000528 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100529 if (jump_if == false) {
530 for (int i = 0; i < n; i++) {
531 c_if_cond(comp, pns->nodes[i], false, label);
532 }
533 } else {
534 int label2 = comp_next_label(comp);
535 for (int i = 0; i < n - 1; i++) {
536 c_if_cond(comp, pns->nodes[i], false, label2);
537 }
538 c_if_cond(comp, pns->nodes[n - 1], true, label);
539 EMIT(label_assign, label2);
540 }
541 return;
Damiend99b0522013-12-21 18:17:45 +0000542 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100543 c_if_cond(comp, pns->nodes[0], !jump_if, label);
544 return;
545 }
546 }
547
548 // nothing special, fall back to default compiling for node and jump
549 compile_node(comp, pn);
550 if (jump_if == false) {
551 EMIT(pop_jump_if_false, label);
552 } else {
553 EMIT(pop_jump_if_true, label);
554 }
555#endif
Damien429d7192013-10-04 19:53:11 +0100556}
557
558typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damiend99b0522013-12-21 18:17:45 +0000559void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100560
Damiend99b0522013-12-21 18:17:45 +0000561void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100562 if (assign_kind != ASSIGN_AUG_STORE) {
563 compile_node(comp, pns->nodes[0]);
564 }
565
Damiend99b0522013-12-21 18:17:45 +0000566 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
567 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
568 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
569 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100570 if (assign_kind != ASSIGN_AUG_STORE) {
571 for (int i = 0; i < n - 1; i++) {
572 compile_node(comp, pns1->nodes[i]);
573 }
574 }
Damiend99b0522013-12-21 18:17:45 +0000575 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
576 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100577 }
Damiend99b0522013-12-21 18:17:45 +0000578 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +0100579 printf("SyntaxError: can't assign to function call\n");
580 return;
Damiend99b0522013-12-21 18:17:45 +0000581 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100582 if (assign_kind == ASSIGN_AUG_STORE) {
583 EMIT(rot_three);
584 EMIT(store_subscr);
585 } else {
586 compile_node(comp, pns1->nodes[0]);
587 if (assign_kind == ASSIGN_AUG_LOAD) {
588 EMIT(dup_top_two);
589 EMIT(binary_op, RT_BINARY_OP_SUBSCR);
590 } else {
591 EMIT(store_subscr);
592 }
593 }
Damiend99b0522013-12-21 18:17:45 +0000594 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
595 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100596 if (assign_kind == ASSIGN_AUG_LOAD) {
597 EMIT(dup_top);
Damiend99b0522013-12-21 18:17:45 +0000598 EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100599 } else {
600 if (assign_kind == ASSIGN_AUG_STORE) {
601 EMIT(rot_two);
602 }
Damiend99b0522013-12-21 18:17:45 +0000603 EMIT(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100604 }
605 } else {
606 // shouldn't happen
607 assert(0);
608 }
609 } else {
610 // shouldn't happen
611 assert(0);
612 }
613
Damiend99b0522013-12-21 18:17:45 +0000614 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100615 // SyntaxError, cannot assign
616 assert(0);
617 }
618}
619
Damiend99b0522013-12-21 18:17:45 +0000620void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
Damien429d7192013-10-04 19:53:11 +0100621 assert(n >= 0);
622 int have_star_index = -1;
623 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000624 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) {
Damien429d7192013-10-04 19:53:11 +0100625 if (have_star_index < 0) {
626 EMIT(unpack_ex, i, n - i - 1);
627 have_star_index = i;
628 } else {
629 printf("SyntaxError: two starred expressions in assignment\n");
630 return;
631 }
632 }
633 }
634 if (have_star_index < 0) {
635 EMIT(unpack_sequence, n);
636 }
637 for (int i = 0; i < n; i++) {
638 if (i == have_star_index) {
Damiend99b0522013-12-21 18:17:45 +0000639 c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100640 } else {
641 c_assign(comp, nodes[i], ASSIGN_STORE);
642 }
643 }
644}
645
646// assigns top of stack to pn
Damiend99b0522013-12-21 18:17:45 +0000647void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100648 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +0000649 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100650 assert(0);
Damiend99b0522013-12-21 18:17:45 +0000651 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
652 if (MP_PARSE_NODE_IS_ID(pn)) {
653 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100654 switch (assign_kind) {
655 case ASSIGN_STORE:
656 case ASSIGN_AUG_STORE:
Damien4b03e772013-10-05 14:17:09 +0100657 EMIT(store_id, arg);
Damien429d7192013-10-04 19:53:11 +0100658 break;
659 case ASSIGN_AUG_LOAD:
Damien4b03e772013-10-05 14:17:09 +0100660 EMIT(load_id, arg);
Damien429d7192013-10-04 19:53:11 +0100661 break;
662 }
663 } else {
664 printf("SyntaxError: can't assign to literal\n");
665 return;
666 }
667 } else {
Damiend99b0522013-12-21 18:17:45 +0000668 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
669 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +0100670 case PN_power:
671 // lhs is an index or attribute
672 c_assign_power(comp, pns, assign_kind);
673 break;
674
675 case PN_testlist_star_expr:
676 case PN_exprlist:
677 // lhs is a tuple
678 if (assign_kind != ASSIGN_STORE) {
679 goto bad_aug;
680 }
Damiend99b0522013-12-21 18:17:45 +0000681 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100682 break;
683
684 case PN_atom_paren:
685 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000686 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100687 // empty tuple
688 printf("SyntaxError: can't assign to ()\n");
689 return;
Damiend99b0522013-12-21 18:17:45 +0000690 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
691 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100692 goto testlist_comp;
693 } else {
694 // parenthesis around 1 item, is just that item
695 pn = pns->nodes[0];
696 goto tail_recursion;
697 }
698 break;
699
700 case PN_atom_bracket:
701 // lhs is something in brackets
702 if (assign_kind != ASSIGN_STORE) {
703 goto bad_aug;
704 }
Damiend99b0522013-12-21 18:17:45 +0000705 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100706 // empty list, assignment allowed
707 c_assign_tuple(comp, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000708 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
709 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100710 goto testlist_comp;
711 } else {
712 // brackets around 1 item
713 c_assign_tuple(comp, 1, &pns->nodes[0]);
714 }
715 break;
716
717 default:
Damiend99b0522013-12-21 18:17:45 +0000718 printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien429d7192013-10-04 19:53:11 +0100719 assert(0);
720 }
721 return;
722
723 testlist_comp:
724 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000725 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
726 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
727 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100728 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000729 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100730 c_assign_tuple(comp, 1, &pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000731 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100732 // sequence of many items
733 // TODO call c_assign_tuple instead
Damiend99b0522013-12-21 18:17:45 +0000734 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
Damien429d7192013-10-04 19:53:11 +0100735 EMIT(unpack_sequence, 1 + n);
736 c_assign(comp, pns->nodes[0], ASSIGN_STORE);
737 for (int i = 0; i < n; i++) {
738 c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
739 }
Damiend99b0522013-12-21 18:17:45 +0000740 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +0100741 // TODO not implemented
742 assert(0);
743 } else {
744 // sequence with 2 items
745 goto sequence_with_2_items;
746 }
747 } else {
748 // sequence with 2 items
749 sequence_with_2_items:
750 c_assign_tuple(comp, 2, pns->nodes);
751 }
752 return;
753 }
754 return;
755
756 bad_aug:
757 printf("SyntaxError: illegal expression for augmented assignment\n");
758}
759
760// stuff for lambda and comprehensions and generators
761void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
762 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000763 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100764 int nfree = 0;
765 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000766 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
767 id_info_t *id = &comp->scope_cur->id_info[i];
768 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
769 for (int j = 0; j < this_scope->id_info_len; j++) {
770 id_info_t *id2 = &this_scope->id_info[j];
771 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +0000772#if MICROPY_EMIT_CPYTHON
Damien318aec62013-12-10 18:28:17 +0000773 EMIT(load_closure, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000774#else
775 // in Micro Python we load closures using LOAD_FAST
776 EMIT(load_fast, id->qstr, id->local_num);
777#endif
Damien318aec62013-12-10 18:28:17 +0000778 nfree += 1;
779 }
780 }
Damien429d7192013-10-04 19:53:11 +0100781 }
782 }
783 }
784 if (nfree > 0) {
785 EMIT(build_tuple, nfree);
786 }
787
788 // make the function/closure
789 if (nfree == 0) {
790 EMIT(make_function, this_scope, n_dict_params, n_default_params);
791 } else {
792 EMIT(make_closure, this_scope, n_dict_params, n_default_params);
793 }
794}
795
Damiend99b0522013-12-21 18:17:45 +0000796void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
797 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
798 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
799 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100800 // this parameter has a default value
801 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
802 if (comp->have_bare_star) {
803 comp->param_pass_num_dict_params += 1;
804 if (comp->param_pass == 1) {
Damiend99b0522013-12-21 18:17:45 +0000805 EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100806 compile_node(comp, pns->nodes[2]);
807 }
808 } else {
809 comp->param_pass_num_default_params += 1;
810 if (comp->param_pass == 2) {
811 compile_node(comp, pns->nodes[2]);
812 }
813 }
814 }
Damiend99b0522013-12-21 18:17:45 +0000815 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
816 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
817 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100818 // bare star
819 comp->have_bare_star = true;
820 }
821 }
822}
823
824// leaves function object on stack
825// returns function name
Damiend99b0522013-12-21 18:17:45 +0000826qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100827 if (comp->pass == PASS_1) {
828 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000829 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100830 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000831 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100832 }
833
834 // save variables (probably don't need to do this, since we can't have nested definitions..?)
835 bool old_have_bare_star = comp->have_bare_star;
836 int old_param_pass = comp->param_pass;
837 int old_param_pass_num_dict_params = comp->param_pass_num_dict_params;
838 int old_param_pass_num_default_params = comp->param_pass_num_default_params;
839
840 // compile default parameters
841 comp->have_bare_star = false;
842 comp->param_pass = 1; // pass 1 does any default parameters after bare star
843 comp->param_pass_num_dict_params = 0;
844 comp->param_pass_num_default_params = 0;
845 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
846 comp->have_bare_star = false;
847 comp->param_pass = 2; // pass 2 does any default parameters before bare star
848 comp->param_pass_num_dict_params = 0;
849 comp->param_pass_num_default_params = 0;
850 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
851
852 // get the scope for this function
853 scope_t *fscope = (scope_t*)pns->nodes[4];
854
855 // make the function
856 close_over_variables_etc(comp, fscope, comp->param_pass_num_dict_params, comp->param_pass_num_default_params);
857
858 // restore variables
859 comp->have_bare_star = old_have_bare_star;
860 comp->param_pass = old_param_pass;
861 comp->param_pass_num_dict_params = old_param_pass_num_dict_params;
862 comp->param_pass_num_default_params = old_param_pass_num_default_params;
863
864 // return its name (the 'f' in "def f(...):")
865 return fscope->simple_name;
866}
867
868// leaves class object on stack
869// returns class name
Damiend99b0522013-12-21 18:17:45 +0000870qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100871 if (comp->pass == PASS_1) {
872 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000873 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100874 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000875 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100876 }
877
878 EMIT(load_build_class);
879
880 // scope for this class
881 scope_t *cscope = (scope_t*)pns->nodes[3];
882
883 // compile the class
884 close_over_variables_etc(comp, cscope, 0, 0);
885
886 // get its name
887 EMIT(load_const_id, cscope->simple_name);
888
889 // nodes[1] has parent classes, if any
Damiend99b0522013-12-21 18:17:45 +0000890 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +0100891 // no parent classes
892 EMIT(call_function, 2, 0, false, false);
893 } else {
894 // have a parent class or classes
895 // TODO what if we have, eg, *a or **a in the parent list?
896 compile_node(comp, pns->nodes[1]);
897 EMIT(call_function, 2 + list_len(pns->nodes[1], PN_arglist), 0, false, false);
898 }
899
900 // return its name (the 'C' in class C(...):")
901 return cscope->simple_name;
902}
903
Damien6cdd3af2013-10-05 18:08:26 +0100904// returns true if it was a built-in decorator (even if the built-in had an error)
Damiend99b0522013-12-21 18:17:45 +0000905static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
906 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != comp->qstr_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100907 return false;
908 }
909
910 if (name_len != 2) {
911 printf("SyntaxError: invalid micropython decorator\n");
912 return true;
913 }
914
Damiend99b0522013-12-21 18:17:45 +0000915 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien5ac1b2e2013-10-18 19:58:12 +0100916 if (attr == comp->qstr_byte_code) {
917 *emit_options = EMIT_OPT_BYTE_CODE;
Damience89a212013-10-15 22:25:17 +0100918#if MICROPY_EMIT_NATIVE
919 } else if (attr == comp->qstr_native) {
Damien6cdd3af2013-10-05 18:08:26 +0100920 *emit_options = EMIT_OPT_NATIVE_PYTHON;
Damien7af3d192013-10-07 00:02:49 +0100921 } else if (attr == comp->qstr_viper) {
922 *emit_options = EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100923#endif
Damien3ef4abb2013-10-12 16:53:13 +0100924#if MICROPY_EMIT_INLINE_THUMB
Damien5bfb7592013-10-05 18:41:24 +0100925 } else if (attr == comp->qstr_asm_thumb) {
926 *emit_options = EMIT_OPT_ASM_THUMB;
Damienc025ebb2013-10-12 14:30:21 +0100927#endif
Damien6cdd3af2013-10-05 18:08:26 +0100928 } else {
Damience89a212013-10-15 22:25:17 +0100929 printf("SyntaxError: invalid micropython decorator '%s'\n", qstr_str(attr));
Damien6cdd3af2013-10-05 18:08:26 +0100930 }
931
932 return true;
933}
934
Damiend99b0522013-12-21 18:17:45 +0000935void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100936 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000937 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +0100938 int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
939
Damien6cdd3af2013-10-05 18:08:26 +0100940 // inherit emit options for this function/class definition
941 uint emit_options = comp->scope_cur->emit_options;
942
943 // compile each decorator
944 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100945 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000946 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
947 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100948
949 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +0000950 mp_parse_node_t *name_nodes;
Damien6cdd3af2013-10-05 18:08:26 +0100951 int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
952
953 // check for built-in decorators
954 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
955 // this was a built-in
956 num_built_in_decorators += 1;
957
958 } else {
959 // not a built-in, compile normally
960
961 // compile the decorator function
962 compile_node(comp, name_nodes[0]);
963 for (int i = 1; i < name_len; i++) {
Damiend99b0522013-12-21 18:17:45 +0000964 assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be
965 EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i]));
Damien6cdd3af2013-10-05 18:08:26 +0100966 }
967
968 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +0000969 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +0100970 // call the decorator function with the arguments in nodes[1]
971 compile_node(comp, pns_decorator->nodes[1]);
972 }
Damien429d7192013-10-04 19:53:11 +0100973 }
974 }
975
976 // compile the body (funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +0000977 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +0100978 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +0000979 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100980 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Damiend99b0522013-12-21 18:17:45 +0000981 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100982 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +0100983 } else {
984 // shouldn't happen
985 assert(0);
986 }
987
988 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +0100989 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien429d7192013-10-04 19:53:11 +0100990 EMIT(call_function, 1, 0, false, false);
991 }
992
993 // store func/class object into name
Damien4b03e772013-10-05 14:17:09 +0100994 EMIT(store_id, body_name);
Damien429d7192013-10-04 19:53:11 +0100995}
996
Damiend99b0522013-12-21 18:17:45 +0000997void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +0100998 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +0100999 // store function object into function name
Damien4b03e772013-10-05 14:17:09 +01001000 EMIT(store_id, fname);
Damien429d7192013-10-04 19:53:11 +01001001}
1002
Damiend99b0522013-12-21 18:17:45 +00001003void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
1004 if (MP_PARSE_NODE_IS_ID(pn)) {
1005 EMIT(delete_id, MP_PARSE_NODE_LEAF_ARG(pn));
1006 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
1007 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001008
1009 compile_node(comp, pns->nodes[0]); // base of the power node
1010
Damiend99b0522013-12-21 18:17:45 +00001011 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1012 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1013 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
1014 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001015 for (int i = 0; i < n - 1; i++) {
1016 compile_node(comp, pns1->nodes[i]);
1017 }
Damiend99b0522013-12-21 18:17:45 +00001018 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
1019 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +01001020 }
Damiend99b0522013-12-21 18:17:45 +00001021 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +01001022 // SyntaxError: can't delete a function call
1023 assert(0);
Damiend99b0522013-12-21 18:17:45 +00001024 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +01001025 compile_node(comp, pns1->nodes[0]);
1026 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +00001027 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
1028 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
1029 EMIT(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001030 } else {
1031 // shouldn't happen
1032 assert(0);
1033 }
1034 } else {
1035 // shouldn't happen
1036 assert(0);
1037 }
1038
Damiend99b0522013-12-21 18:17:45 +00001039 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001040 // SyntaxError, cannot delete
1041 assert(0);
1042 }
Damiend99b0522013-12-21 18:17:45 +00001043 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
1044 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
1045 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) {
1046 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001047 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
1048
Damiend99b0522013-12-21 18:17:45 +00001049 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1050 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1051 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01001052 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00001053 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001054 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00001055 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01001056 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +00001057 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001058 c_del_stmt(comp, pns->nodes[0]);
1059 for (int i = 0; i < n; i++) {
1060 c_del_stmt(comp, pns1->nodes[i]);
1061 }
Damiend99b0522013-12-21 18:17:45 +00001062 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01001063 // TODO not implemented; can't del comprehension?
1064 assert(0);
1065 } else {
1066 // sequence with 2 items
1067 goto sequence_with_2_items;
1068 }
1069 } else {
1070 // sequence with 2 items
1071 sequence_with_2_items:
1072 c_del_stmt(comp, pns->nodes[0]);
1073 c_del_stmt(comp, pns->nodes[1]);
1074 }
1075 } else {
1076 // tuple with 1 element
1077 c_del_stmt(comp, pn);
1078 }
1079 } else {
1080 // not implemented
1081 assert(0);
1082 }
1083}
1084
Damiend99b0522013-12-21 18:17:45 +00001085void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001086 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
1087}
1088
Damiend99b0522013-12-21 18:17:45 +00001089void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001090 if (comp->break_label == 0) {
1091 printf("ERROR: cannot break from here\n");
1092 }
1093 EMIT(break_loop, comp->break_label);
1094}
1095
Damiend99b0522013-12-21 18:17:45 +00001096void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001097 if (comp->continue_label == 0) {
1098 printf("ERROR: cannot continue from here\n");
1099 }
1100 if (comp->except_nest_level > 0) {
1101 EMIT(continue_loop, comp->continue_label);
1102 } else {
1103 EMIT(jump, comp->continue_label);
1104 }
1105}
1106
Damiend99b0522013-12-21 18:17:45 +00001107void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +01001108 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
1109 printf("SyntaxError: 'return' outside function\n");
1110 comp->had_error = true;
1111 return;
1112 }
Damiend99b0522013-12-21 18:17:45 +00001113 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001114 // no argument to 'return', so return None
Damiend99b0522013-12-21 18:17:45 +00001115 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
1116 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +01001117 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +00001118 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
1119 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 +01001120
Damienb05d7072013-10-05 13:37:10 +01001121 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001122 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1123 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
1124 EMIT(return_value);
1125 EMIT(label_assign, l_fail);
1126 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1127 } else {
1128 compile_node(comp, pns->nodes[0]);
1129 }
1130 EMIT(return_value);
1131}
1132
Damiend99b0522013-12-21 18:17:45 +00001133void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001134 compile_node(comp, pns->nodes[0]);
1135 EMIT(pop_top);
1136}
1137
Damiend99b0522013-12-21 18:17:45 +00001138void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1139 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001140 // raise
1141 EMIT(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001142 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001143 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001144 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001145 compile_node(comp, pns->nodes[0]);
1146 compile_node(comp, pns->nodes[1]);
1147 EMIT(raise_varargs, 2);
1148 } else {
1149 // raise x
1150 compile_node(comp, pns->nodes[0]);
1151 EMIT(raise_varargs, 1);
1152 }
1153}
1154
1155// q1 holds the base, q2 the full name
1156// eg a -> q1=q2=a
1157// a.b.c -> q1=a, q2=a.b.c
Damiend99b0522013-12-21 18:17:45 +00001158void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
Damien429d7192013-10-04 19:53:11 +01001159 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001160 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1161 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001162 // a name of the form x as y; unwrap it
Damiend99b0522013-12-21 18:17:45 +00001163 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001164 pn = pns->nodes[0];
1165 is_as = true;
1166 }
Damiend99b0522013-12-21 18:17:45 +00001167 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001168 // just a simple name
Damiend99b0522013-12-21 18:17:45 +00001169 *q2 = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001170 if (!is_as) {
1171 *q1 = *q2;
1172 }
1173 EMIT(import_name, *q2);
Damiend99b0522013-12-21 18:17:45 +00001174 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
1175 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
1176 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) {
Damien429d7192013-10-04 19:53:11 +01001177 // a name of the form a.b.c
1178 if (!is_as) {
Damiend99b0522013-12-21 18:17:45 +00001179 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001180 }
Damiend99b0522013-12-21 18:17:45 +00001181 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001182 int len = n - 1;
1183 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001184 len += strlen(qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])));
Damien429d7192013-10-04 19:53:11 +01001185 }
1186 char *str = m_new(char, len + 1);
Damien Georgefe8fb912014-01-02 16:36:09 +00001187 char *str_dest = str;
Damien429d7192013-10-04 19:53:11 +01001188 str[0] = 0;
1189 for (int i = 0; i < n; i++) {
1190 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001191 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001192 }
Damien Georgefe8fb912014-01-02 16:36:09 +00001193 const char *str_src = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
1194 size_t str_src_len = strlen(str_src);
1195 memcpy(str_dest, str_src, str_src_len);
1196 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001197 }
Damien Georgefe8fb912014-01-02 16:36:09 +00001198 *str_dest = '\0';
Damien732407f2013-12-29 19:33:23 +00001199 *q2 = qstr_from_str_take(str, len + 1);
Damien429d7192013-10-04 19:53:11 +01001200 EMIT(import_name, *q2);
1201 if (is_as) {
1202 for (int i = 1; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001203 EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001204 }
1205 }
1206 } else {
1207 // TODO not implemented
1208 assert(0);
1209 }
1210 } else {
1211 // TODO not implemented
1212 assert(0);
1213 }
1214}
1215
Damiend99b0522013-12-21 18:17:45 +00001216void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01001217 EMIT(load_const_small_int, 0); // ??
Damiend99b0522013-12-21 18:17:45 +00001218 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001219 qstr q1, q2;
1220 do_import_name(comp, pn, &q1, &q2);
Damien4b03e772013-10-05 14:17:09 +01001221 EMIT(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001222}
1223
Damiend99b0522013-12-21 18:17:45 +00001224void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001225 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1226}
1227
Damiend99b0522013-12-21 18:17:45 +00001228void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1229 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damiendb4c3612013-12-10 17:27:24 +00001230 EMIT(load_const_small_int, 0); // level 0 for __import__
1231
1232 // build the "fromlist" tuple
1233#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001234 EMIT(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001235#else
1236 EMIT(load_const_str, qstr_from_str_static("*"), false);
1237 EMIT(build_tuple, 1);
1238#endif
1239
1240 // do the import
Damien429d7192013-10-04 19:53:11 +01001241 qstr dummy_q, id1;
1242 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1243 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001244
Damien429d7192013-10-04 19:53:11 +01001245 } else {
Damiendb4c3612013-12-10 17:27:24 +00001246 EMIT(load_const_small_int, 0); // level 0 for __import__
1247
1248 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001249 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001250 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001251#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001252 {
1253 vstr_t *vstr = vstr_new();
1254 vstr_printf(vstr, "(");
1255 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001256 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1257 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1258 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001259 if (i > 0) {
1260 vstr_printf(vstr, ", ");
1261 }
1262 vstr_printf(vstr, "'");
1263 vstr_printf(vstr, qstr_str(id2));
1264 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001265 }
Damien02f89412013-12-12 15:13:36 +00001266 if (n == 1) {
1267 vstr_printf(vstr, ",");
1268 }
1269 vstr_printf(vstr, ")");
Damien02f89412013-12-12 15:13:36 +00001270 EMIT(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001271 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001272 }
Damiendb4c3612013-12-10 17:27:24 +00001273#else
1274 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001275 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1276 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1277 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damiendb4c3612013-12-10 17:27:24 +00001278 EMIT(load_const_str, id2, false);
1279 }
1280 EMIT(build_tuple, n);
1281#endif
1282
1283 // do the import
Damien429d7192013-10-04 19:53:11 +01001284 qstr dummy_q, id1;
1285 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1286 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001287 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1288 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1289 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien429d7192013-10-04 19:53:11 +01001290 EMIT(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001291 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien4b03e772013-10-05 14:17:09 +01001292 EMIT(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001293 } else {
Damiend99b0522013-12-21 18:17:45 +00001294 EMIT(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001295 }
1296 }
1297 EMIT(pop_top);
1298 }
1299}
1300
Damiend99b0522013-12-21 18:17:45 +00001301void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001302 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001303 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1304 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001305 } else {
Damiend99b0522013-12-21 18:17:45 +00001306 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1307 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001308 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001309 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001310 }
Damien429d7192013-10-04 19:53:11 +01001311 }
1312 }
1313}
1314
Damiend99b0522013-12-21 18:17:45 +00001315void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001316 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001317 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1318 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001319 } else {
Damiend99b0522013-12-21 18:17:45 +00001320 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1321 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001322 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001323 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001324 }
Damien429d7192013-10-04 19:53:11 +01001325 }
1326 }
1327}
1328
Damiend99b0522013-12-21 18:17:45 +00001329void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001330 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001331 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien4b03e772013-10-05 14:17:09 +01001332 EMIT(load_id, comp->qstr_assertion_error);
Damiend99b0522013-12-21 18:17:45 +00001333 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001334 // assertion message
1335 compile_node(comp, pns->nodes[1]);
1336 EMIT(call_function, 1, 0, false, false);
1337 }
1338 EMIT(raise_varargs, 1);
1339 EMIT(label_assign, l_end);
1340}
1341
Damiend99b0522013-12-21 18:17:45 +00001342void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001343 // TODO proper and/or short circuiting
1344
Damienb05d7072013-10-05 13:37:10 +01001345 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001346
Damienb05d7072013-10-05 13:37:10 +01001347 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001348 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1349
1350 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001351 //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 +01001352 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001353 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien429d7192013-10-04 19:53:11 +01001354 EMIT(jump, l_end);
1355 }
1356 //}
1357 EMIT(label_assign, l_fail);
1358
Damiend99b0522013-12-21 18:17:45 +00001359 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001360 // compile elif blocks
1361
Damiend99b0522013-12-21 18:17:45 +00001362 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001363
Damiend99b0522013-12-21 18:17:45 +00001364 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001365 // multiple elif blocks
1366
Damiend99b0522013-12-21 18:17:45 +00001367 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001368 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001369 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
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_elif2->nodes[0], false, l_fail); // elif condition
1372
1373 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001374 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien429d7192013-10-04 19:53:11 +01001375 EMIT(jump, l_end);
1376 }
1377 EMIT(label_assign, l_fail);
1378 }
1379
1380 } else {
1381 // a single elif block
1382
Damienb05d7072013-10-05 13:37:10 +01001383 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001384 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1385
1386 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001387 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien429d7192013-10-04 19:53:11 +01001388 EMIT(jump, l_end);
1389 }
1390 EMIT(label_assign, l_fail);
1391 }
1392 }
1393
1394 // compile else block
1395 compile_node(comp, pns->nodes[3]); // can be null
1396
1397 EMIT(label_assign, l_end);
1398}
1399
Damiend99b0522013-12-21 18:17:45 +00001400void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001401 int old_break_label = comp->break_label;
1402 int old_continue_label = comp->continue_label;
1403
Damienb05d7072013-10-05 13:37:10 +01001404 int break_label = comp_next_label(comp);
1405 int continue_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001406
1407 comp->break_label = break_label;
1408 comp->continue_label = continue_label;
1409
Damience89a212013-10-15 22:25:17 +01001410 // compared to CPython, we have an optimised version of while loops
1411#if MICROPY_EMIT_CPYTHON
1412 int done_label = comp_next_label(comp);
1413 EMIT(setup_loop, break_label);
Damien429d7192013-10-04 19:53:11 +01001414 EMIT(label_assign, continue_label);
1415 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1416 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001417 if (!EMIT(last_emit_was_return_value)) {
Damien429d7192013-10-04 19:53:11 +01001418 EMIT(jump, continue_label);
1419 }
1420 EMIT(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001421 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1422 // this is a small hack to agree with CPython
1423 if (!node_is_const_true(pns->nodes[0])) {
1424 EMIT(pop_block);
1425 }
Damience89a212013-10-15 22:25:17 +01001426#else
1427 int top_label = comp_next_label(comp);
1428 EMIT(jump, continue_label);
1429 EMIT(label_assign, top_label);
1430 compile_node(comp, pns->nodes[1]); // body
1431 EMIT(label_assign, continue_label);
1432 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1433#endif
1434
1435 // break/continue apply to outer loop (if any) in the else block
1436 comp->break_label = old_break_label;
1437 comp->continue_label = old_continue_label;
Damien429d7192013-10-04 19:53:11 +01001438
1439 compile_node(comp, pns->nodes[2]); // else
1440
1441 EMIT(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001442}
1443
Damienf72fd0e2013-11-06 20:20:49 +00001444// TODO preload end and step onto stack if they are not constants
1445// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001446void 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) {
Damienf72fd0e2013-11-06 20:20:49 +00001447 int old_break_label = comp->break_label;
1448 int old_continue_label = comp->continue_label;
1449
1450 int break_label = comp_next_label(comp);
1451 int continue_label = comp_next_label(comp);
1452
1453 comp->break_label = break_label;
1454 comp->continue_label = continue_label;
1455
1456 int top_label = comp_next_label(comp);
1457
1458 // compile: var = start
1459 compile_node(comp, pn_start);
1460 c_assign(comp, pn_var, ASSIGN_STORE);
1461
1462 EMIT(jump, continue_label);
1463 EMIT(label_assign, top_label);
1464
Damienf3822fc2013-11-09 20:12:03 +00001465 // compile body
1466 compile_node(comp, pn_body);
1467
Damienf72fd0e2013-11-06 20:20:49 +00001468 // compile: var += step
1469 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1470 compile_node(comp, pn_step);
1471 EMIT(binary_op, RT_BINARY_OP_INPLACE_ADD);
1472 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1473
Damienf72fd0e2013-11-06 20:20:49 +00001474 EMIT(label_assign, continue_label);
1475
1476 // compile: if var < end: goto top
1477 compile_node(comp, pn_var);
1478 compile_node(comp, pn_end);
1479 EMIT(compare_op, RT_COMPARE_OP_LESS);
1480 EMIT(pop_jump_if_true, top_label);
1481
1482 // break/continue apply to outer loop (if any) in the else block
1483 comp->break_label = old_break_label;
1484 comp->continue_label = old_continue_label;
1485
1486 compile_node(comp, pn_else);
1487
1488 EMIT(label_assign, break_label);
1489}
1490
Damiend99b0522013-12-21 18:17:45 +00001491void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001492#if !MICROPY_EMIT_CPYTHON
1493 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1494 // this is actually slower, but uses no heap memory
1495 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001496 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)) {
1497 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
1498 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == comp->qstr_range && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren) && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
1499 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1500 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001501 int n_args = list_get(&pn_range_args, PN_arglist, &args);
1502 if (1 <= n_args && n_args <= 3) {
Damiend99b0522013-12-21 18:17:45 +00001503 mp_parse_node_t pn_range_start;
1504 mp_parse_node_t pn_range_end;
1505 mp_parse_node_t pn_range_step;
Damienf72fd0e2013-11-06 20:20:49 +00001506 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001507 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001508 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001509 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001510 } else if (n_args == 2) {
1511 pn_range_start = args[0];
1512 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001513 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001514 } else {
1515 pn_range_start = args[0];
1516 pn_range_end = args[1];
1517 pn_range_step = args[2];
1518 }
1519 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1520 return;
1521 }
1522 }
1523 }
1524#endif
1525
Damien429d7192013-10-04 19:53:11 +01001526 int old_break_label = comp->break_label;
1527 int old_continue_label = comp->continue_label;
1528
Damienb05d7072013-10-05 13:37:10 +01001529 int for_label = comp_next_label(comp);
1530 int pop_label = comp_next_label(comp);
1531 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001532
Damienb05d7072013-10-05 13:37:10 +01001533 int break_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001534
1535 comp->continue_label = for_label;
1536 comp->break_label = break_label;
1537
Damience89a212013-10-15 22:25:17 +01001538 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1539#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001540 EMIT(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001541#endif
1542
Damien429d7192013-10-04 19:53:11 +01001543 compile_node(comp, pns->nodes[1]); // iterator
1544 EMIT(get_iter);
1545 EMIT(label_assign, for_label);
1546 EMIT(for_iter, pop_label);
1547 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1548 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001549 if (!EMIT(last_emit_was_return_value)) {
Damien429d7192013-10-04 19:53:11 +01001550 EMIT(jump, for_label);
1551 }
1552 EMIT(label_assign, pop_label);
1553 EMIT(for_iter_end);
1554
1555 // break/continue apply to outer loop (if any) in the else block
1556 comp->break_label = old_break_label;
1557 comp->continue_label = old_continue_label;
1558
Damience89a212013-10-15 22:25:17 +01001559#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001560 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001561#endif
Damien429d7192013-10-04 19:53:11 +01001562
1563 compile_node(comp, pns->nodes[3]); // else (not tested)
1564
1565 EMIT(label_assign, break_label);
1566 EMIT(label_assign, end_label);
1567}
1568
Damiend99b0522013-12-21 18:17:45 +00001569void 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 +01001570 // this function is a bit of a hack at the moment
1571 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1572
1573 // setup code
1574 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001575 int l1 = comp_next_label(comp);
1576 int success_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001577 comp->except_nest_level += 1; // for correct handling of continue
1578 EMIT(setup_except, l1);
1579 compile_node(comp, pn_body); // body
1580 EMIT(pop_block);
1581 EMIT(jump, success_label);
1582 EMIT(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001583 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001584
1585 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001586 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1587 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001588
1589 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001590 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001591
Damiend99b0522013-12-21 18:17:45 +00001592 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001593 // this is a catch all exception handler
1594 if (i + 1 != n_except) {
1595 printf("SyntaxError: default 'except:' must be last\n");
1596 return;
1597 }
1598 } else {
1599 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001600 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1601 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1602 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1603 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001604 // handler binds the exception to a local
1605 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001606 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001607 }
1608 }
1609 EMIT(dup_top);
1610 compile_node(comp, pns_exception_expr);
1611 EMIT(compare_op, RT_COMPARE_OP_EXCEPTION_MATCH);
1612 EMIT(pop_jump_if_false, end_finally_label);
1613 }
1614
1615 EMIT(pop_top);
1616
1617 if (qstr_exception_local == 0) {
1618 EMIT(pop_top);
1619 } else {
Damien4b03e772013-10-05 14:17:09 +01001620 EMIT(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001621 }
1622
1623 EMIT(pop_top);
1624
Damiene2880aa2013-12-20 14:22:59 +00001625 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001626 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001627 l3 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001628 EMIT(setup_finally, l3);
1629 }
1630 compile_node(comp, pns_except->nodes[1]);
1631 if (qstr_exception_local != 0) {
1632 EMIT(pop_block);
1633 }
1634 EMIT(pop_except);
1635 if (qstr_exception_local != 0) {
Damiend99b0522013-12-21 18:17:45 +00001636 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001637 EMIT(label_assign, l3);
Damiend99b0522013-12-21 18:17:45 +00001638 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien4b03e772013-10-05 14:17:09 +01001639 EMIT(store_id, qstr_exception_local);
1640 EMIT(delete_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001641 EMIT(end_finally);
1642 }
1643 EMIT(jump, l2);
1644 EMIT(label_assign, end_finally_label);
1645 }
1646
1647 EMIT(end_finally);
1648 EMIT(label_assign, success_label);
1649 comp->except_nest_level -= 1;
1650 compile_node(comp, pn_else); // else block, can be null
1651 EMIT(label_assign, l2);
1652 EMIT(set_stack_size, stack_size);
1653}
1654
Damiend99b0522013-12-21 18:17:45 +00001655void 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 +01001656 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1657 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001658 int l_finally_block = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001659 EMIT(setup_finally, l_finally_block);
1660 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001661 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001662 compile_node(comp, pn_body);
1663 } else {
1664 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1665 }
1666 EMIT(pop_block);
Damiend99b0522013-12-21 18:17:45 +00001667 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001668 EMIT(label_assign, l_finally_block);
1669 compile_node(comp, pn_finally);
1670 EMIT(end_finally);
1671 EMIT(set_stack_size, stack_size);
1672}
1673
Damiend99b0522013-12-21 18:17:45 +00001674void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1675 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1676 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1677 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001678 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001679 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1680 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001681 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001682 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001683 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001684 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001685 // no finally
1686 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1687 } else {
1688 // have finally
Damiend99b0522013-12-21 18:17:45 +00001689 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 +01001690 }
1691 } else {
1692 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001693 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001694 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001695 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001696 }
1697 } else {
1698 // shouldn't happen
1699 assert(0);
1700 }
1701}
1702
Damiend99b0522013-12-21 18:17:45 +00001703void 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 +01001704 if (n == 0) {
1705 // no more pre-bits, compile the body of the with
1706 compile_node(comp, body);
1707 } else {
Damienb05d7072013-10-05 13:37:10 +01001708 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001709 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001710 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001711 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001712 compile_node(comp, pns->nodes[0]);
1713 EMIT(setup_with, l_end);
1714 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1715 } else {
1716 // this pre-bit is just an expression
1717 compile_node(comp, nodes[0]);
1718 EMIT(setup_with, l_end);
1719 EMIT(pop_top);
1720 }
1721 // compile additional pre-bits and the body
1722 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1723 // finish this with block
1724 EMIT(pop_block);
Damiend99b0522013-12-21 18:17:45 +00001725 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001726 EMIT(label_assign, l_end);
1727 EMIT(with_cleanup);
1728 EMIT(end_finally);
1729 }
1730}
1731
Damiend99b0522013-12-21 18:17:45 +00001732void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001733 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001734 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001735 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1736 assert(n > 0);
1737
1738 // compile in a nested fashion
1739 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1740}
1741
Damiend99b0522013-12-21 18:17:45 +00001742void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1743 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001744 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1745 // for REPL, evaluate then print the expression
1746 EMIT(load_id, qstr_from_str_static("__repl_print__"));
1747 compile_node(comp, pns->nodes[0]);
1748 EMIT(call_function, 1, 0, false, false);
1749 EMIT(pop_top);
1750
Damien429d7192013-10-04 19:53:11 +01001751 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001752 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001753 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001754 // do nothing with a lonely constant
1755 } else {
1756 compile_node(comp, pns->nodes[0]); // just an expression
1757 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1758 }
Damien429d7192013-10-04 19:53:11 +01001759 }
1760 } else {
Damiend99b0522013-12-21 18:17:45 +00001761 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1762 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001763 if (kind == PN_expr_stmt_augassign) {
1764 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1765 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001766 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001767 // note that we don't really need to implement separate inplace ops, just normal binary ops will suffice
Damiend99b0522013-12-21 18:17:45 +00001768 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
1769 case MP_TOKEN_DEL_PIPE_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_OR); break;
1770 case MP_TOKEN_DEL_CARET_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_XOR); break;
1771 case MP_TOKEN_DEL_AMPERSAND_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_AND); break;
1772 case MP_TOKEN_DEL_DBL_LESS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_LSHIFT); break;
1773 case MP_TOKEN_DEL_DBL_MORE_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_RSHIFT); break;
1774 case MP_TOKEN_DEL_PLUS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_ADD); break;
1775 case MP_TOKEN_DEL_MINUS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_SUBTRACT); break;
1776 case MP_TOKEN_DEL_STAR_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_MULTIPLY); break;
1777 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_FLOOR_DIVIDE); break;
1778 case MP_TOKEN_DEL_SLASH_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_TRUE_DIVIDE); break;
1779 case MP_TOKEN_DEL_PERCENT_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_MODULO); break;
1780 case MP_TOKEN_DEL_DBL_STAR_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_POWER); break;
Damien429d7192013-10-04 19:53:11 +01001781 default: assert(0); // shouldn't happen
1782 }
1783 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1784 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001785 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1786 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001787 // following CPython, we store left-most first
1788 if (rhs > 0) {
1789 EMIT(dup_top);
1790 }
1791 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1792 for (int i = 0; i < rhs; i++) {
1793 if (i + 1 < rhs) {
1794 EMIT(dup_top);
1795 }
Damiend99b0522013-12-21 18:17:45 +00001796 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001797 }
1798 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001799 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1800 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1801 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1802 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001803 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001804 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1805 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001806 compile_node(comp, pns10->nodes[0]); // rhs
1807 compile_node(comp, pns10->nodes[1]); // rhs
1808 EMIT(rot_two);
1809 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1810 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001811 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1812 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1813 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1814 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001815 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001816 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1817 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001818 compile_node(comp, pns10->nodes[0]); // rhs
1819 compile_node(comp, pns10->nodes[1]); // rhs
1820 compile_node(comp, pns10->nodes[2]); // rhs
1821 EMIT(rot_three);
1822 EMIT(rot_two);
1823 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1824 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1825 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1826 } else {
1827 compile_node(comp, pns1->nodes[0]); // rhs
1828 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1829 }
1830 } else {
1831 // shouldn't happen
1832 assert(0);
1833 }
1834 }
1835}
1836
Damiend99b0522013-12-21 18:17:45 +00001837void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1838 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001839 compile_node(comp, pns->nodes[0]);
1840 for (int i = 1; i < num_nodes; i += 1) {
1841 compile_node(comp, pns->nodes[i]);
1842 EMIT(binary_op, binary_op);
1843 }
1844}
1845
Damiend99b0522013-12-21 18:17:45 +00001846void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1847 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1848 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001849
1850 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001851 int l_fail = comp_next_label(comp);
1852 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001853 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1854 compile_node(comp, pns->nodes[0]); // success value
1855 EMIT(jump, l_end);
1856 EMIT(label_assign, l_fail);
1857 EMIT(set_stack_size, stack_size); // force stack size reset
1858 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1859 EMIT(label_assign, l_end);
1860}
1861
Damiend99b0522013-12-21 18:17:45 +00001862void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001863 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001864 //mp_parse_node_t pn_params = pns->nodes[0];
1865 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001866
1867 if (comp->pass == PASS_1) {
1868 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001869 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 +01001870 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001871 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001872 }
1873
1874 // get the scope for this lambda
1875 scope_t *this_scope = (scope_t*)pns->nodes[2];
1876
1877 // make the lambda
1878 close_over_variables_etc(comp, this_scope, 0, 0);
1879}
1880
Damiend99b0522013-12-21 18:17:45 +00001881void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001882 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001883 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001884 for (int i = 0; i < n; i += 1) {
1885 compile_node(comp, pns->nodes[i]);
1886 if (i + 1 < n) {
1887 EMIT(jump_if_true_or_pop, l_end);
1888 }
1889 }
1890 EMIT(label_assign, l_end);
1891}
1892
Damiend99b0522013-12-21 18:17:45 +00001893void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001894 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001895 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001896 for (int i = 0; i < n; i += 1) {
1897 compile_node(comp, pns->nodes[i]);
1898 if (i + 1 < n) {
1899 EMIT(jump_if_false_or_pop, l_end);
1900 }
1901 }
1902 EMIT(label_assign, l_end);
1903}
1904
Damiend99b0522013-12-21 18:17:45 +00001905void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001906 compile_node(comp, pns->nodes[0]);
1907 EMIT(unary_op, RT_UNARY_OP_NOT);
1908}
1909
Damiend99b0522013-12-21 18:17:45 +00001910void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001911 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001912 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001913 compile_node(comp, pns->nodes[0]);
1914 bool multi = (num_nodes > 3);
1915 int l_fail = 0;
1916 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001917 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001918 }
1919 for (int i = 1; i + 1 < num_nodes; i += 2) {
1920 compile_node(comp, pns->nodes[i + 1]);
1921 if (i + 2 < num_nodes) {
1922 EMIT(dup_top);
1923 EMIT(rot_three);
1924 }
Damiend99b0522013-12-21 18:17:45 +00001925 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS)) {
Damien429d7192013-10-04 19:53:11 +01001926 EMIT(compare_op, RT_COMPARE_OP_LESS);
Damiend99b0522013-12-21 18:17:45 +00001927 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE)) {
Damien429d7192013-10-04 19:53:11 +01001928 EMIT(compare_op, RT_COMPARE_OP_MORE);
Damiend99b0522013-12-21 18:17:45 +00001929 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_EQUAL)) {
Damien429d7192013-10-04 19:53:11 +01001930 EMIT(compare_op, RT_COMPARE_OP_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001931 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS_EQUAL)) {
Damien429d7192013-10-04 19:53:11 +01001932 EMIT(compare_op, RT_COMPARE_OP_LESS_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001933 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE_EQUAL)) {
Damien429d7192013-10-04 19:53:11 +01001934 EMIT(compare_op, RT_COMPARE_OP_MORE_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001935 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_NOT_EQUAL)) {
Damien429d7192013-10-04 19:53:11 +01001936 EMIT(compare_op, RT_COMPARE_OP_NOT_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001937 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_KW_IN)) {
Damien429d7192013-10-04 19:53:11 +01001938 EMIT(compare_op, RT_COMPARE_OP_IN);
Damiend99b0522013-12-21 18:17:45 +00001939 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
1940 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
1941 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01001942 if (kind == PN_comp_op_not_in) {
1943 EMIT(compare_op, RT_COMPARE_OP_NOT_IN);
1944 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00001945 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001946 EMIT(compare_op, RT_COMPARE_OP_IS);
1947 } else {
1948 EMIT(compare_op, RT_COMPARE_OP_IS_NOT);
1949 }
1950 } else {
1951 // shouldn't happen
1952 assert(0);
1953 }
1954 } else {
1955 // shouldn't happen
1956 assert(0);
1957 }
1958 if (i + 2 < num_nodes) {
1959 EMIT(jump_if_false_or_pop, l_fail);
1960 }
1961 }
1962 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001963 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001964 EMIT(jump, l_end);
1965 EMIT(label_assign, l_fail);
1966 EMIT(rot_two);
1967 EMIT(pop_top);
1968 EMIT(label_assign, l_end);
1969 EMIT(set_stack_size, stack_size + 1); // force stack size
1970 }
1971}
1972
Damiend99b0522013-12-21 18:17:45 +00001973void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001974 // TODO
1975 assert(0);
1976 compile_node(comp, pns->nodes[0]);
1977 //EMIT(unary_op, "UNARY_STAR");
1978}
1979
Damiend99b0522013-12-21 18:17:45 +00001980void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001981 c_binary_op(comp, pns, RT_BINARY_OP_OR);
1982}
1983
Damiend99b0522013-12-21 18:17:45 +00001984void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001985 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
1986}
1987
Damiend99b0522013-12-21 18:17:45 +00001988void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001989 c_binary_op(comp, pns, RT_BINARY_OP_AND);
1990}
1991
Damiend99b0522013-12-21 18:17:45 +00001992void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1993 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001994 compile_node(comp, pns->nodes[0]);
1995 for (int i = 1; i + 1 < num_nodes; i += 2) {
1996 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00001997 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien429d7192013-10-04 19:53:11 +01001998 EMIT(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00001999 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien429d7192013-10-04 19:53:11 +01002000 EMIT(binary_op, RT_BINARY_OP_RSHIFT);
2001 } else {
2002 // shouldn't happen
2003 assert(0);
2004 }
2005 }
2006}
2007
Damiend99b0522013-12-21 18:17:45 +00002008void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2009 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002010 compile_node(comp, pns->nodes[0]);
2011 for (int i = 1; i + 1 < num_nodes; i += 2) {
2012 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002013 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien429d7192013-10-04 19:53:11 +01002014 EMIT(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002015 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien429d7192013-10-04 19:53:11 +01002016 EMIT(binary_op, RT_BINARY_OP_SUBTRACT);
2017 } else {
2018 // shouldn't happen
2019 assert(0);
2020 }
2021 }
2022}
2023
Damiend99b0522013-12-21 18:17:45 +00002024void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2025 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002026 compile_node(comp, pns->nodes[0]);
2027 for (int i = 1; i + 1 < num_nodes; i += 2) {
2028 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002029 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien429d7192013-10-04 19:53:11 +01002030 EMIT(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002031 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien429d7192013-10-04 19:53:11 +01002032 EMIT(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002033 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +01002034 EMIT(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002035 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien429d7192013-10-04 19:53:11 +01002036 EMIT(binary_op, RT_BINARY_OP_MODULO);
2037 } else {
2038 // shouldn't happen
2039 assert(0);
2040 }
2041 }
2042}
2043
Damiend99b0522013-12-21 18:17:45 +00002044void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002045 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002046 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien429d7192013-10-04 19:53:11 +01002047 EMIT(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002048 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien429d7192013-10-04 19:53:11 +01002049 EMIT(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002050 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien429d7192013-10-04 19:53:11 +01002051 EMIT(unary_op, RT_UNARY_OP_INVERT);
2052 } else {
2053 // shouldn't happen
2054 assert(0);
2055 }
2056}
2057
Damiend99b0522013-12-21 18:17:45 +00002058void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool is_method_call) {
Damien429d7192013-10-04 19:53:11 +01002059 // function to call is on top of stack
2060
2061 int old_n_arg_keyword = comp->n_arg_keyword;
2062 bool old_have_star_arg = comp->have_star_arg;
2063 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2064 comp->n_arg_keyword = 0;
2065 comp->have_star_arg = false;
2066 comp->have_dbl_star_arg = false;
2067
2068 compile_node(comp, pns->nodes[0]); // arguments to function call; can be null
2069
2070 // compute number of positional arguments
2071 int n_positional = list_len(pns->nodes[0], PN_arglist) - comp->n_arg_keyword;
2072 if (comp->have_star_arg) {
2073 n_positional -= 1;
2074 }
2075 if (comp->have_dbl_star_arg) {
2076 n_positional -= 1;
2077 }
2078
2079 if (is_method_call) {
2080 EMIT(call_method, n_positional, comp->n_arg_keyword, comp->have_star_arg, comp->have_dbl_star_arg);
2081 } else {
2082 EMIT(call_function, n_positional, comp->n_arg_keyword, comp->have_star_arg, comp->have_dbl_star_arg);
2083 }
2084
2085 comp->n_arg_keyword = old_n_arg_keyword;
2086 comp->have_star_arg = old_have_star_arg;
2087 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2088}
2089
Damiend99b0522013-12-21 18:17:45 +00002090void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2091 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002092 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002093 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 +01002094 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002095 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2096 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
2097 EMIT(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien429d7192013-10-04 19:53:11 +01002098 compile_trailer_paren_helper(comp, pns_paren, true);
2099 i += 1;
2100 } else {
2101 compile_node(comp, pns->nodes[i]);
2102 }
2103 }
2104}
2105
Damiend99b0522013-12-21 18:17:45 +00002106void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002107 compile_node(comp, pns->nodes[0]);
2108 EMIT(binary_op, RT_BINARY_OP_POWER);
2109}
2110
Damiend99b0522013-12-21 18:17:45 +00002111void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002112 // a list of strings
Damien63321742013-12-10 17:41:49 +00002113
2114 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002115 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002116 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002117 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002118 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002119 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2120 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2121 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002122 if (i == 0) {
2123 string_kind = pn_kind;
2124 } else if (pn_kind != string_kind) {
2125 printf("SyntaxError: cannot mix bytes and nonbytes literals\n");
2126 return;
2127 }
Damiend99b0522013-12-21 18:17:45 +00002128 const char *str = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien63321742013-12-10 17:41:49 +00002129 n_bytes += strlen(str);
Damien429d7192013-10-04 19:53:11 +01002130 }
Damien63321742013-12-10 17:41:49 +00002131
2132 // allocate memory for concatenated string/bytes
2133 char *cat_str = m_new(char, n_bytes + 1);
Damien63321742013-12-10 17:41:49 +00002134
2135 // concatenate string/bytes
Damien Georgefe8fb912014-01-02 16:36:09 +00002136 char *s_dest = cat_str;
Damien63321742013-12-10 17:41:49 +00002137 for (int i = 0; i < n; i++) {
Damien Georgefe8fb912014-01-02 16:36:09 +00002138 const char *s = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
2139 size_t s_len = strlen(s);
2140 memcpy(s_dest, s, s_len);
2141 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002142 }
Damien Georgefe8fb912014-01-02 16:36:09 +00002143 *s_dest = '\0';
Damien63321742013-12-10 17:41:49 +00002144
Damien732407f2013-12-29 19:33:23 +00002145 EMIT(load_const_str, qstr_from_str_take(cat_str, n_bytes + 1), string_kind == MP_PARSE_NODE_BYTES);
Damien429d7192013-10-04 19:53:11 +01002146}
2147
2148// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002149void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2150 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2151 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2152 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002153
2154 if (comp->pass == PASS_1) {
2155 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002156 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 +01002157 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002158 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002159 }
2160
2161 // get the scope for this comprehension
2162 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2163
2164 // compile the comprehension
2165 close_over_variables_etc(comp, this_scope, 0, 0);
2166
2167 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2168 EMIT(get_iter);
2169 EMIT(call_function, 1, 0, false, false);
2170}
2171
Damiend99b0522013-12-21 18:17:45 +00002172void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2173 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002174 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002175 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2176 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2177 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2178 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2179 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2180 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2181 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002182 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002183 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002184 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002185 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002186 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002187 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002188 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002189 // generator expression
2190 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2191 } else {
2192 // tuple with 2 items
2193 goto tuple_with_2_items;
2194 }
2195 } else {
2196 // tuple with 2 items
2197 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002198 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002199 }
2200 } else {
2201 // parenthesis around a single item, is just that item
2202 compile_node(comp, pns->nodes[0]);
2203 }
2204}
2205
Damiend99b0522013-12-21 18:17:45 +00002206void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2207 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002208 // empty list
2209 EMIT(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002210 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2211 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2212 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2213 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2214 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002215 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002216 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002217 compile_node(comp, pns2->nodes[0]);
2218 EMIT(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002219 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002220 // list of many items
2221 compile_node(comp, pns2->nodes[0]);
2222 compile_generic_all_nodes(comp, pns3);
Damiend99b0522013-12-21 18:17:45 +00002223 EMIT(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
2224 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002225 // list comprehension
2226 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2227 } else {
2228 // list with 2 items
2229 goto list_with_2_items;
2230 }
2231 } else {
2232 // list with 2 items
2233 list_with_2_items:
2234 compile_node(comp, pns2->nodes[0]);
2235 compile_node(comp, pns2->nodes[1]);
2236 EMIT(build_list, 2);
2237 }
2238 } else {
2239 // list with 1 item
2240 compile_node(comp, pns->nodes[0]);
2241 EMIT(build_list, 1);
2242 }
2243}
2244
Damiend99b0522013-12-21 18:17:45 +00002245void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2246 mp_parse_node_t pn = pns->nodes[0];
2247 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002248 // empty dict
2249 EMIT(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002250 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2251 pns = (mp_parse_node_struct_t*)pn;
2252 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002253 // dict with one element
2254 EMIT(build_map, 1);
2255 compile_node(comp, pn);
2256 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002257 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2258 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2259 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2260 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002261 // dict/set with multiple elements
2262
2263 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002264 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002265 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2266
2267 // first element sets whether it's a dict or set
2268 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002269 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002270 // a dictionary
2271 EMIT(build_map, 1 + n);
2272 compile_node(comp, pns->nodes[0]);
2273 EMIT(store_map);
2274 is_dict = true;
2275 } else {
2276 // a set
2277 compile_node(comp, pns->nodes[0]); // 1st value of set
2278 is_dict = false;
2279 }
2280
2281 // process rest of elements
2282 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002283 mp_parse_node_t pn = nodes[i];
2284 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002285 compile_node(comp, pn);
2286 if (is_dict) {
2287 if (!is_key_value) {
2288 printf("SyntaxError?: expecting key:value for dictionary");
2289 return;
2290 }
2291 EMIT(store_map);
2292 } else {
2293 if (is_key_value) {
2294 printf("SyntaxError?: expecting just a value for set");
2295 return;
2296 }
2297 }
2298 }
2299
2300 // if it's a set, build it
2301 if (!is_dict) {
2302 EMIT(build_set, 1 + n);
2303 }
Damiend99b0522013-12-21 18:17:45 +00002304 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002305 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002306 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002307 // a dictionary comprehension
2308 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2309 } else {
2310 // a set comprehension
2311 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2312 }
2313 } else {
2314 // shouldn't happen
2315 assert(0);
2316 }
2317 } else {
2318 // set with one element
2319 goto set_with_one_element;
2320 }
2321 } else {
2322 // set with one element
2323 set_with_one_element:
2324 compile_node(comp, pn);
2325 EMIT(build_set, 1);
2326 }
2327}
2328
Damiend99b0522013-12-21 18:17:45 +00002329void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002330 compile_trailer_paren_helper(comp, pns, false);
2331}
2332
Damiend99b0522013-12-21 18:17:45 +00002333void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002334 // object who's index we want is on top of stack
2335 compile_node(comp, pns->nodes[0]); // the index
2336 EMIT(binary_op, RT_BINARY_OP_SUBSCR);
2337}
2338
Damiend99b0522013-12-21 18:17:45 +00002339void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002340 // object who's attribute we want is on top of stack
Damiend99b0522013-12-21 18:17:45 +00002341 EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002342}
2343
Damiend99b0522013-12-21 18:17:45 +00002344void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2345 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2346 mp_parse_node_t pn = pns->nodes[0];
2347 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002348 // [?:]
Damiend99b0522013-12-21 18:17:45 +00002349 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002350 EMIT(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002351 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2352 pns = (mp_parse_node_struct_t*)pn;
2353 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
2354 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002355 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002356 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002357 // [?::]
2358 EMIT(build_slice, 2);
2359 } else {
2360 // [?::x]
2361 compile_node(comp, pn);
2362 EMIT(build_slice, 3);
2363 }
Damiend99b0522013-12-21 18:17:45 +00002364 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002365 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002366 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2367 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2368 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2369 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002370 // [?:x:]
2371 EMIT(build_slice, 2);
2372 } else {
2373 // [?:x:x]
2374 compile_node(comp, pns->nodes[0]);
2375 EMIT(build_slice, 3);
2376 }
2377 } else {
2378 // [?:x]
2379 compile_node(comp, pn);
2380 EMIT(build_slice, 2);
2381 }
2382 } else {
2383 // [?:x]
2384 compile_node(comp, pn);
2385 EMIT(build_slice, 2);
2386 }
2387}
2388
Damiend99b0522013-12-21 18:17:45 +00002389void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002390 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002391 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2392 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002393}
2394
Damiend99b0522013-12-21 18:17:45 +00002395void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
2396 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002397 compile_subscript_3_helper(comp, pns);
2398}
2399
Damiend99b0522013-12-21 18:17:45 +00002400void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002401 // if this is called then we are compiling a dict key:value pair
2402 compile_node(comp, pns->nodes[1]); // value
2403 compile_node(comp, pns->nodes[0]); // key
2404}
2405
Damiend99b0522013-12-21 18:17:45 +00002406void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002407 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002408 // store class object into class name
Damien4b03e772013-10-05 14:17:09 +01002409 EMIT(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002410}
2411
Damiend99b0522013-12-21 18:17:45 +00002412void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002413 if (comp->have_star_arg) {
2414 printf("SyntaxError?: can't have multiple *x\n");
2415 return;
2416 }
2417 comp->have_star_arg = true;
2418 compile_node(comp, pns->nodes[0]);
2419}
2420
Damiend99b0522013-12-21 18:17:45 +00002421void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002422 if (comp->have_dbl_star_arg) {
2423 printf("SyntaxError?: can't have multiple **x\n");
2424 return;
2425 }
2426 comp->have_dbl_star_arg = true;
2427 compile_node(comp, pns->nodes[0]);
2428}
2429
Damiend99b0522013-12-21 18:17:45 +00002430void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2431 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2432 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2433 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2434 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002435 printf("SyntaxError?: lhs of keyword argument must be an id\n");
2436 return;
2437 }
Damiend99b0522013-12-21 18:17:45 +00002438 EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002439 compile_node(comp, pns2->nodes[0]);
2440 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002441 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002442 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2443 } else {
2444 // shouldn't happen
2445 assert(0);
2446 }
2447}
2448
Damiend99b0522013-12-21 18:17:45 +00002449void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002450 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
2451 printf("SyntaxError: 'yield' outside function\n");
2452 return;
2453 }
Damiend99b0522013-12-21 18:17:45 +00002454 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
2455 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002456 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002457 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2458 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002459 compile_node(comp, pns->nodes[0]);
2460 EMIT(get_iter);
Damiend99b0522013-12-21 18:17:45 +00002461 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002462 EMIT(yield_from);
2463 } else {
2464 compile_node(comp, pns->nodes[0]);
2465 EMIT(yield_value);
2466 }
2467}
2468
Damiend99b0522013-12-21 18:17:45 +00002469typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Damien429d7192013-10-04 19:53:11 +01002470static compile_function_t compile_function[] = {
2471 NULL,
2472#define nc NULL
2473#define c(f) compile_##f
2474#define DEF_RULE(rule, comp, kind, arg...) comp,
2475#include "grammar.h"
2476#undef nc
2477#undef c
2478#undef DEF_RULE
2479};
2480
Damiend99b0522013-12-21 18:17:45 +00002481void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2482 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002483 // pass
Damiend99b0522013-12-21 18:17:45 +00002484 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
2485 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
2486 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
2487 case MP_PARSE_NODE_ID: EMIT(load_id, arg); break;
2488 case MP_PARSE_NODE_SMALL_INT: EMIT(load_const_small_int, arg); break;
2489 case MP_PARSE_NODE_INTEGER: EMIT(load_const_int, arg); break;
2490 case MP_PARSE_NODE_DECIMAL: EMIT(load_const_dec, arg); break;
2491 case MP_PARSE_NODE_STRING: EMIT(load_const_str, arg, false); break;
2492 case MP_PARSE_NODE_BYTES: EMIT(load_const_str, arg, true); break;
2493 case MP_PARSE_NODE_TOKEN:
2494 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002495 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002496 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002497 // do nothing
2498 } else {
2499 EMIT(load_const_tok, arg);
2500 }
2501 break;
Damien429d7192013-10-04 19:53:11 +01002502 default: assert(0);
2503 }
2504 } else {
Damiend99b0522013-12-21 18:17:45 +00002505 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2506 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002507 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002508 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
2509 mp_parse_node_show(pn, 0);
Damien429d7192013-10-04 19:53:11 +01002510 assert(0);
2511 } else {
2512 f(comp, pns);
2513 }
2514 }
2515}
2516
Damiend99b0522013-12-21 18:17:45 +00002517void 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 +01002518 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002519 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002520 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2521 if (MP_PARSE_NODE_IS_ID(pn)) {
2522 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002523 if (comp->have_bare_star) {
2524 // comes after a bare star, so doesn't count as a parameter
2525 } else {
2526 comp->scope_cur->num_params += 1;
2527 }
Damienb14de212013-10-06 00:28:28 +01002528 } else {
Damiend99b0522013-12-21 18:17:45 +00002529 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2530 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2531 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2532 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002533 //int node_index = 1; unused
2534 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002535 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002536 // this parameter has an annotation
2537 pn_annotation = pns->nodes[1];
2538 }
2539 //node_index = 2; unused
2540 }
2541 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002542 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002543 // this parameter has a default value
2544 if (comp->have_bare_star) {
2545 comp->scope_cur->num_dict_params += 1;
2546 } else {
2547 comp->scope_cur->num_default_params += 1;
2548 }
2549 }
2550 */
2551 if (comp->have_bare_star) {
2552 // comes after a bare star, so doesn't count as a parameter
2553 } else {
2554 comp->scope_cur->num_params += 1;
2555 }
Damiend99b0522013-12-21 18:17:45 +00002556 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2557 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002558 // bare star
2559 // TODO see http://www.python.org/dev/peps/pep-3102/
2560 comp->have_bare_star = true;
2561 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002562 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002563 // named star
2564 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002565 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2566 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002567 // named star with annotation
2568 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002569 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2570 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002571 pn_annotation = pns->nodes[1];
2572 } else {
2573 // shouldn't happen
2574 assert(0);
2575 }
Damiend99b0522013-12-21 18:17:45 +00002576 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2577 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2578 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002579 // this parameter has an annotation
2580 pn_annotation = pns->nodes[1];
2581 }
2582 comp->scope_cur->flags |= SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002583 } else {
Damienb14de212013-10-06 00:28:28 +01002584 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002585 assert(0);
2586 }
Damien429d7192013-10-04 19:53:11 +01002587 }
2588
2589 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002590 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002591 // TODO this parameter has an annotation
2592 }
2593 bool added;
2594 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2595 if (!added) {
2596 printf("SyntaxError?: same name used for parameter; %s\n", qstr_str(param_name));
2597 return;
2598 }
2599 id_info->param = true;
2600 id_info->kind = ID_INFO_KIND_LOCAL;
2601 }
2602}
2603
Damiend99b0522013-12-21 18:17:45 +00002604void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002605 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2606}
2607
Damiend99b0522013-12-21 18:17:45 +00002608void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002609 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2610}
2611
Damiend99b0522013-12-21 18:17:45 +00002612void 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 +01002613 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002614 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002615 // no more nested if/for; compile inner expression
2616 compile_node(comp, pn_inner_expr);
2617 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
2618 EMIT(list_append, for_depth + 2);
2619 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
2620 EMIT(map_add, for_depth + 2);
2621 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
2622 EMIT(set_add, for_depth + 2);
2623 } else {
2624 EMIT(yield_value);
2625 EMIT(pop_top);
2626 }
Damiend99b0522013-12-21 18:17:45 +00002627 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002628 // if condition
Damiend99b0522013-12-21 18:17:45 +00002629 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002630 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2631 pn_iter = pns_comp_if->nodes[1];
2632 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002633 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002634 // for loop
Damiend99b0522013-12-21 18:17:45 +00002635 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002636 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002637 int l_end2 = comp_next_label(comp);
2638 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002639 EMIT(get_iter);
2640 EMIT(label_assign, l_top2);
2641 EMIT(for_iter, l_end2);
2642 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2643 compile_scope_comp_iter(comp, pns_comp_for2->nodes[2], pn_inner_expr, l_top2, for_depth + 1);
2644 EMIT(jump, l_top2);
2645 EMIT(label_assign, l_end2);
2646 EMIT(for_iter_end);
2647 } else {
2648 // shouldn't happen
2649 assert(0);
2650 }
2651}
2652
Damiend99b0522013-12-21 18:17:45 +00002653void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002654 // see http://www.python.org/dev/peps/pep-0257/
2655
2656 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002657 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002658 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002659 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002660 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002661 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2662 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002663 for (int i = 0; i < num_nodes; i++) {
2664 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002665 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 +00002666 // not a newline, so this is the first statement; finish search
2667 break;
2668 }
2669 }
2670 // 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 +00002671 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002672 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002673 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002674 } else {
2675 return;
2676 }
2677
2678 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002679 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2680 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2681 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2682 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2683 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002684 compile_node(comp, pns->nodes[0]); // a doc string
2685 // store doc string
Damien4b03e772013-10-05 14:17:09 +01002686 EMIT(store_id, comp->qstr___doc__);
Damien429d7192013-10-04 19:53:11 +01002687 }
2688 }
2689 }
2690}
2691
2692void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2693 comp->pass = pass;
2694 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002695 comp->next_label = 1;
Damien415eb6f2013-10-05 12:19:06 +01002696 EMIT(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002697
2698 if (comp->pass == PASS_1) {
2699 scope->stack_size = 0;
2700 }
2701
Damien5ac1b2e2013-10-18 19:58:12 +01002702#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002703 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002704 scope_print_info(scope);
2705 }
Damien5ac1b2e2013-10-18 19:58:12 +01002706#endif
Damien429d7192013-10-04 19:53:11 +01002707
2708 // compile
2709 if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002710 if (!comp->is_repl) {
2711 check_for_doc_string(comp, scope->pn);
2712 }
Damien429d7192013-10-04 19:53:11 +01002713 compile_node(comp, scope->pn);
Damiend99b0522013-12-21 18:17:45 +00002714 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002715 EMIT(return_value);
2716 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002717 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2718 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2719 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002720
2721 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002722 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002723 if (comp->pass == PASS_1) {
2724 comp->have_bare_star = false;
2725 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2726 }
2727
Damiend99b0522013-12-21 18:17:45 +00002728 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // 2 is something...
Damien429d7192013-10-04 19:53:11 +01002729
2730 compile_node(comp, pns->nodes[3]); // 3 is function body
2731 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002732 if (!EMIT(last_emit_was_return_value)) {
Damiend99b0522013-12-21 18:17:45 +00002733 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002734 EMIT(return_value);
2735 }
2736 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002737 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2738 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2739 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002740
2741 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002742 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002743 if (comp->pass == PASS_1) {
2744 comp->have_bare_star = false;
2745 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2746 }
2747
2748 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2749 EMIT(return_value);
2750 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2751 // a bit of a hack at the moment
2752
Damiend99b0522013-12-21 18:17:45 +00002753 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2754 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2755 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2756 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2757 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002758
Damien6cdd3af2013-10-05 18:08:26 +01002759 qstr qstr_arg = qstr_from_str_static(".0");
Damien429d7192013-10-04 19:53:11 +01002760 if (comp->pass == PASS_1) {
2761 bool added;
2762 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2763 assert(added);
2764 id_info->kind = ID_INFO_KIND_LOCAL;
2765 scope->num_params = 1;
2766 }
2767
2768 if (scope->kind == SCOPE_LIST_COMP) {
2769 EMIT(build_list, 0);
2770 } else if (scope->kind == SCOPE_DICT_COMP) {
2771 EMIT(build_map, 0);
2772 } else if (scope->kind == SCOPE_SET_COMP) {
2773 EMIT(build_set, 0);
2774 }
2775
Damienb05d7072013-10-05 13:37:10 +01002776 int l_end = comp_next_label(comp);
2777 int l_top = comp_next_label(comp);
Damien4b03e772013-10-05 14:17:09 +01002778 EMIT(load_id, qstr_arg);
Damien429d7192013-10-04 19:53:11 +01002779 EMIT(label_assign, l_top);
2780 EMIT(for_iter, l_end);
2781 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2782 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
2783 EMIT(jump, l_top);
2784 EMIT(label_assign, l_end);
2785 EMIT(for_iter_end);
2786
2787 if (scope->kind == SCOPE_GEN_EXPR) {
Damiend99b0522013-12-21 18:17:45 +00002788 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002789 }
2790 EMIT(return_value);
2791 } else {
2792 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00002793 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2794 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2795 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01002796
2797 if (comp->pass == PASS_1) {
2798 bool added;
2799 id_info_t *id_info = scope_find_or_add_id(scope, comp->qstr___class__, &added);
2800 assert(added);
2801 id_info->kind = ID_INFO_KIND_LOCAL;
2802 id_info = scope_find_or_add_id(scope, comp->qstr___locals__, &added);
2803 assert(added);
2804 id_info->kind = ID_INFO_KIND_LOCAL;
2805 id_info->param = true;
2806 scope->num_params = 1; // __locals__ is the parameter
2807 }
2808
Damien4b03e772013-10-05 14:17:09 +01002809 EMIT(load_id, comp->qstr___locals__);
Damien429d7192013-10-04 19:53:11 +01002810 EMIT(store_locals);
Damien4b03e772013-10-05 14:17:09 +01002811 EMIT(load_id, comp->qstr___name__);
2812 EMIT(store_id, comp->qstr___module__);
Damiend99b0522013-12-21 18:17:45 +00002813 EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
Damien4b03e772013-10-05 14:17:09 +01002814 EMIT(store_id, comp->qstr___qualname__);
Damien429d7192013-10-04 19:53:11 +01002815
2816 check_for_doc_string(comp, pns->nodes[2]);
2817 compile_node(comp, pns->nodes[2]); // 2 is class body
2818
2819 id_info_t *id = scope_find(scope, comp->qstr___class__);
2820 assert(id != NULL);
2821 if (id->kind == ID_INFO_KIND_LOCAL) {
Damiend99b0522013-12-21 18:17:45 +00002822 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002823 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002824#if MICROPY_EMIT_CPYTHON
Damien27fb45e2013-10-20 15:07:49 +01002825 EMIT(load_closure, comp->qstr___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002826#else
2827 EMIT(load_fast, comp->qstr___class__, 0); // XXX check this is the correct local num
2828#endif
Damien429d7192013-10-04 19:53:11 +01002829 }
2830 EMIT(return_value);
2831 }
2832
Damien415eb6f2013-10-05 12:19:06 +01002833 EMIT(end_pass);
Damienb05d7072013-10-05 13:37:10 +01002834
Damien826005c2013-10-05 23:17:28 +01002835}
2836
2837void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2838 comp->pass = pass;
2839 comp->scope_cur = scope;
2840 comp->next_label = 1;
2841
2842 if (scope->kind != SCOPE_FUNCTION) {
2843 printf("Error: inline assembler must be a function\n");
2844 return;
2845 }
2846
Damiena2f2f7d2013-10-06 00:14:13 +01002847 if (comp->pass > PASS_1) {
2848 EMIT_INLINE_ASM(start_pass, comp->pass, comp->scope_cur);
2849 }
2850
Damien826005c2013-10-05 23:17:28 +01002851 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002852 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2853 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2854 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002855
Damiend99b0522013-12-21 18:17:45 +00002856 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002857
Damiena2f2f7d2013-10-06 00:14:13 +01002858 // parameters are in pns->nodes[1]
2859 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002860 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002861 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
2862 scope->num_params = EMIT_INLINE_ASM(count_params, n_params, pn_params);
2863 }
2864
Damiend99b0522013-12-21 18:17:45 +00002865 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002866
Damiend99b0522013-12-21 18:17:45 +00002867 mp_parse_node_t pn_body = pns->nodes[3]; // body
2868 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002869 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2870
Damien826005c2013-10-05 23:17:28 +01002871 if (comp->pass == PASS_3) {
2872 //printf("----\n");
2873 scope_print_info(scope);
2874 }
2875
2876 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002877 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2878 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2879 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2880 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2881 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2882 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2883 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2884 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2885 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2886 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2887 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2888 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2889 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002890 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2891
2892 // emit instructions
2893 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00002894 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien826005c2013-10-05 23:17:28 +01002895 printf("SyntaxError: inline assembler 'label' requires 1 argument\n");
2896 return;
2897 }
2898 int lab = comp_next_label(comp);
2899 if (pass > PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00002900 EMIT_INLINE_ASM(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01002901 }
2902 } else {
2903 if (pass > PASS_1) {
2904 EMIT_INLINE_ASM(op, op, n_args, pn_arg);
2905 }
2906 }
2907 }
2908
2909 if (comp->pass > PASS_1) {
2910 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01002911 }
Damien429d7192013-10-04 19:53:11 +01002912}
2913
2914void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
2915 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00002916 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01002917 scope->num_locals = 0;
2918 for (int i = 0; i < scope->id_info_len; i++) {
2919 id_info_t *id = &scope->id_info[i];
2920 if (scope->kind == SCOPE_CLASS && id->qstr == comp->qstr___class__) {
2921 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
2922 continue;
2923 }
2924 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
2925 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
2926 }
Damien9ecbcff2013-12-11 00:41:43 +00002927 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01002928 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
2929 id->local_num = scope->num_locals;
2930 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002931 }
2932 }
2933
2934 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00002935#if MICROPY_EMIT_CPYTHON
2936 int num_cell = 0;
2937#endif
Damien9ecbcff2013-12-11 00:41:43 +00002938 for (int i = 0; i < scope->id_info_len; i++) {
2939 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00002940#if MICROPY_EMIT_CPYTHON
2941 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00002942 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00002943 id->local_num = num_cell;
2944 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002945 }
Damien George6baf76e2013-12-30 22:32:17 +00002946#else
2947 // in Micro Python the cells come right after the fast locals
2948 // parameters are not counted here, since they remain at the start
2949 // of the locals, even if they are cell vars
2950 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
2951 id->local_num = scope->num_locals;
2952 scope->num_locals += 1;
2953 }
2954#endif
Damien9ecbcff2013-12-11 00:41:43 +00002955 }
Damien9ecbcff2013-12-11 00:41:43 +00002956
2957 // compute the index of free vars (freevars[idx] in CPython)
2958 // make sure they are in the order of the parent scope
2959 if (scope->parent != NULL) {
2960 int num_free = 0;
2961 for (int i = 0; i < scope->parent->id_info_len; i++) {
2962 id_info_t *id = &scope->parent->id_info[i];
2963 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
2964 for (int j = 0; j < scope->id_info_len; j++) {
2965 id_info_t *id2 = &scope->id_info[j];
2966 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00002967 assert(!id2->param); // free vars should not be params
2968#if MICROPY_EMIT_CPYTHON
2969 // in CPython the frees are numbered after the cells
2970 id2->local_num = num_cell + num_free;
2971#else
2972 // in Micro Python the frees come first, before the params
2973 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00002974#endif
2975 num_free += 1;
2976 }
2977 }
2978 }
Damien429d7192013-10-04 19:53:11 +01002979 }
Damien George6baf76e2013-12-30 22:32:17 +00002980#if !MICROPY_EMIT_CPYTHON
2981 // in Micro Python shift all other locals after the free locals
2982 if (num_free > 0) {
2983 for (int i = 0; i < scope->id_info_len; i++) {
2984 id_info_t *id = &scope->id_info[i];
2985 if (id->param || id->kind != ID_INFO_KIND_FREE) {
2986 id->local_num += num_free;
2987 }
2988 }
2989 scope->num_params += num_free; // free vars are counted as params for passing them into the function
2990 scope->num_locals += num_free;
2991 }
2992#endif
Damien429d7192013-10-04 19:53:11 +01002993 }
2994
2995 // compute flags
2996 //scope->flags = 0; since we set some things in parameters
2997 if (scope->kind != SCOPE_MODULE) {
2998 scope->flags |= SCOPE_FLAG_NEWLOCALS;
2999 }
3000 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) {
3001 assert(scope->parent != NULL);
3002 scope->flags |= SCOPE_FLAG_OPTIMISED;
3003
3004 // TODO possibly other ways it can be nested
3005 if (scope->parent->kind == SCOPE_FUNCTION || (scope->parent->kind == SCOPE_CLASS && scope->parent->parent->kind == SCOPE_FUNCTION)) {
3006 scope->flags |= SCOPE_FLAG_NESTED;
3007 }
3008 }
3009 int num_free = 0;
3010 for (int i = 0; i < scope->id_info_len; i++) {
3011 id_info_t *id = &scope->id_info[i];
3012 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3013 num_free += 1;
3014 }
3015 }
3016 if (num_free == 0) {
3017 scope->flags |= SCOPE_FLAG_NOFREE;
3018 }
3019}
3020
Damien George1fb03172014-01-03 14:22:03 +00003021mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003022 compiler_t *comp = m_new(compiler_t, 1);
3023
Damien6cdd3af2013-10-05 18:08:26 +01003024 comp->qstr___class__ = qstr_from_str_static("__class__");
3025 comp->qstr___locals__ = qstr_from_str_static("__locals__");
3026 comp->qstr___name__ = qstr_from_str_static("__name__");
3027 comp->qstr___module__ = qstr_from_str_static("__module__");
3028 comp->qstr___qualname__ = qstr_from_str_static("__qualname__");
3029 comp->qstr___doc__ = qstr_from_str_static("__doc__");
3030 comp->qstr_assertion_error = qstr_from_str_static("AssertionError");
3031 comp->qstr_micropython = qstr_from_str_static("micropython");
Damien5ac1b2e2013-10-18 19:58:12 +01003032 comp->qstr_byte_code = qstr_from_str_static("byte_code");
Damien6cdd3af2013-10-05 18:08:26 +01003033 comp->qstr_native = qstr_from_str_static("native");
Damien7af3d192013-10-07 00:02:49 +01003034 comp->qstr_viper = qstr_from_str_static("viper");
Damien5bfb7592013-10-05 18:41:24 +01003035 comp->qstr_asm_thumb = qstr_from_str_static("asm_thumb");
Damiend7933892013-11-28 19:12:18 +00003036 comp->qstr_range = qstr_from_str_static("range");
Damien429d7192013-10-04 19:53:11 +01003037
Damien5ac1b2e2013-10-18 19:58:12 +01003038 comp->is_repl = is_repl;
3039 comp->had_error = false;
3040
Damien429d7192013-10-04 19:53:11 +01003041 comp->break_label = 0;
3042 comp->continue_label = 0;
3043 comp->except_nest_level = 0;
3044 comp->scope_head = NULL;
3045 comp->scope_cur = NULL;
3046
Damien826005c2013-10-05 23:17:28 +01003047 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003048 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003049
3050 // set the outer scope
Damien6cdd3af2013-10-05 18:08:26 +01003051 scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003052
Damien826005c2013-10-05 23:17:28 +01003053 // compile pass 1
3054 comp->emit = emit_pass1_new(comp->qstr___class__);
3055 comp->emit_method_table = &emit_pass1_method_table;
3056 comp->emit_inline_asm = NULL;
3057 comp->emit_inline_asm_method_table = NULL;
3058 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003059 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003060 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003061#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003062 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003063 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003064#endif
Damien826005c2013-10-05 23:17:28 +01003065 } else {
3066 compile_scope(comp, s, PASS_1);
3067 }
3068
3069 // update maximim number of labels needed
3070 if (comp->next_label > max_num_labels) {
3071 max_num_labels = comp->next_label;
3072 }
Damien429d7192013-10-04 19:53:11 +01003073 }
3074
Damien826005c2013-10-05 23:17:28 +01003075 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003076 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003077 compile_scope_compute_things(comp, s);
3078 }
3079
Damien826005c2013-10-05 23:17:28 +01003080 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003081 emit_pass1_free(comp->emit);
3082
Damien826005c2013-10-05 23:17:28 +01003083 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003084#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003085 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003086#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003087 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003088#endif
Damien3ef4abb2013-10-12 16:53:13 +01003089#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003090 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003091#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003092#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003093 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003094 if (false) {
3095 // dummy
3096
Damien3ef4abb2013-10-12 16:53:13 +01003097#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003098 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3099 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003100 if (emit_inline_thumb == NULL) {
3101 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3102 }
3103 comp->emit = NULL;
3104 comp->emit_method_table = NULL;
3105 comp->emit_inline_asm = emit_inline_thumb;
3106 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3107 compile_scope_inline_asm(comp, s, PASS_2);
3108 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003109#endif
3110
Damien826005c2013-10-05 23:17:28 +01003111 } else {
Damienc025ebb2013-10-12 14:30:21 +01003112
3113 // choose the emit type
3114
Damien3ef4abb2013-10-12 16:53:13 +01003115#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003116 comp->emit = emit_cpython_new(max_num_labels);
3117 comp->emit_method_table = &emit_cpython_method_table;
3118#else
Damien826005c2013-10-05 23:17:28 +01003119 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003120
3121#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003122 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003123 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003124#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003125 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003126 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003127 }
Damien13ed3a62013-10-08 09:05:10 +01003128 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003129#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003130 if (emit_native == NULL) {
3131 emit_native = emit_native_thumb_new(max_num_labels);
3132 }
3133 comp->emit_method_table = &emit_native_thumb_method_table;
3134#endif
3135 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003136 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003137 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003138#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003139
Damien826005c2013-10-05 23:17:28 +01003140 default:
3141 if (emit_bc == NULL) {
3142 emit_bc = emit_bc_new(max_num_labels);
3143 }
3144 comp->emit = emit_bc;
3145 comp->emit_method_table = &emit_bc_method_table;
3146 break;
3147 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003148#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003149
3150 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003151 compile_scope(comp, s, PASS_2);
3152 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003153 }
Damien429d7192013-10-04 19:53:11 +01003154 }
3155
Damien George1fb03172014-01-03 14:22:03 +00003156 bool had_error = comp->had_error;
Damien732407f2013-12-29 19:33:23 +00003157 m_del_obj(compiler_t, comp);
Damien5ac1b2e2013-10-18 19:58:12 +01003158
Damien George1fb03172014-01-03 14:22:03 +00003159 if (had_error) {
3160 // TODO return a proper error message
3161 return mp_const_none;
3162 } else {
3163#if MICROPY_EMIT_CPYTHON
3164 // can't create code, so just return true
3165 return mp_const_true;
3166#else
3167 // return function that executes the outer module
3168 return rt_make_function_from_id(1);
3169#endif
3170 }
Damien429d7192013-10-04 19:53:11 +01003171}