blob: 27b2439639e8634630c9c9777d64faa5ef704344 [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <unistd.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <string.h>
6#include <assert.h>
7
8#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "mpconfig.h"
Damien Georgeeb7bfcb2014-01-04 15:57:35 +000010#include "mpqstr.h"
Damien429d7192013-10-04 19:53:11 +010011#include "lexer.h"
Damien429d7192013-10-04 19:53:11 +010012#include "parse.h"
13#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000014#include "runtime0.h"
Damien429d7192013-10-04 19:53:11 +010015#include "emit.h"
Damien George1fb03172014-01-03 14:22:03 +000016#include "obj.h"
17#include "compile.h"
18#include "runtime.h"
Damien429d7192013-10-04 19:53:11 +010019
20// TODO need to mangle __attr names
21
Damience89a212013-10-15 22:25:17 +010022#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)
23
Damien429d7192013-10-04 19:53:11 +010024typedef enum {
25 PN_none = 0,
26#define DEF_RULE(rule, comp, kind, arg...) PN_##rule,
27#include "grammar.h"
28#undef DEF_RULE
29 PN_maximum_number_of,
30} pn_kind_t;
31
Damien415eb6f2013-10-05 12:19:06 +010032#define EMIT(fun, arg...) (comp->emit_method_table->fun(comp->emit, ##arg))
Damien826005c2013-10-05 23:17:28 +010033#define EMIT_INLINE_ASM(fun, arg...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, ##arg))
Damien429d7192013-10-04 19:53:11 +010034
Damien6cdd3af2013-10-05 18:08:26 +010035#define EMIT_OPT_NONE (0)
36#define EMIT_OPT_BYTE_CODE (1)
37#define EMIT_OPT_NATIVE_PYTHON (2)
Damien7af3d192013-10-07 00:02:49 +010038#define EMIT_OPT_VIPER (3)
39#define EMIT_OPT_ASM_THUMB (4)
Damien6cdd3af2013-10-05 18:08:26 +010040
Damien429d7192013-10-04 19:53:11 +010041typedef struct _compiler_t {
Damien Georgecbd2f742014-01-19 11:48:48 +000042 qstr source_file;
Damien5ac1b2e2013-10-18 19:58:12 +010043 bool is_repl;
Damien429d7192013-10-04 19:53:11 +010044 pass_kind_t pass;
Damien5ac1b2e2013-10-18 19:58:12 +010045 bool had_error; // try to keep compiler clean from nlr
Damien429d7192013-10-04 19:53:11 +010046
Damienb05d7072013-10-05 13:37:10 +010047 int next_label;
Damienb05d7072013-10-05 13:37:10 +010048
Damien429d7192013-10-04 19:53:11 +010049 int break_label;
50 int continue_label;
51 int except_nest_level;
52
53 int n_arg_keyword;
54 bool have_star_arg;
55 bool have_dbl_star_arg;
56 bool have_bare_star;
57 int param_pass;
58 int param_pass_num_dict_params;
59 int param_pass_num_default_params;
60
61 scope_t *scope_head;
62 scope_t *scope_cur;
63
Damien6cdd3af2013-10-05 18:08:26 +010064 emit_t *emit; // current emitter
65 const emit_method_table_t *emit_method_table; // current emit method table
Damien826005c2013-10-05 23:17:28 +010066
67 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
68 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 +010069} compiler_t;
70
Damiend99b0522013-12-21 18:17:45 +000071mp_parse_node_t fold_constants(mp_parse_node_t pn) {
72 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
73 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
74 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +010075
76 // fold arguments first
77 for (int i = 0; i < n; i++) {
78 pns->nodes[i] = fold_constants(pns->nodes[i]);
79 }
80
Damiend99b0522013-12-21 18:17:45 +000081 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +010082 case PN_shift_expr:
Damiend99b0522013-12-21 18:17:45 +000083 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
84 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
85 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
86 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
Damien3ef4abb2013-10-12 16:53:13 +010087#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +010088 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +000089 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
Damien0efb3a12013-10-12 16:16:56 +010090#endif
Damiend99b0522013-12-21 18:17:45 +000091 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
92 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien429d7192013-10-04 19:53:11 +010093 } else {
94 // shouldn't happen
95 assert(0);
96 }
97 }
98 break;
99
100 case PN_arith_expr:
Damien0efb3a12013-10-12 16:16:56 +0100101 // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
Damiend99b0522013-12-21 18:17:45 +0000102 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
103 machine_int_t arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
104 machine_int_t arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
Damien0efb3a12013-10-12 16:16:56 +0100105 machine_int_t res;
Damiend99b0522013-12-21 18:17:45 +0000106 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100107 res = arg0 + arg1;
Damiend99b0522013-12-21 18:17:45 +0000108 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100109 res = arg0 - arg1;
Damien429d7192013-10-04 19:53:11 +0100110 } else {
111 // shouldn't happen
112 assert(0);
Damien0efb3a12013-10-12 16:16:56 +0100113 res = 0;
114 }
Damiend99b0522013-12-21 18:17:45 +0000115 if (MP_FIT_SMALL_INT(res)) {
116 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
Damien429d7192013-10-04 19:53:11 +0100117 }
118 }
119 break;
120
121 case PN_term:
Damiend99b0522013-12-21 18:17:45 +0000122 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
123 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
124 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
125 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien3ef4abb2013-10-12 16:53:13 +0100126#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100127 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000128 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
Damien0efb3a12013-10-12 16:16:56 +0100129#endif
Damiend99b0522013-12-21 18:17:45 +0000130 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +0100131 ; // pass
Damiend99b0522013-12-21 18:17:45 +0000132 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
Damien0efb3a12013-10-12 16:16:56 +0100133 // XXX implement this properly as Python's % operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000134 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1);
135 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
Damien0efb3a12013-10-12 16:16:56 +0100136 // XXX implement this properly as Python's // operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000137 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1);
Damien429d7192013-10-04 19:53:11 +0100138 } else {
139 // shouldn't happen
140 assert(0);
141 }
142 }
143 break;
144
145 case PN_factor_2:
Damiend99b0522013-12-21 18:17:45 +0000146 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
147 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
148 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
149 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
150 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
151 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
152 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
153 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien429d7192013-10-04 19:53:11 +0100154 } else {
155 // shouldn't happen
156 assert(0);
157 }
158 }
159 break;
160
Damien3ef4abb2013-10-12 16:53:13 +0100161#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +0100162 case PN_power:
Damien0efb3a12013-10-12 16:16:56 +0100163 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000164 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])) {
165 mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
166 if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
167 int power = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100168 if (power >= 0) {
169 int ans = 1;
Damiend99b0522013-12-21 18:17:45 +0000170 int base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100171 for (; power > 0; power--) {
172 ans *= base;
173 }
Damiend99b0522013-12-21 18:17:45 +0000174 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien429d7192013-10-04 19:53:11 +0100175 }
176 }
177 }
178 break;
Damien0efb3a12013-10-12 16:16:56 +0100179#endif
Damien429d7192013-10-04 19:53:11 +0100180 }
181 }
182
183 return pn;
184}
185
Damiend99b0522013-12-21 18:17:45 +0000186void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100187
Damienb05d7072013-10-05 13:37:10 +0100188static int comp_next_label(compiler_t *comp) {
189 return comp->next_label++;
190}
191
Damiend99b0522013-12-21 18:17:45 +0000192static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
Damien Georgecbd2f742014-01-19 11:48:48 +0000193 scope_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
Damien429d7192013-10-04 19:53:11 +0100194 scope->parent = comp->scope_cur;
195 scope->next = NULL;
196 if (comp->scope_head == NULL) {
197 comp->scope_head = scope;
198 } else {
199 scope_t *s = comp->scope_head;
200 while (s->next != NULL) {
201 s = s->next;
202 }
203 s->next = scope;
204 }
205 return scope;
206}
207
Damiend99b0522013-12-21 18:17:45 +0000208static int list_len(mp_parse_node_t pn, int pn_kind) {
209 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100210 return 0;
Damiend99b0522013-12-21 18:17:45 +0000211 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100212 return 1;
213 } else {
Damiend99b0522013-12-21 18:17:45 +0000214 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
215 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100216 return 1;
217 } else {
Damiend99b0522013-12-21 18:17:45 +0000218 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100219 }
220 }
221}
222
Damiend99b0522013-12-21 18:17:45 +0000223static 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)) {
224 if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
225 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
226 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100227 for (int i = 0; i < num_nodes; i++) {
228 f(comp, pns->nodes[i]);
229 }
Damiend99b0522013-12-21 18:17:45 +0000230 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100231 f(comp, pn);
232 }
233}
234
Damiend99b0522013-12-21 18:17:45 +0000235static int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
236 if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100237 *nodes = NULL;
238 return 0;
Damiend99b0522013-12-21 18:17:45 +0000239 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100240 *nodes = pn;
241 return 1;
242 } else {
Damiend99b0522013-12-21 18:17:45 +0000243 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
244 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100245 *nodes = pn;
246 return 1;
247 } else {
248 *nodes = pns->nodes;
Damiend99b0522013-12-21 18:17:45 +0000249 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100250 }
251 }
252}
253
Damiend99b0522013-12-21 18:17:45 +0000254void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100255}
256
Damiend99b0522013-12-21 18:17:45 +0000257void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
258 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100259 for (int i = 0; i < num_nodes; i++) {
260 compile_node(comp, pns->nodes[i]);
261 }
262}
263
Damien3ef4abb2013-10-12 16:53:13 +0100264#if MICROPY_EMIT_CPYTHON
Damiend99b0522013-12-21 18:17:45 +0000265static bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
266 if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100267 return false;
268 }
Damiend99b0522013-12-21 18:17:45 +0000269 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +0100270 return false;
271 }
272 return true;
273}
274
Damien02f89412013-12-12 15:13:36 +0000275static void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
276 const char *str = qstr_str(qstr);
277 int len = strlen(str);
278 bool has_single_quote = false;
279 bool has_double_quote = false;
280 for (int i = 0; i < len; i++) {
281 if (str[i] == '\'') {
282 has_single_quote = true;
283 } else if (str[i] == '"') {
284 has_double_quote = true;
285 }
286 }
287 if (bytes) {
288 vstr_printf(vstr, "b");
289 }
290 bool quote_single = false;
291 if (has_single_quote && !has_double_quote) {
292 vstr_printf(vstr, "\"");
293 } else {
294 quote_single = true;
295 vstr_printf(vstr, "'");
296 }
297 for (int i = 0; i < len; i++) {
298 if (str[i] == '\n') {
299 vstr_printf(vstr, "\\n");
300 } else if (str[i] == '\\') {
301 vstr_printf(vstr, "\\\\");
302 } else if (str[i] == '\'' && quote_single) {
303 vstr_printf(vstr, "\\'");
304 } else {
305 vstr_printf(vstr, "%c", str[i]);
306 }
307 }
308 if (has_single_quote && !has_double_quote) {
309 vstr_printf(vstr, "\"");
310 } else {
311 vstr_printf(vstr, "'");
312 }
313}
314
Damiend99b0522013-12-21 18:17:45 +0000315static void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
316 assert(MP_PARSE_NODE_IS_LEAF(pn));
317 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
318 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
319 case MP_PARSE_NODE_ID: assert(0);
320 case MP_PARSE_NODE_SMALL_INT: vstr_printf(vstr, "%d", arg); break;
321 case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
322 case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
323 case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
324 case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
325 case MP_PARSE_NODE_TOKEN:
Damien429d7192013-10-04 19:53:11 +0100326 switch (arg) {
Damiend99b0522013-12-21 18:17:45 +0000327 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
328 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
329 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
Damien429d7192013-10-04 19:53:11 +0100330 default: assert(0);
331 }
332 break;
333 default: assert(0);
334 }
335}
336
Damiend99b0522013-12-21 18:17:45 +0000337static 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 +0100338 int n = 0;
339 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000340 n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien429d7192013-10-04 19:53:11 +0100341 }
342 int total = n;
343 bool is_const = true;
Damiend99b0522013-12-21 18:17:45 +0000344 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100345 total += 1;
Damien3a205172013-10-12 15:01:56 +0100346 if (!cpython_c_tuple_is_const(pn)) {
Damien429d7192013-10-04 19:53:11 +0100347 is_const = false;
348 }
349 }
350 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100351 if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien429d7192013-10-04 19:53:11 +0100352 is_const = false;
353 break;
354 }
355 }
356 if (total > 0 && is_const) {
357 bool need_comma = false;
Damien02f89412013-12-12 15:13:36 +0000358 vstr_t *vstr = vstr_new();
359 vstr_printf(vstr, "(");
Damiend99b0522013-12-21 18:17:45 +0000360 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien02f89412013-12-12 15:13:36 +0000361 cpython_c_tuple_emit_const(comp, pn, vstr);
Damien429d7192013-10-04 19:53:11 +0100362 need_comma = true;
363 }
364 for (int i = 0; i < n; i++) {
365 if (need_comma) {
Damien02f89412013-12-12 15:13:36 +0000366 vstr_printf(vstr, ", ");
Damien429d7192013-10-04 19:53:11 +0100367 }
Damien02f89412013-12-12 15:13:36 +0000368 cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien429d7192013-10-04 19:53:11 +0100369 need_comma = true;
370 }
371 if (total == 1) {
Damien02f89412013-12-12 15:13:36 +0000372 vstr_printf(vstr, ",)");
Damien429d7192013-10-04 19:53:11 +0100373 } else {
Damien02f89412013-12-12 15:13:36 +0000374 vstr_printf(vstr, ")");
Damien429d7192013-10-04 19:53:11 +0100375 }
Damien02f89412013-12-12 15:13:36 +0000376 EMIT(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +0000377 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +0100378 } else {
Damiend99b0522013-12-21 18:17:45 +0000379 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100380 compile_node(comp, pn);
381 }
382 for (int i = 0; i < n; i++) {
383 compile_node(comp, pns_list->nodes[i]);
384 }
385 EMIT(build_tuple, total);
386 }
387}
Damien3a205172013-10-12 15:01:56 +0100388#endif
389
390// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
Damiend99b0522013-12-21 18:17:45 +0000391void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3ef4abb2013-10-12 16:53:13 +0100392#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100393 cpython_c_tuple(comp, pn, pns_list);
394#else
395 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000396 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100397 compile_node(comp, pn);
398 total += 1;
399 }
400 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000401 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100402 for (int i = 0; i < n; i++) {
403 compile_node(comp, pns_list->nodes[i]);
404 }
405 total += n;
406 }
407 EMIT(build_tuple, total);
408#endif
409}
Damien429d7192013-10-04 19:53:11 +0100410
Damiend99b0522013-12-21 18:17:45 +0000411void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100412 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000413 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100414}
415
Damiend99b0522013-12-21 18:17:45 +0000416static bool node_is_const_false(mp_parse_node_t pn) {
417 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
418 // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100419}
420
Damiend99b0522013-12-21 18:17:45 +0000421static bool node_is_const_true(mp_parse_node_t pn) {
422 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 +0100423}
424
Damien3ef4abb2013-10-12 16:53:13 +0100425#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100426// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
Damiend99b0522013-12-21 18:17:45 +0000427static 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 +0100428 if (node_is_const_false(pn)) {
429 if (jump_if == false) {
430 EMIT(jump, label);
431 }
432 return;
433 } else if (node_is_const_true(pn)) {
434 if (jump_if == true) {
435 EMIT(jump, label);
436 }
437 return;
Damiend99b0522013-12-21 18:17:45 +0000438 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
439 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
440 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
441 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien429d7192013-10-04 19:53:11 +0100442 if (jump_if == false) {
Damienb05d7072013-10-05 13:37:10 +0100443 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100444 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100445 cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien429d7192013-10-04 19:53:11 +0100446 }
Damien3a205172013-10-12 15:01:56 +0100447 cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100448 EMIT(label_assign, label2);
449 } else {
450 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100451 cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100452 }
453 }
454 return;
Damiend99b0522013-12-21 18:17:45 +0000455 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien429d7192013-10-04 19:53:11 +0100456 if (jump_if == false) {
457 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100458 cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100459 }
460 } else {
Damienb05d7072013-10-05 13:37:10 +0100461 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100462 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100463 cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien429d7192013-10-04 19:53:11 +0100464 }
Damien3a205172013-10-12 15:01:56 +0100465 cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100466 EMIT(label_assign, label2);
467 }
468 return;
Damiend99b0522013-12-21 18:17:45 +0000469 } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100470 cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien429d7192013-10-04 19:53:11 +0100471 return;
472 }
473 }
474
475 // nothing special, fall back to default compiling for node and jump
476 compile_node(comp, pn);
477 if (jump_if == false) {
478 EMIT(pop_jump_if_false, label);
479 } else {
480 EMIT(pop_jump_if_true, label);
481 }
482}
Damien3a205172013-10-12 15:01:56 +0100483#endif
Damien429d7192013-10-04 19:53:11 +0100484
Damiend99b0522013-12-21 18:17:45 +0000485static void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien3ef4abb2013-10-12 16:53:13 +0100486#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100487 cpython_c_if_cond(comp, pn, jump_if, label, false);
488#else
489 if (node_is_const_false(pn)) {
490 if (jump_if == false) {
491 EMIT(jump, label);
492 }
493 return;
494 } else if (node_is_const_true(pn)) {
495 if (jump_if == true) {
496 EMIT(jump, label);
497 }
498 return;
Damiend99b0522013-12-21 18:17:45 +0000499 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
500 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
501 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
502 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100503 if (jump_if == false) {
504 int label2 = comp_next_label(comp);
505 for (int i = 0; i < n - 1; i++) {
506 c_if_cond(comp, pns->nodes[i], true, label2);
507 }
508 c_if_cond(comp, pns->nodes[n - 1], false, label);
509 EMIT(label_assign, label2);
510 } else {
511 for (int i = 0; i < n; i++) {
512 c_if_cond(comp, pns->nodes[i], true, label);
513 }
514 }
515 return;
Damiend99b0522013-12-21 18:17:45 +0000516 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100517 if (jump_if == false) {
518 for (int i = 0; i < n; i++) {
519 c_if_cond(comp, pns->nodes[i], false, label);
520 }
521 } else {
522 int label2 = comp_next_label(comp);
523 for (int i = 0; i < n - 1; i++) {
524 c_if_cond(comp, pns->nodes[i], false, label2);
525 }
526 c_if_cond(comp, pns->nodes[n - 1], true, label);
527 EMIT(label_assign, label2);
528 }
529 return;
Damiend99b0522013-12-21 18:17:45 +0000530 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100531 c_if_cond(comp, pns->nodes[0], !jump_if, label);
532 return;
533 }
534 }
535
536 // nothing special, fall back to default compiling for node and jump
537 compile_node(comp, pn);
538 if (jump_if == false) {
539 EMIT(pop_jump_if_false, label);
540 } else {
541 EMIT(pop_jump_if_true, label);
542 }
543#endif
Damien429d7192013-10-04 19:53:11 +0100544}
545
546typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damiend99b0522013-12-21 18:17:45 +0000547void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100548
Damiend99b0522013-12-21 18:17:45 +0000549void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100550 if (assign_kind != ASSIGN_AUG_STORE) {
551 compile_node(comp, pns->nodes[0]);
552 }
553
Damiend99b0522013-12-21 18:17:45 +0000554 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
555 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
556 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
557 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100558 if (assign_kind != ASSIGN_AUG_STORE) {
559 for (int i = 0; i < n - 1; i++) {
560 compile_node(comp, pns1->nodes[i]);
561 }
562 }
Damiend99b0522013-12-21 18:17:45 +0000563 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
564 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100565 }
Damiend99b0522013-12-21 18:17:45 +0000566 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +0100567 printf("SyntaxError: can't assign to function call\n");
568 return;
Damiend99b0522013-12-21 18:17:45 +0000569 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100570 if (assign_kind == ASSIGN_AUG_STORE) {
571 EMIT(rot_three);
572 EMIT(store_subscr);
573 } else {
574 compile_node(comp, pns1->nodes[0]);
575 if (assign_kind == ASSIGN_AUG_LOAD) {
576 EMIT(dup_top_two);
577 EMIT(binary_op, RT_BINARY_OP_SUBSCR);
578 } else {
579 EMIT(store_subscr);
580 }
581 }
Damiend99b0522013-12-21 18:17:45 +0000582 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
583 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100584 if (assign_kind == ASSIGN_AUG_LOAD) {
585 EMIT(dup_top);
Damiend99b0522013-12-21 18:17:45 +0000586 EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100587 } else {
588 if (assign_kind == ASSIGN_AUG_STORE) {
589 EMIT(rot_two);
590 }
Damiend99b0522013-12-21 18:17:45 +0000591 EMIT(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100592 }
593 } else {
594 // shouldn't happen
595 assert(0);
596 }
597 } else {
598 // shouldn't happen
599 assert(0);
600 }
601
Damiend99b0522013-12-21 18:17:45 +0000602 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100603 // SyntaxError, cannot assign
604 assert(0);
605 }
606}
607
Damiend99b0522013-12-21 18:17:45 +0000608void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
Damien429d7192013-10-04 19:53:11 +0100609 assert(n >= 0);
610 int have_star_index = -1;
611 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000612 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) {
Damien429d7192013-10-04 19:53:11 +0100613 if (have_star_index < 0) {
614 EMIT(unpack_ex, i, n - i - 1);
615 have_star_index = i;
616 } else {
617 printf("SyntaxError: two starred expressions in assignment\n");
618 return;
619 }
620 }
621 }
622 if (have_star_index < 0) {
623 EMIT(unpack_sequence, n);
624 }
625 for (int i = 0; i < n; i++) {
626 if (i == have_star_index) {
Damiend99b0522013-12-21 18:17:45 +0000627 c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100628 } else {
629 c_assign(comp, nodes[i], ASSIGN_STORE);
630 }
631 }
632}
633
634// assigns top of stack to pn
Damiend99b0522013-12-21 18:17:45 +0000635void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100636 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +0000637 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100638 assert(0);
Damiend99b0522013-12-21 18:17:45 +0000639 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
640 if (MP_PARSE_NODE_IS_ID(pn)) {
641 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100642 switch (assign_kind) {
643 case ASSIGN_STORE:
644 case ASSIGN_AUG_STORE:
Damien4b03e772013-10-05 14:17:09 +0100645 EMIT(store_id, arg);
Damien429d7192013-10-04 19:53:11 +0100646 break;
647 case ASSIGN_AUG_LOAD:
Damien4b03e772013-10-05 14:17:09 +0100648 EMIT(load_id, arg);
Damien429d7192013-10-04 19:53:11 +0100649 break;
650 }
651 } else {
652 printf("SyntaxError: can't assign to literal\n");
653 return;
654 }
655 } else {
Damiend99b0522013-12-21 18:17:45 +0000656 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
657 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +0100658 case PN_power:
659 // lhs is an index or attribute
660 c_assign_power(comp, pns, assign_kind);
661 break;
662
663 case PN_testlist_star_expr:
664 case PN_exprlist:
665 // lhs is a tuple
666 if (assign_kind != ASSIGN_STORE) {
667 goto bad_aug;
668 }
Damiend99b0522013-12-21 18:17:45 +0000669 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100670 break;
671
672 case PN_atom_paren:
673 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000674 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100675 // empty tuple
676 printf("SyntaxError: can't assign to ()\n");
677 return;
Damiend99b0522013-12-21 18:17:45 +0000678 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
679 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100680 goto testlist_comp;
681 } else {
682 // parenthesis around 1 item, is just that item
683 pn = pns->nodes[0];
684 goto tail_recursion;
685 }
686 break;
687
688 case PN_atom_bracket:
689 // lhs is something in brackets
690 if (assign_kind != ASSIGN_STORE) {
691 goto bad_aug;
692 }
Damiend99b0522013-12-21 18:17:45 +0000693 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100694 // empty list, assignment allowed
695 c_assign_tuple(comp, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000696 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
697 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100698 goto testlist_comp;
699 } else {
700 // brackets around 1 item
701 c_assign_tuple(comp, 1, &pns->nodes[0]);
702 }
703 break;
704
705 default:
Damiend99b0522013-12-21 18:17:45 +0000706 printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien429d7192013-10-04 19:53:11 +0100707 assert(0);
708 }
709 return;
710
711 testlist_comp:
712 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000713 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
714 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
715 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100716 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000717 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100718 c_assign_tuple(comp, 1, &pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000719 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100720 // sequence of many items
721 // TODO call c_assign_tuple instead
Damiend99b0522013-12-21 18:17:45 +0000722 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
Damien429d7192013-10-04 19:53:11 +0100723 EMIT(unpack_sequence, 1 + n);
724 c_assign(comp, pns->nodes[0], ASSIGN_STORE);
725 for (int i = 0; i < n; i++) {
726 c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
727 }
Damiend99b0522013-12-21 18:17:45 +0000728 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +0100729 // TODO not implemented
730 assert(0);
731 } else {
732 // sequence with 2 items
733 goto sequence_with_2_items;
734 }
735 } else {
736 // sequence with 2 items
737 sequence_with_2_items:
738 c_assign_tuple(comp, 2, pns->nodes);
739 }
740 return;
741 }
742 return;
743
744 bad_aug:
745 printf("SyntaxError: illegal expression for augmented assignment\n");
746}
747
748// stuff for lambda and comprehensions and generators
749void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
750 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000751 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100752 int nfree = 0;
753 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000754 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
755 id_info_t *id = &comp->scope_cur->id_info[i];
756 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
757 for (int j = 0; j < this_scope->id_info_len; j++) {
758 id_info_t *id2 = &this_scope->id_info[j];
759 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +0000760#if MICROPY_EMIT_CPYTHON
Damien318aec62013-12-10 18:28:17 +0000761 EMIT(load_closure, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000762#else
763 // in Micro Python we load closures using LOAD_FAST
764 EMIT(load_fast, id->qstr, id->local_num);
765#endif
Damien318aec62013-12-10 18:28:17 +0000766 nfree += 1;
767 }
768 }
Damien429d7192013-10-04 19:53:11 +0100769 }
770 }
771 }
772 if (nfree > 0) {
773 EMIT(build_tuple, nfree);
774 }
775
776 // make the function/closure
777 if (nfree == 0) {
778 EMIT(make_function, this_scope, n_dict_params, n_default_params);
779 } else {
780 EMIT(make_closure, this_scope, n_dict_params, n_default_params);
781 }
782}
783
Damiend99b0522013-12-21 18:17:45 +0000784void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
785 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
786 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
787 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100788 // this parameter has a default value
789 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
790 if (comp->have_bare_star) {
791 comp->param_pass_num_dict_params += 1;
792 if (comp->param_pass == 1) {
Damiend99b0522013-12-21 18:17:45 +0000793 EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100794 compile_node(comp, pns->nodes[2]);
795 }
796 } else {
797 comp->param_pass_num_default_params += 1;
798 if (comp->param_pass == 2) {
799 compile_node(comp, pns->nodes[2]);
800 }
801 }
802 }
Damiend99b0522013-12-21 18:17:45 +0000803 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
804 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
805 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100806 // bare star
807 comp->have_bare_star = true;
808 }
809 }
810}
811
812// leaves function object on stack
813// returns function name
Damiend99b0522013-12-21 18:17:45 +0000814qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100815 if (comp->pass == PASS_1) {
816 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000817 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100818 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000819 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100820 }
821
822 // save variables (probably don't need to do this, since we can't have nested definitions..?)
823 bool old_have_bare_star = comp->have_bare_star;
824 int old_param_pass = comp->param_pass;
825 int old_param_pass_num_dict_params = comp->param_pass_num_dict_params;
826 int old_param_pass_num_default_params = comp->param_pass_num_default_params;
827
828 // compile default parameters
829 comp->have_bare_star = false;
830 comp->param_pass = 1; // pass 1 does any default parameters after bare star
831 comp->param_pass_num_dict_params = 0;
832 comp->param_pass_num_default_params = 0;
833 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
834 comp->have_bare_star = false;
835 comp->param_pass = 2; // pass 2 does any default parameters before bare star
836 comp->param_pass_num_dict_params = 0;
837 comp->param_pass_num_default_params = 0;
838 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
839
840 // get the scope for this function
841 scope_t *fscope = (scope_t*)pns->nodes[4];
842
843 // make the function
844 close_over_variables_etc(comp, fscope, comp->param_pass_num_dict_params, comp->param_pass_num_default_params);
845
846 // restore variables
847 comp->have_bare_star = old_have_bare_star;
848 comp->param_pass = old_param_pass;
849 comp->param_pass_num_dict_params = old_param_pass_num_dict_params;
850 comp->param_pass_num_default_params = old_param_pass_num_default_params;
851
852 // return its name (the 'f' in "def f(...):")
853 return fscope->simple_name;
854}
855
856// leaves class object on stack
857// returns class name
Damiend99b0522013-12-21 18:17:45 +0000858qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100859 if (comp->pass == PASS_1) {
860 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000861 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100862 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000863 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100864 }
865
866 EMIT(load_build_class);
867
868 // scope for this class
869 scope_t *cscope = (scope_t*)pns->nodes[3];
870
871 // compile the class
872 close_over_variables_etc(comp, cscope, 0, 0);
873
874 // get its name
875 EMIT(load_const_id, cscope->simple_name);
876
877 // nodes[1] has parent classes, if any
Damiend99b0522013-12-21 18:17:45 +0000878 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +0100879 // no parent classes
880 EMIT(call_function, 2, 0, false, false);
881 } else {
882 // have a parent class or classes
883 // TODO what if we have, eg, *a or **a in the parent list?
884 compile_node(comp, pns->nodes[1]);
885 EMIT(call_function, 2 + list_len(pns->nodes[1], PN_arglist), 0, false, false);
886 }
887
888 // return its name (the 'C' in class C(...):")
889 return cscope->simple_name;
890}
891
Damien6cdd3af2013-10-05 18:08:26 +0100892// returns true if it was a built-in decorator (even if the built-in had an error)
Damiend99b0522013-12-21 18:17:45 +0000893static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000894 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100895 return false;
896 }
897
898 if (name_len != 2) {
899 printf("SyntaxError: invalid micropython decorator\n");
900 return true;
901 }
902
Damiend99b0522013-12-21 18:17:45 +0000903 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000904 if (attr == MP_QSTR_byte_code) {
Damien5ac1b2e2013-10-18 19:58:12 +0100905 *emit_options = EMIT_OPT_BYTE_CODE;
Damience89a212013-10-15 22:25:17 +0100906#if MICROPY_EMIT_NATIVE
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000907 } else if (attr == MP_QSTR_native) {
Damien6cdd3af2013-10-05 18:08:26 +0100908 *emit_options = EMIT_OPT_NATIVE_PYTHON;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000909 } else if (attr == MP_QSTR_viper) {
Damien7af3d192013-10-07 00:02:49 +0100910 *emit_options = EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100911#endif
Damien3ef4abb2013-10-12 16:53:13 +0100912#if MICROPY_EMIT_INLINE_THUMB
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000913 } else if (attr == MP_QSTR_asm_thumb) {
Damien5bfb7592013-10-05 18:41:24 +0100914 *emit_options = EMIT_OPT_ASM_THUMB;
Damienc025ebb2013-10-12 14:30:21 +0100915#endif
Damien6cdd3af2013-10-05 18:08:26 +0100916 } else {
Damience89a212013-10-15 22:25:17 +0100917 printf("SyntaxError: invalid micropython decorator '%s'\n", qstr_str(attr));
Damien6cdd3af2013-10-05 18:08:26 +0100918 }
919
920 return true;
921}
922
Damiend99b0522013-12-21 18:17:45 +0000923void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100924 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000925 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +0100926 int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
927
Damien6cdd3af2013-10-05 18:08:26 +0100928 // inherit emit options for this function/class definition
929 uint emit_options = comp->scope_cur->emit_options;
930
931 // compile each decorator
932 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100933 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000934 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
935 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100936
937 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +0000938 mp_parse_node_t *name_nodes;
Damien6cdd3af2013-10-05 18:08:26 +0100939 int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
940
941 // check for built-in decorators
942 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
943 // this was a built-in
944 num_built_in_decorators += 1;
945
946 } else {
947 // not a built-in, compile normally
948
949 // compile the decorator function
950 compile_node(comp, name_nodes[0]);
951 for (int i = 1; i < name_len; i++) {
Damiend99b0522013-12-21 18:17:45 +0000952 assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be
953 EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i]));
Damien6cdd3af2013-10-05 18:08:26 +0100954 }
955
956 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +0000957 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +0100958 // call the decorator function with the arguments in nodes[1]
959 compile_node(comp, pns_decorator->nodes[1]);
960 }
Damien429d7192013-10-04 19:53:11 +0100961 }
962 }
963
964 // compile the body (funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +0000965 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +0100966 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +0000967 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100968 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Damiend99b0522013-12-21 18:17:45 +0000969 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100970 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +0100971 } else {
972 // shouldn't happen
973 assert(0);
974 }
975
976 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +0100977 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien429d7192013-10-04 19:53:11 +0100978 EMIT(call_function, 1, 0, false, false);
979 }
980
981 // store func/class object into name
Damien4b03e772013-10-05 14:17:09 +0100982 EMIT(store_id, body_name);
Damien429d7192013-10-04 19:53:11 +0100983}
984
Damiend99b0522013-12-21 18:17:45 +0000985void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +0100986 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +0100987 // store function object into function name
Damien4b03e772013-10-05 14:17:09 +0100988 EMIT(store_id, fname);
Damien429d7192013-10-04 19:53:11 +0100989}
990
Damiend99b0522013-12-21 18:17:45 +0000991void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
992 if (MP_PARSE_NODE_IS_ID(pn)) {
993 EMIT(delete_id, MP_PARSE_NODE_LEAF_ARG(pn));
994 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
995 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +0100996
997 compile_node(comp, pns->nodes[0]); // base of the power node
998
Damiend99b0522013-12-21 18:17:45 +0000999 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1000 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1001 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
1002 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001003 for (int i = 0; i < n - 1; i++) {
1004 compile_node(comp, pns1->nodes[i]);
1005 }
Damiend99b0522013-12-21 18:17:45 +00001006 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
1007 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +01001008 }
Damiend99b0522013-12-21 18:17:45 +00001009 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +01001010 // SyntaxError: can't delete a function call
1011 assert(0);
Damiend99b0522013-12-21 18:17:45 +00001012 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +01001013 compile_node(comp, pns1->nodes[0]);
1014 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +00001015 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
1016 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
1017 EMIT(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001018 } else {
1019 // shouldn't happen
1020 assert(0);
1021 }
1022 } else {
1023 // shouldn't happen
1024 assert(0);
1025 }
1026
Damiend99b0522013-12-21 18:17:45 +00001027 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001028 // SyntaxError, cannot delete
1029 assert(0);
1030 }
Damiend99b0522013-12-21 18:17:45 +00001031 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
1032 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
1033 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) {
1034 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001035 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
1036
Damiend99b0522013-12-21 18:17:45 +00001037 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1038 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1039 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01001040 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00001041 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001042 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00001043 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01001044 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +00001045 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001046 c_del_stmt(comp, pns->nodes[0]);
1047 for (int i = 0; i < n; i++) {
1048 c_del_stmt(comp, pns1->nodes[i]);
1049 }
Damiend99b0522013-12-21 18:17:45 +00001050 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01001051 // TODO not implemented; can't del comprehension?
1052 assert(0);
1053 } else {
1054 // sequence with 2 items
1055 goto sequence_with_2_items;
1056 }
1057 } else {
1058 // sequence with 2 items
1059 sequence_with_2_items:
1060 c_del_stmt(comp, pns->nodes[0]);
1061 c_del_stmt(comp, pns->nodes[1]);
1062 }
1063 } else {
1064 // tuple with 1 element
1065 c_del_stmt(comp, pn);
1066 }
1067 } else {
1068 // not implemented
1069 assert(0);
1070 }
1071}
1072
Damiend99b0522013-12-21 18:17:45 +00001073void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001074 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
1075}
1076
Damiend99b0522013-12-21 18:17:45 +00001077void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001078 if (comp->break_label == 0) {
1079 printf("ERROR: cannot break from here\n");
1080 }
1081 EMIT(break_loop, comp->break_label);
1082}
1083
Damiend99b0522013-12-21 18:17:45 +00001084void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001085 if (comp->continue_label == 0) {
1086 printf("ERROR: cannot continue from here\n");
1087 }
1088 if (comp->except_nest_level > 0) {
1089 EMIT(continue_loop, comp->continue_label);
1090 } else {
1091 EMIT(jump, comp->continue_label);
1092 }
1093}
1094
Damiend99b0522013-12-21 18:17:45 +00001095void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +01001096 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
1097 printf("SyntaxError: 'return' outside function\n");
1098 comp->had_error = true;
1099 return;
1100 }
Damiend99b0522013-12-21 18:17:45 +00001101 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001102 // no argument to 'return', so return None
Damiend99b0522013-12-21 18:17:45 +00001103 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
1104 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +01001105 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +00001106 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
1107 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 +01001108
Damienb05d7072013-10-05 13:37:10 +01001109 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001110 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1111 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
1112 EMIT(return_value);
1113 EMIT(label_assign, l_fail);
1114 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1115 } else {
1116 compile_node(comp, pns->nodes[0]);
1117 }
1118 EMIT(return_value);
1119}
1120
Damiend99b0522013-12-21 18:17:45 +00001121void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001122 compile_node(comp, pns->nodes[0]);
1123 EMIT(pop_top);
1124}
1125
Damiend99b0522013-12-21 18:17:45 +00001126void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1127 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001128 // raise
1129 EMIT(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001130 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001131 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001132 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001133 compile_node(comp, pns->nodes[0]);
1134 compile_node(comp, pns->nodes[1]);
1135 EMIT(raise_varargs, 2);
1136 } else {
1137 // raise x
1138 compile_node(comp, pns->nodes[0]);
1139 EMIT(raise_varargs, 1);
1140 }
1141}
1142
1143// q1 holds the base, q2 the full name
1144// eg a -> q1=q2=a
1145// a.b.c -> q1=a, q2=a.b.c
Damiend99b0522013-12-21 18:17:45 +00001146void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
Damien429d7192013-10-04 19:53:11 +01001147 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001148 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1149 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001150 // a name of the form x as y; unwrap it
Damiend99b0522013-12-21 18:17:45 +00001151 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001152 pn = pns->nodes[0];
1153 is_as = true;
1154 }
Damiend99b0522013-12-21 18:17:45 +00001155 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001156 // just a simple name
Damiend99b0522013-12-21 18:17:45 +00001157 *q2 = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001158 if (!is_as) {
1159 *q1 = *q2;
1160 }
1161 EMIT(import_name, *q2);
Damiend99b0522013-12-21 18:17:45 +00001162 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
1163 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
1164 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) {
Damien429d7192013-10-04 19:53:11 +01001165 // a name of the form a.b.c
1166 if (!is_as) {
Damiend99b0522013-12-21 18:17:45 +00001167 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001168 }
Damiend99b0522013-12-21 18:17:45 +00001169 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001170 int len = n - 1;
1171 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001172 len += strlen(qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])));
Damien429d7192013-10-04 19:53:11 +01001173 }
1174 char *str = m_new(char, len + 1);
Damien Georgefe8fb912014-01-02 16:36:09 +00001175 char *str_dest = str;
Damien429d7192013-10-04 19:53:11 +01001176 str[0] = 0;
1177 for (int i = 0; i < n; i++) {
1178 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001179 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001180 }
Damien Georgefe8fb912014-01-02 16:36:09 +00001181 const char *str_src = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
1182 size_t str_src_len = strlen(str_src);
1183 memcpy(str_dest, str_src, str_src_len);
1184 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001185 }
Damien Georgefe8fb912014-01-02 16:36:09 +00001186 *str_dest = '\0';
Damien732407f2013-12-29 19:33:23 +00001187 *q2 = qstr_from_str_take(str, len + 1);
Damien429d7192013-10-04 19:53:11 +01001188 EMIT(import_name, *q2);
1189 if (is_as) {
1190 for (int i = 1; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001191 EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001192 }
1193 }
1194 } else {
1195 // TODO not implemented
1196 assert(0);
1197 }
1198 } else {
1199 // TODO not implemented
1200 assert(0);
1201 }
1202}
1203
Damiend99b0522013-12-21 18:17:45 +00001204void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01001205 EMIT(load_const_small_int, 0); // ??
Damiend99b0522013-12-21 18:17:45 +00001206 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001207 qstr q1, q2;
1208 do_import_name(comp, pn, &q1, &q2);
Damien4b03e772013-10-05 14:17:09 +01001209 EMIT(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001210}
1211
Damiend99b0522013-12-21 18:17:45 +00001212void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001213 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1214}
1215
Damiend99b0522013-12-21 18:17:45 +00001216void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1217 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damiendb4c3612013-12-10 17:27:24 +00001218 EMIT(load_const_small_int, 0); // level 0 for __import__
1219
1220 // build the "fromlist" tuple
1221#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001222 EMIT(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001223#else
1224 EMIT(load_const_str, qstr_from_str_static("*"), false);
1225 EMIT(build_tuple, 1);
1226#endif
1227
1228 // do the import
Damien429d7192013-10-04 19:53:11 +01001229 qstr dummy_q, id1;
1230 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1231 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001232
Damien429d7192013-10-04 19:53:11 +01001233 } else {
Damiendb4c3612013-12-10 17:27:24 +00001234 EMIT(load_const_small_int, 0); // level 0 for __import__
1235
1236 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001237 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001238 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001239#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001240 {
1241 vstr_t *vstr = vstr_new();
1242 vstr_printf(vstr, "(");
1243 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001244 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1245 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1246 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001247 if (i > 0) {
1248 vstr_printf(vstr, ", ");
1249 }
1250 vstr_printf(vstr, "'");
1251 vstr_printf(vstr, qstr_str(id2));
1252 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001253 }
Damien02f89412013-12-12 15:13:36 +00001254 if (n == 1) {
1255 vstr_printf(vstr, ",");
1256 }
1257 vstr_printf(vstr, ")");
Damien02f89412013-12-12 15:13:36 +00001258 EMIT(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001259 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001260 }
Damiendb4c3612013-12-10 17:27:24 +00001261#else
1262 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001263 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1264 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1265 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damiendb4c3612013-12-10 17:27:24 +00001266 EMIT(load_const_str, id2, false);
1267 }
1268 EMIT(build_tuple, n);
1269#endif
1270
1271 // do the import
Damien429d7192013-10-04 19:53:11 +01001272 qstr dummy_q, id1;
1273 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
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
Damien429d7192013-10-04 19:53:11 +01001278 EMIT(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001279 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien4b03e772013-10-05 14:17:09 +01001280 EMIT(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001281 } else {
Damiend99b0522013-12-21 18:17:45 +00001282 EMIT(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001283 }
1284 }
1285 EMIT(pop_top);
1286 }
1287}
1288
Damiend99b0522013-12-21 18:17:45 +00001289void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001290 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001291 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1292 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001293 } else {
Damiend99b0522013-12-21 18:17:45 +00001294 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1295 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001296 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001297 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001298 }
Damien429d7192013-10-04 19:53:11 +01001299 }
1300 }
1301}
1302
Damiend99b0522013-12-21 18:17:45 +00001303void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001304 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001305 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1306 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001307 } else {
Damiend99b0522013-12-21 18:17:45 +00001308 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1309 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001310 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001311 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001312 }
Damien429d7192013-10-04 19:53:11 +01001313 }
1314 }
1315}
1316
Damiend99b0522013-12-21 18:17:45 +00001317void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001318 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001319 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien Georgee5863d92014-01-12 12:35:08 +00001320 EMIT(load_global, MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
Damiend99b0522013-12-21 18:17:45 +00001321 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001322 // assertion message
1323 compile_node(comp, pns->nodes[1]);
1324 EMIT(call_function, 1, 0, false, false);
1325 }
1326 EMIT(raise_varargs, 1);
1327 EMIT(label_assign, l_end);
1328}
1329
Damiend99b0522013-12-21 18:17:45 +00001330void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001331 // TODO proper and/or short circuiting
1332
Damienb05d7072013-10-05 13:37:10 +01001333 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001334
Damienb05d7072013-10-05 13:37:10 +01001335 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001336 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1337
1338 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001339 //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 +01001340 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001341 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien429d7192013-10-04 19:53:11 +01001342 EMIT(jump, l_end);
1343 }
1344 //}
1345 EMIT(label_assign, l_fail);
1346
Damiend99b0522013-12-21 18:17:45 +00001347 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001348 // compile elif blocks
1349
Damiend99b0522013-12-21 18:17:45 +00001350 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001351
Damiend99b0522013-12-21 18:17:45 +00001352 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001353 // multiple elif blocks
1354
Damiend99b0522013-12-21 18:17:45 +00001355 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001356 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001357 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
Damienb05d7072013-10-05 13:37:10 +01001358 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001359 c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition
1360
1361 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001362 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien429d7192013-10-04 19:53:11 +01001363 EMIT(jump, l_end);
1364 }
1365 EMIT(label_assign, l_fail);
1366 }
1367
1368 } else {
1369 // a single elif block
1370
Damienb05d7072013-10-05 13:37:10 +01001371 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001372 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1373
1374 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001375 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien429d7192013-10-04 19:53:11 +01001376 EMIT(jump, l_end);
1377 }
1378 EMIT(label_assign, l_fail);
1379 }
1380 }
1381
1382 // compile else block
1383 compile_node(comp, pns->nodes[3]); // can be null
1384
1385 EMIT(label_assign, l_end);
1386}
1387
Damiend99b0522013-12-21 18:17:45 +00001388void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001389 int old_break_label = comp->break_label;
1390 int old_continue_label = comp->continue_label;
1391
Damienb05d7072013-10-05 13:37:10 +01001392 int break_label = comp_next_label(comp);
1393 int continue_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001394
1395 comp->break_label = break_label;
1396 comp->continue_label = continue_label;
1397
Damience89a212013-10-15 22:25:17 +01001398 // compared to CPython, we have an optimised version of while loops
1399#if MICROPY_EMIT_CPYTHON
1400 int done_label = comp_next_label(comp);
1401 EMIT(setup_loop, break_label);
Damien429d7192013-10-04 19:53:11 +01001402 EMIT(label_assign, continue_label);
1403 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1404 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001405 if (!EMIT(last_emit_was_return_value)) {
Damien429d7192013-10-04 19:53:11 +01001406 EMIT(jump, continue_label);
1407 }
1408 EMIT(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001409 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1410 // this is a small hack to agree with CPython
1411 if (!node_is_const_true(pns->nodes[0])) {
1412 EMIT(pop_block);
1413 }
Damience89a212013-10-15 22:25:17 +01001414#else
1415 int top_label = comp_next_label(comp);
1416 EMIT(jump, continue_label);
1417 EMIT(label_assign, top_label);
1418 compile_node(comp, pns->nodes[1]); // body
1419 EMIT(label_assign, continue_label);
1420 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1421#endif
1422
1423 // break/continue apply to outer loop (if any) in the else block
1424 comp->break_label = old_break_label;
1425 comp->continue_label = old_continue_label;
Damien429d7192013-10-04 19:53:11 +01001426
1427 compile_node(comp, pns->nodes[2]); // else
1428
1429 EMIT(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001430}
1431
Damienf72fd0e2013-11-06 20:20:49 +00001432// TODO preload end and step onto stack if they are not constants
1433// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001434void 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 +00001435 int old_break_label = comp->break_label;
1436 int old_continue_label = comp->continue_label;
1437
1438 int break_label = comp_next_label(comp);
1439 int continue_label = comp_next_label(comp);
1440
1441 comp->break_label = break_label;
1442 comp->continue_label = continue_label;
1443
1444 int top_label = comp_next_label(comp);
1445
1446 // compile: var = start
1447 compile_node(comp, pn_start);
1448 c_assign(comp, pn_var, ASSIGN_STORE);
1449
1450 EMIT(jump, continue_label);
1451 EMIT(label_assign, top_label);
1452
Damienf3822fc2013-11-09 20:12:03 +00001453 // compile body
1454 compile_node(comp, pn_body);
1455
Damienf72fd0e2013-11-06 20:20:49 +00001456 // compile: var += step
1457 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1458 compile_node(comp, pn_step);
1459 EMIT(binary_op, RT_BINARY_OP_INPLACE_ADD);
1460 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1461
Damienf72fd0e2013-11-06 20:20:49 +00001462 EMIT(label_assign, continue_label);
1463
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001464 // compile: if var <cond> end: goto top
Damienf72fd0e2013-11-06 20:20:49 +00001465 compile_node(comp, pn_var);
1466 compile_node(comp, pn_end);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001467 if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001468 EMIT(binary_op, RT_COMPARE_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001469 } else {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001470 EMIT(binary_op, RT_COMPARE_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001471 }
Damienf72fd0e2013-11-06 20:20:49 +00001472 EMIT(pop_jump_if_true, top_label);
1473
1474 // break/continue apply to outer loop (if any) in the else block
1475 comp->break_label = old_break_label;
1476 comp->continue_label = old_continue_label;
1477
1478 compile_node(comp, pn_else);
1479
1480 EMIT(label_assign, break_label);
1481}
1482
Damiend99b0522013-12-21 18:17:45 +00001483void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001484#if !MICROPY_EMIT_CPYTHON
1485 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1486 // this is actually slower, but uses no heap memory
1487 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001488 if (/*comp->scope_cur->emit_options == EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_power)) {
1489 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001490 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1491 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1492 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
1493 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
Damiend99b0522013-12-21 18:17:45 +00001494 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1495 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001496 int n_args = list_get(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001497 mp_parse_node_t pn_range_start;
1498 mp_parse_node_t pn_range_end;
1499 mp_parse_node_t pn_range_step;
1500 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001501 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001502 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001503 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001504 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001505 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001506 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001507 } else if (n_args == 2) {
1508 pn_range_start = args[0];
1509 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001510 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001511 } else {
1512 pn_range_start = args[0];
1513 pn_range_end = args[1];
1514 pn_range_step = args[2];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001515 // We need to know sign of step. This is possible only if it's constant
1516 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
1517 optimize = false;
1518 }
Damienf72fd0e2013-11-06 20:20:49 +00001519 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001520 }
1521 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001522 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1523 return;
1524 }
1525 }
1526 }
1527#endif
1528
Damien429d7192013-10-04 19:53:11 +01001529 int old_break_label = comp->break_label;
1530 int old_continue_label = comp->continue_label;
1531
Damienb05d7072013-10-05 13:37:10 +01001532 int for_label = comp_next_label(comp);
1533 int pop_label = comp_next_label(comp);
1534 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001535
Damienb05d7072013-10-05 13:37:10 +01001536 int break_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001537
1538 comp->continue_label = for_label;
1539 comp->break_label = break_label;
1540
Damience89a212013-10-15 22:25:17 +01001541 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1542#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001543 EMIT(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001544#endif
1545
Damien429d7192013-10-04 19:53:11 +01001546 compile_node(comp, pns->nodes[1]); // iterator
1547 EMIT(get_iter);
1548 EMIT(label_assign, for_label);
1549 EMIT(for_iter, pop_label);
1550 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1551 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001552 if (!EMIT(last_emit_was_return_value)) {
Damien429d7192013-10-04 19:53:11 +01001553 EMIT(jump, for_label);
1554 }
1555 EMIT(label_assign, pop_label);
1556 EMIT(for_iter_end);
1557
1558 // break/continue apply to outer loop (if any) in the else block
1559 comp->break_label = old_break_label;
1560 comp->continue_label = old_continue_label;
1561
Damience89a212013-10-15 22:25:17 +01001562#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001563 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001564#endif
Damien429d7192013-10-04 19:53:11 +01001565
1566 compile_node(comp, pns->nodes[3]); // else (not tested)
1567
1568 EMIT(label_assign, break_label);
1569 EMIT(label_assign, end_label);
1570}
1571
Damiend99b0522013-12-21 18:17:45 +00001572void 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 +01001573 // this function is a bit of a hack at the moment
1574 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1575
1576 // setup code
1577 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001578 int l1 = comp_next_label(comp);
1579 int success_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001580 comp->except_nest_level += 1; // for correct handling of continue
1581 EMIT(setup_except, l1);
1582 compile_node(comp, pn_body); // body
1583 EMIT(pop_block);
1584 EMIT(jump, success_label);
1585 EMIT(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001586 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001587
1588 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001589 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1590 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001591
1592 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001593 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001594
Damiend99b0522013-12-21 18:17:45 +00001595 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001596 // this is a catch all exception handler
1597 if (i + 1 != n_except) {
1598 printf("SyntaxError: default 'except:' must be last\n");
1599 return;
1600 }
1601 } else {
1602 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001603 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1604 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1605 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1606 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001607 // handler binds the exception to a local
1608 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001609 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001610 }
1611 }
1612 EMIT(dup_top);
1613 compile_node(comp, pns_exception_expr);
John R. Lentonb8698fc2014-01-11 00:58:59 +00001614 EMIT(binary_op, RT_COMPARE_OP_EXCEPTION_MATCH);
Damien429d7192013-10-04 19:53:11 +01001615 EMIT(pop_jump_if_false, end_finally_label);
1616 }
1617
1618 EMIT(pop_top);
1619
1620 if (qstr_exception_local == 0) {
1621 EMIT(pop_top);
1622 } else {
Damien4b03e772013-10-05 14:17:09 +01001623 EMIT(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001624 }
1625
1626 EMIT(pop_top);
1627
Damiene2880aa2013-12-20 14:22:59 +00001628 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001629 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001630 l3 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001631 EMIT(setup_finally, l3);
1632 }
1633 compile_node(comp, pns_except->nodes[1]);
1634 if (qstr_exception_local != 0) {
1635 EMIT(pop_block);
1636 }
1637 EMIT(pop_except);
1638 if (qstr_exception_local != 0) {
Damiend99b0522013-12-21 18:17:45 +00001639 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001640 EMIT(label_assign, l3);
Damiend99b0522013-12-21 18:17:45 +00001641 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien4b03e772013-10-05 14:17:09 +01001642 EMIT(store_id, qstr_exception_local);
1643 EMIT(delete_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001644 EMIT(end_finally);
1645 }
1646 EMIT(jump, l2);
1647 EMIT(label_assign, end_finally_label);
1648 }
1649
1650 EMIT(end_finally);
1651 EMIT(label_assign, success_label);
1652 comp->except_nest_level -= 1;
1653 compile_node(comp, pn_else); // else block, can be null
1654 EMIT(label_assign, l2);
1655 EMIT(set_stack_size, stack_size);
1656}
1657
Damiend99b0522013-12-21 18:17:45 +00001658void 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 +01001659 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1660 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001661 int l_finally_block = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001662 EMIT(setup_finally, l_finally_block);
1663 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001664 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001665 compile_node(comp, pn_body);
1666 } else {
1667 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1668 }
1669 EMIT(pop_block);
Damiend99b0522013-12-21 18:17:45 +00001670 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001671 EMIT(label_assign, l_finally_block);
1672 compile_node(comp, pn_finally);
1673 EMIT(end_finally);
1674 EMIT(set_stack_size, stack_size);
1675}
1676
Damiend99b0522013-12-21 18:17:45 +00001677void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1678 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1679 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1680 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001681 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001682 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1683 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001684 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001685 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001686 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001687 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001688 // no finally
1689 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1690 } else {
1691 // have finally
Damiend99b0522013-12-21 18:17:45 +00001692 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 +01001693 }
1694 } else {
1695 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001696 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001697 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001698 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001699 }
1700 } else {
1701 // shouldn't happen
1702 assert(0);
1703 }
1704}
1705
Damiend99b0522013-12-21 18:17:45 +00001706void 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 +01001707 if (n == 0) {
1708 // no more pre-bits, compile the body of the with
1709 compile_node(comp, body);
1710 } else {
Damienb05d7072013-10-05 13:37:10 +01001711 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001712 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001713 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001714 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001715 compile_node(comp, pns->nodes[0]);
1716 EMIT(setup_with, l_end);
1717 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1718 } else {
1719 // this pre-bit is just an expression
1720 compile_node(comp, nodes[0]);
1721 EMIT(setup_with, l_end);
1722 EMIT(pop_top);
1723 }
1724 // compile additional pre-bits and the body
1725 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1726 // finish this with block
1727 EMIT(pop_block);
Damiend99b0522013-12-21 18:17:45 +00001728 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001729 EMIT(label_assign, l_end);
1730 EMIT(with_cleanup);
1731 EMIT(end_finally);
1732 }
1733}
1734
Damiend99b0522013-12-21 18:17:45 +00001735void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001736 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001737 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001738 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1739 assert(n > 0);
1740
1741 // compile in a nested fashion
1742 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1743}
1744
Damiend99b0522013-12-21 18:17:45 +00001745void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1746 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001747 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1748 // for REPL, evaluate then print the expression
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00001749 EMIT(load_id, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001750 compile_node(comp, pns->nodes[0]);
1751 EMIT(call_function, 1, 0, false, false);
1752 EMIT(pop_top);
1753
Damien429d7192013-10-04 19:53:11 +01001754 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001755 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001756 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001757 // do nothing with a lonely constant
1758 } else {
1759 compile_node(comp, pns->nodes[0]); // just an expression
1760 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1761 }
Damien429d7192013-10-04 19:53:11 +01001762 }
1763 } else {
Damiend99b0522013-12-21 18:17:45 +00001764 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1765 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001766 if (kind == PN_expr_stmt_augassign) {
1767 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1768 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001769 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001770 // note that we don't really need to implement separate inplace ops, just normal binary ops will suffice
Damiend99b0522013-12-21 18:17:45 +00001771 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
1772 case MP_TOKEN_DEL_PIPE_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_OR); break;
1773 case MP_TOKEN_DEL_CARET_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_XOR); break;
1774 case MP_TOKEN_DEL_AMPERSAND_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_AND); break;
1775 case MP_TOKEN_DEL_DBL_LESS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_LSHIFT); break;
1776 case MP_TOKEN_DEL_DBL_MORE_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_RSHIFT); break;
1777 case MP_TOKEN_DEL_PLUS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_ADD); break;
1778 case MP_TOKEN_DEL_MINUS_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_SUBTRACT); break;
1779 case MP_TOKEN_DEL_STAR_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_MULTIPLY); break;
1780 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_FLOOR_DIVIDE); break;
1781 case MP_TOKEN_DEL_SLASH_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_TRUE_DIVIDE); break;
1782 case MP_TOKEN_DEL_PERCENT_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_MODULO); break;
1783 case MP_TOKEN_DEL_DBL_STAR_EQUAL: EMIT(binary_op, RT_BINARY_OP_INPLACE_POWER); break;
Damien429d7192013-10-04 19:53:11 +01001784 default: assert(0); // shouldn't happen
1785 }
1786 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1787 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001788 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1789 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001790 // following CPython, we store left-most first
1791 if (rhs > 0) {
1792 EMIT(dup_top);
1793 }
1794 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1795 for (int i = 0; i < rhs; i++) {
1796 if (i + 1 < rhs) {
1797 EMIT(dup_top);
1798 }
Damiend99b0522013-12-21 18:17:45 +00001799 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001800 }
1801 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001802 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1803 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1804 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1805 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001806 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001807 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1808 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001809 compile_node(comp, pns10->nodes[0]); // rhs
1810 compile_node(comp, pns10->nodes[1]); // rhs
1811 EMIT(rot_two);
1812 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1813 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001814 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1815 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1816 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1817 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001818 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001819 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1820 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001821 compile_node(comp, pns10->nodes[0]); // rhs
1822 compile_node(comp, pns10->nodes[1]); // rhs
1823 compile_node(comp, pns10->nodes[2]); // rhs
1824 EMIT(rot_three);
1825 EMIT(rot_two);
1826 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1827 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1828 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1829 } else {
1830 compile_node(comp, pns1->nodes[0]); // rhs
1831 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1832 }
1833 } else {
1834 // shouldn't happen
1835 assert(0);
1836 }
1837 }
1838}
1839
Damiend99b0522013-12-21 18:17:45 +00001840void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1841 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001842 compile_node(comp, pns->nodes[0]);
1843 for (int i = 1; i < num_nodes; i += 1) {
1844 compile_node(comp, pns->nodes[i]);
1845 EMIT(binary_op, binary_op);
1846 }
1847}
1848
Damiend99b0522013-12-21 18:17:45 +00001849void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1850 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1851 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001852
1853 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001854 int l_fail = comp_next_label(comp);
1855 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001856 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1857 compile_node(comp, pns->nodes[0]); // success value
1858 EMIT(jump, l_end);
1859 EMIT(label_assign, l_fail);
1860 EMIT(set_stack_size, stack_size); // force stack size reset
1861 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1862 EMIT(label_assign, l_end);
1863}
1864
Damiend99b0522013-12-21 18:17:45 +00001865void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001866 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001867 //mp_parse_node_t pn_params = pns->nodes[0];
1868 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001869
1870 if (comp->pass == PASS_1) {
1871 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001872 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 +01001873 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001874 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001875 }
1876
1877 // get the scope for this lambda
1878 scope_t *this_scope = (scope_t*)pns->nodes[2];
1879
1880 // make the lambda
1881 close_over_variables_etc(comp, this_scope, 0, 0);
1882}
1883
Damiend99b0522013-12-21 18:17:45 +00001884void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001885 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001886 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001887 for (int i = 0; i < n; i += 1) {
1888 compile_node(comp, pns->nodes[i]);
1889 if (i + 1 < n) {
1890 EMIT(jump_if_true_or_pop, l_end);
1891 }
1892 }
1893 EMIT(label_assign, l_end);
1894}
1895
Damiend99b0522013-12-21 18:17:45 +00001896void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001897 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001898 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001899 for (int i = 0; i < n; i += 1) {
1900 compile_node(comp, pns->nodes[i]);
1901 if (i + 1 < n) {
1902 EMIT(jump_if_false_or_pop, l_end);
1903 }
1904 }
1905 EMIT(label_assign, l_end);
1906}
1907
Damiend99b0522013-12-21 18:17:45 +00001908void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001909 compile_node(comp, pns->nodes[0]);
1910 EMIT(unary_op, RT_UNARY_OP_NOT);
1911}
1912
Damiend99b0522013-12-21 18:17:45 +00001913void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001914 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001915 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001916 compile_node(comp, pns->nodes[0]);
1917 bool multi = (num_nodes > 3);
1918 int l_fail = 0;
1919 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001920 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001921 }
1922 for (int i = 1; i + 1 < num_nodes; i += 2) {
1923 compile_node(comp, pns->nodes[i + 1]);
1924 if (i + 2 < num_nodes) {
1925 EMIT(dup_top);
1926 EMIT(rot_three);
1927 }
Damiend99b0522013-12-21 18:17:45 +00001928 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS)) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001929 EMIT(binary_op, RT_COMPARE_OP_LESS);
Damiend99b0522013-12-21 18:17:45 +00001930 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE)) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001931 EMIT(binary_op, RT_COMPARE_OP_MORE);
Damiend99b0522013-12-21 18:17:45 +00001932 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_EQUAL)) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001933 EMIT(binary_op, RT_COMPARE_OP_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001934 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS_EQUAL)) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001935 EMIT(binary_op, RT_COMPARE_OP_LESS_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001936 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE_EQUAL)) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001937 EMIT(binary_op, RT_COMPARE_OP_MORE_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001938 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_NOT_EQUAL)) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001939 EMIT(binary_op, RT_COMPARE_OP_NOT_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001940 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_KW_IN)) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001941 EMIT(binary_op, RT_COMPARE_OP_IN);
Damiend99b0522013-12-21 18:17:45 +00001942 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
1943 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
1944 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01001945 if (kind == PN_comp_op_not_in) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001946 EMIT(binary_op, RT_COMPARE_OP_NOT_IN);
Damien429d7192013-10-04 19:53:11 +01001947 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00001948 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001949 EMIT(binary_op, RT_COMPARE_OP_IS);
Damien429d7192013-10-04 19:53:11 +01001950 } else {
John R. Lentonb8698fc2014-01-11 00:58:59 +00001951 EMIT(binary_op, RT_COMPARE_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01001952 }
1953 } else {
1954 // shouldn't happen
1955 assert(0);
1956 }
1957 } else {
1958 // shouldn't happen
1959 assert(0);
1960 }
1961 if (i + 2 < num_nodes) {
1962 EMIT(jump_if_false_or_pop, l_fail);
1963 }
1964 }
1965 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001966 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001967 EMIT(jump, l_end);
1968 EMIT(label_assign, l_fail);
1969 EMIT(rot_two);
1970 EMIT(pop_top);
1971 EMIT(label_assign, l_end);
1972 EMIT(set_stack_size, stack_size + 1); // force stack size
1973 }
1974}
1975
Damiend99b0522013-12-21 18:17:45 +00001976void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001977 // TODO
1978 assert(0);
1979 compile_node(comp, pns->nodes[0]);
1980 //EMIT(unary_op, "UNARY_STAR");
1981}
1982
Damiend99b0522013-12-21 18:17:45 +00001983void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001984 c_binary_op(comp, pns, RT_BINARY_OP_OR);
1985}
1986
Damiend99b0522013-12-21 18:17:45 +00001987void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001988 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
1989}
1990
Damiend99b0522013-12-21 18:17:45 +00001991void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001992 c_binary_op(comp, pns, RT_BINARY_OP_AND);
1993}
1994
Damiend99b0522013-12-21 18:17:45 +00001995void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1996 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001997 compile_node(comp, pns->nodes[0]);
1998 for (int i = 1; i + 1 < num_nodes; i += 2) {
1999 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002000 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien429d7192013-10-04 19:53:11 +01002001 EMIT(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00002002 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien429d7192013-10-04 19:53:11 +01002003 EMIT(binary_op, RT_BINARY_OP_RSHIFT);
2004 } else {
2005 // shouldn't happen
2006 assert(0);
2007 }
2008 }
2009}
2010
Damiend99b0522013-12-21 18:17:45 +00002011void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2012 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002013 compile_node(comp, pns->nodes[0]);
2014 for (int i = 1; i + 1 < num_nodes; i += 2) {
2015 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002016 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien429d7192013-10-04 19:53:11 +01002017 EMIT(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002018 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien429d7192013-10-04 19:53:11 +01002019 EMIT(binary_op, RT_BINARY_OP_SUBTRACT);
2020 } else {
2021 // shouldn't happen
2022 assert(0);
2023 }
2024 }
2025}
2026
Damiend99b0522013-12-21 18:17:45 +00002027void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2028 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002029 compile_node(comp, pns->nodes[0]);
2030 for (int i = 1; i + 1 < num_nodes; i += 2) {
2031 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002032 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien429d7192013-10-04 19:53:11 +01002033 EMIT(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002034 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien429d7192013-10-04 19:53:11 +01002035 EMIT(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002036 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +01002037 EMIT(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002038 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien429d7192013-10-04 19:53:11 +01002039 EMIT(binary_op, RT_BINARY_OP_MODULO);
2040 } else {
2041 // shouldn't happen
2042 assert(0);
2043 }
2044 }
2045}
2046
Damiend99b0522013-12-21 18:17:45 +00002047void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002048 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002049 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien429d7192013-10-04 19:53:11 +01002050 EMIT(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002051 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien429d7192013-10-04 19:53:11 +01002052 EMIT(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002053 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien429d7192013-10-04 19:53:11 +01002054 EMIT(unary_op, RT_UNARY_OP_INVERT);
2055 } else {
2056 // shouldn't happen
2057 assert(0);
2058 }
2059}
2060
Damiend99b0522013-12-21 18:17:45 +00002061void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool is_method_call) {
Damien429d7192013-10-04 19:53:11 +01002062 // function to call is on top of stack
2063
2064 int old_n_arg_keyword = comp->n_arg_keyword;
2065 bool old_have_star_arg = comp->have_star_arg;
2066 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2067 comp->n_arg_keyword = 0;
2068 comp->have_star_arg = false;
2069 comp->have_dbl_star_arg = false;
2070
2071 compile_node(comp, pns->nodes[0]); // arguments to function call; can be null
2072
2073 // compute number of positional arguments
2074 int n_positional = list_len(pns->nodes[0], PN_arglist) - comp->n_arg_keyword;
2075 if (comp->have_star_arg) {
2076 n_positional -= 1;
2077 }
2078 if (comp->have_dbl_star_arg) {
2079 n_positional -= 1;
2080 }
2081
2082 if (is_method_call) {
2083 EMIT(call_method, n_positional, comp->n_arg_keyword, comp->have_star_arg, comp->have_dbl_star_arg);
2084 } else {
2085 EMIT(call_function, n_positional, comp->n_arg_keyword, comp->have_star_arg, comp->have_dbl_star_arg);
2086 }
2087
2088 comp->n_arg_keyword = old_n_arg_keyword;
2089 comp->have_star_arg = old_have_star_arg;
2090 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2091}
2092
Damiend99b0522013-12-21 18:17:45 +00002093void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2094 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002095 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002096 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 +01002097 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002098 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2099 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
2100 EMIT(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien429d7192013-10-04 19:53:11 +01002101 compile_trailer_paren_helper(comp, pns_paren, true);
2102 i += 1;
2103 } else {
2104 compile_node(comp, pns->nodes[i]);
2105 }
2106 }
2107}
2108
Damiend99b0522013-12-21 18:17:45 +00002109void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002110 compile_node(comp, pns->nodes[0]);
2111 EMIT(binary_op, RT_BINARY_OP_POWER);
2112}
2113
Damiend99b0522013-12-21 18:17:45 +00002114void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002115 // a list of strings
Damien63321742013-12-10 17:41:49 +00002116
2117 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002118 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002119 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002120 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002121 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002122 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2123 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2124 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002125 if (i == 0) {
2126 string_kind = pn_kind;
2127 } else if (pn_kind != string_kind) {
2128 printf("SyntaxError: cannot mix bytes and nonbytes literals\n");
2129 return;
2130 }
Damiend99b0522013-12-21 18:17:45 +00002131 const char *str = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien63321742013-12-10 17:41:49 +00002132 n_bytes += strlen(str);
Damien429d7192013-10-04 19:53:11 +01002133 }
Damien63321742013-12-10 17:41:49 +00002134
2135 // allocate memory for concatenated string/bytes
2136 char *cat_str = m_new(char, n_bytes + 1);
Damien63321742013-12-10 17:41:49 +00002137
2138 // concatenate string/bytes
Damien Georgefe8fb912014-01-02 16:36:09 +00002139 char *s_dest = cat_str;
Damien63321742013-12-10 17:41:49 +00002140 for (int i = 0; i < n; i++) {
Damien Georgefe8fb912014-01-02 16:36:09 +00002141 const char *s = qstr_str(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
2142 size_t s_len = strlen(s);
2143 memcpy(s_dest, s, s_len);
2144 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002145 }
Damien Georgefe8fb912014-01-02 16:36:09 +00002146 *s_dest = '\0';
Damien63321742013-12-10 17:41:49 +00002147
Damien732407f2013-12-29 19:33:23 +00002148 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 +01002149}
2150
2151// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002152void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2153 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2154 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2155 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002156
2157 if (comp->pass == PASS_1) {
2158 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002159 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 +01002160 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002161 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002162 }
2163
2164 // get the scope for this comprehension
2165 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2166
2167 // compile the comprehension
2168 close_over_variables_etc(comp, this_scope, 0, 0);
2169
2170 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2171 EMIT(get_iter);
2172 EMIT(call_function, 1, 0, false, false);
2173}
2174
Damiend99b0522013-12-21 18:17:45 +00002175void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2176 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002177 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002178 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2179 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2180 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2181 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2182 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2183 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2184 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002185 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002186 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002187 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002188 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002189 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002190 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002191 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002192 // generator expression
2193 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2194 } else {
2195 // tuple with 2 items
2196 goto tuple_with_2_items;
2197 }
2198 } else {
2199 // tuple with 2 items
2200 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002201 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002202 }
2203 } else {
2204 // parenthesis around a single item, is just that item
2205 compile_node(comp, pns->nodes[0]);
2206 }
2207}
2208
Damiend99b0522013-12-21 18:17:45 +00002209void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2210 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002211 // empty list
2212 EMIT(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002213 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2214 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2215 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2216 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2217 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002218 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002219 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002220 compile_node(comp, pns2->nodes[0]);
2221 EMIT(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002222 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002223 // list of many items
2224 compile_node(comp, pns2->nodes[0]);
2225 compile_generic_all_nodes(comp, pns3);
Damiend99b0522013-12-21 18:17:45 +00002226 EMIT(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
2227 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002228 // list comprehension
2229 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2230 } else {
2231 // list with 2 items
2232 goto list_with_2_items;
2233 }
2234 } else {
2235 // list with 2 items
2236 list_with_2_items:
2237 compile_node(comp, pns2->nodes[0]);
2238 compile_node(comp, pns2->nodes[1]);
2239 EMIT(build_list, 2);
2240 }
2241 } else {
2242 // list with 1 item
2243 compile_node(comp, pns->nodes[0]);
2244 EMIT(build_list, 1);
2245 }
2246}
2247
Damiend99b0522013-12-21 18:17:45 +00002248void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2249 mp_parse_node_t pn = pns->nodes[0];
2250 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002251 // empty dict
2252 EMIT(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002253 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2254 pns = (mp_parse_node_struct_t*)pn;
2255 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002256 // dict with one element
2257 EMIT(build_map, 1);
2258 compile_node(comp, pn);
2259 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002260 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2261 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2262 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2263 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002264 // dict/set with multiple elements
2265
2266 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002267 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002268 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2269
2270 // first element sets whether it's a dict or set
2271 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002272 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002273 // a dictionary
2274 EMIT(build_map, 1 + n);
2275 compile_node(comp, pns->nodes[0]);
2276 EMIT(store_map);
2277 is_dict = true;
2278 } else {
2279 // a set
2280 compile_node(comp, pns->nodes[0]); // 1st value of set
2281 is_dict = false;
2282 }
2283
2284 // process rest of elements
2285 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002286 mp_parse_node_t pn = nodes[i];
2287 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002288 compile_node(comp, pn);
2289 if (is_dict) {
2290 if (!is_key_value) {
2291 printf("SyntaxError?: expecting key:value for dictionary");
2292 return;
2293 }
2294 EMIT(store_map);
2295 } else {
2296 if (is_key_value) {
2297 printf("SyntaxError?: expecting just a value for set");
2298 return;
2299 }
2300 }
2301 }
2302
2303 // if it's a set, build it
2304 if (!is_dict) {
2305 EMIT(build_set, 1 + n);
2306 }
Damiend99b0522013-12-21 18:17:45 +00002307 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002308 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002309 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002310 // a dictionary comprehension
2311 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2312 } else {
2313 // a set comprehension
2314 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2315 }
2316 } else {
2317 // shouldn't happen
2318 assert(0);
2319 }
2320 } else {
2321 // set with one element
2322 goto set_with_one_element;
2323 }
2324 } else {
2325 // set with one element
2326 set_with_one_element:
2327 compile_node(comp, pn);
2328 EMIT(build_set, 1);
2329 }
2330}
2331
Damiend99b0522013-12-21 18:17:45 +00002332void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002333 compile_trailer_paren_helper(comp, pns, false);
2334}
2335
Damiend99b0522013-12-21 18:17:45 +00002336void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002337 // object who's index we want is on top of stack
2338 compile_node(comp, pns->nodes[0]); // the index
2339 EMIT(binary_op, RT_BINARY_OP_SUBSCR);
2340}
2341
Damiend99b0522013-12-21 18:17:45 +00002342void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002343 // object who's attribute we want is on top of stack
Damiend99b0522013-12-21 18:17:45 +00002344 EMIT(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002345}
2346
Damiend99b0522013-12-21 18:17:45 +00002347void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2348 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2349 mp_parse_node_t pn = pns->nodes[0];
2350 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002351 // [?:]
Damiend99b0522013-12-21 18:17:45 +00002352 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002353 EMIT(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002354 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2355 pns = (mp_parse_node_struct_t*)pn;
2356 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
2357 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002358 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002359 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002360 // [?::]
2361 EMIT(build_slice, 2);
2362 } else {
2363 // [?::x]
2364 compile_node(comp, pn);
2365 EMIT(build_slice, 3);
2366 }
Damiend99b0522013-12-21 18:17:45 +00002367 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002368 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002369 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2370 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2371 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2372 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002373 // [?:x:]
2374 EMIT(build_slice, 2);
2375 } else {
2376 // [?:x:x]
2377 compile_node(comp, pns->nodes[0]);
2378 EMIT(build_slice, 3);
2379 }
2380 } else {
2381 // [?:x]
2382 compile_node(comp, pn);
2383 EMIT(build_slice, 2);
2384 }
2385 } else {
2386 // [?:x]
2387 compile_node(comp, pn);
2388 EMIT(build_slice, 2);
2389 }
2390}
2391
Damiend99b0522013-12-21 18:17:45 +00002392void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002393 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002394 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2395 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002396}
2397
Damiend99b0522013-12-21 18:17:45 +00002398void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
2399 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002400 compile_subscript_3_helper(comp, pns);
2401}
2402
Damiend99b0522013-12-21 18:17:45 +00002403void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002404 // if this is called then we are compiling a dict key:value pair
2405 compile_node(comp, pns->nodes[1]); // value
2406 compile_node(comp, pns->nodes[0]); // key
2407}
2408
Damiend99b0522013-12-21 18:17:45 +00002409void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002410 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002411 // store class object into class name
Damien4b03e772013-10-05 14:17:09 +01002412 EMIT(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002413}
2414
Damiend99b0522013-12-21 18:17:45 +00002415void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002416 if (comp->have_star_arg) {
2417 printf("SyntaxError?: can't have multiple *x\n");
2418 return;
2419 }
2420 comp->have_star_arg = true;
2421 compile_node(comp, pns->nodes[0]);
2422}
2423
Damiend99b0522013-12-21 18:17:45 +00002424void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002425 if (comp->have_dbl_star_arg) {
2426 printf("SyntaxError?: can't have multiple **x\n");
2427 return;
2428 }
2429 comp->have_dbl_star_arg = true;
2430 compile_node(comp, pns->nodes[0]);
2431}
2432
Damiend99b0522013-12-21 18:17:45 +00002433void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2434 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2435 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2436 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2437 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002438 printf("SyntaxError?: lhs of keyword argument must be an id\n");
2439 return;
2440 }
Damiend99b0522013-12-21 18:17:45 +00002441 EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002442 compile_node(comp, pns2->nodes[0]);
2443 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002444 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002445 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2446 } else {
2447 // shouldn't happen
2448 assert(0);
2449 }
2450}
2451
Damiend99b0522013-12-21 18:17:45 +00002452void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002453 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
2454 printf("SyntaxError: 'yield' outside function\n");
2455 return;
2456 }
Damiend99b0522013-12-21 18:17:45 +00002457 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
2458 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002459 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002460 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2461 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002462 compile_node(comp, pns->nodes[0]);
2463 EMIT(get_iter);
Damiend99b0522013-12-21 18:17:45 +00002464 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002465 EMIT(yield_from);
2466 } else {
2467 compile_node(comp, pns->nodes[0]);
2468 EMIT(yield_value);
2469 }
2470}
2471
Damiend99b0522013-12-21 18:17:45 +00002472typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Damien429d7192013-10-04 19:53:11 +01002473static compile_function_t compile_function[] = {
2474 NULL,
2475#define nc NULL
2476#define c(f) compile_##f
2477#define DEF_RULE(rule, comp, kind, arg...) comp,
2478#include "grammar.h"
2479#undef nc
2480#undef c
2481#undef DEF_RULE
2482};
2483
Damiend99b0522013-12-21 18:17:45 +00002484void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2485 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002486 // pass
Damiend99b0522013-12-21 18:17:45 +00002487 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
2488 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
2489 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
2490 case MP_PARSE_NODE_ID: EMIT(load_id, arg); break;
2491 case MP_PARSE_NODE_SMALL_INT: EMIT(load_const_small_int, arg); break;
2492 case MP_PARSE_NODE_INTEGER: EMIT(load_const_int, arg); break;
2493 case MP_PARSE_NODE_DECIMAL: EMIT(load_const_dec, arg); break;
2494 case MP_PARSE_NODE_STRING: EMIT(load_const_str, arg, false); break;
2495 case MP_PARSE_NODE_BYTES: EMIT(load_const_str, arg, true); break;
2496 case MP_PARSE_NODE_TOKEN:
2497 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002498 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002499 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002500 // do nothing
2501 } else {
2502 EMIT(load_const_tok, arg);
2503 }
2504 break;
Damien429d7192013-10-04 19:53:11 +01002505 default: assert(0);
2506 }
2507 } else {
Damiend99b0522013-12-21 18:17:45 +00002508 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien George08335002014-01-18 23:24:36 +00002509 EMIT(set_line_number, pns->source_line);
Damiend99b0522013-12-21 18:17:45 +00002510 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002511 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002512 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien Georgecbd2f742014-01-19 11:48:48 +00002513#if MICROPY_DEBUG_PRINTERS
2514 mp_parse_node_print(pn, 0);
2515#endif
Damien429d7192013-10-04 19:53:11 +01002516 assert(0);
2517 } else {
2518 f(comp, pns);
2519 }
2520 }
2521}
2522
Damiend99b0522013-12-21 18:17:45 +00002523void 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 +01002524 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002525 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002526 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2527 if (MP_PARSE_NODE_IS_ID(pn)) {
2528 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002529 if (comp->have_bare_star) {
2530 // comes after a bare star, so doesn't count as a parameter
2531 } else {
2532 comp->scope_cur->num_params += 1;
2533 }
Damienb14de212013-10-06 00:28:28 +01002534 } else {
Damiend99b0522013-12-21 18:17:45 +00002535 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2536 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2537 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2538 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002539 //int node_index = 1; unused
2540 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002541 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002542 // this parameter has an annotation
2543 pn_annotation = pns->nodes[1];
2544 }
2545 //node_index = 2; unused
2546 }
2547 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002548 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002549 // this parameter has a default value
2550 if (comp->have_bare_star) {
2551 comp->scope_cur->num_dict_params += 1;
2552 } else {
2553 comp->scope_cur->num_default_params += 1;
2554 }
2555 }
2556 */
2557 if (comp->have_bare_star) {
2558 // comes after a bare star, so doesn't count as a parameter
2559 } else {
2560 comp->scope_cur->num_params += 1;
2561 }
Damiend99b0522013-12-21 18:17:45 +00002562 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2563 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002564 // bare star
2565 // TODO see http://www.python.org/dev/peps/pep-3102/
2566 comp->have_bare_star = true;
2567 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002568 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002569 // named star
2570 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002571 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2572 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002573 // named star with annotation
2574 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002575 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2576 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002577 pn_annotation = pns->nodes[1];
2578 } else {
2579 // shouldn't happen
2580 assert(0);
2581 }
Damiend99b0522013-12-21 18:17:45 +00002582 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2583 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2584 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002585 // this parameter has an annotation
2586 pn_annotation = pns->nodes[1];
2587 }
2588 comp->scope_cur->flags |= SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002589 } else {
Damienb14de212013-10-06 00:28:28 +01002590 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002591 assert(0);
2592 }
Damien429d7192013-10-04 19:53:11 +01002593 }
2594
2595 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002596 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002597 // TODO this parameter has an annotation
2598 }
2599 bool added;
2600 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2601 if (!added) {
2602 printf("SyntaxError?: same name used for parameter; %s\n", qstr_str(param_name));
2603 return;
2604 }
2605 id_info->param = true;
2606 id_info->kind = ID_INFO_KIND_LOCAL;
2607 }
2608}
2609
Damiend99b0522013-12-21 18:17:45 +00002610void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002611 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2612}
2613
Damiend99b0522013-12-21 18:17:45 +00002614void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002615 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2616}
2617
Damiend99b0522013-12-21 18:17:45 +00002618void 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 +01002619 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002620 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002621 // no more nested if/for; compile inner expression
2622 compile_node(comp, pn_inner_expr);
2623 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
2624 EMIT(list_append, for_depth + 2);
2625 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
2626 EMIT(map_add, for_depth + 2);
2627 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
2628 EMIT(set_add, for_depth + 2);
2629 } else {
2630 EMIT(yield_value);
2631 EMIT(pop_top);
2632 }
Damiend99b0522013-12-21 18:17:45 +00002633 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002634 // if condition
Damiend99b0522013-12-21 18:17:45 +00002635 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002636 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2637 pn_iter = pns_comp_if->nodes[1];
2638 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002639 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002640 // for loop
Damiend99b0522013-12-21 18:17:45 +00002641 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002642 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002643 int l_end2 = comp_next_label(comp);
2644 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002645 EMIT(get_iter);
2646 EMIT(label_assign, l_top2);
2647 EMIT(for_iter, l_end2);
2648 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2649 compile_scope_comp_iter(comp, pns_comp_for2->nodes[2], pn_inner_expr, l_top2, for_depth + 1);
2650 EMIT(jump, l_top2);
2651 EMIT(label_assign, l_end2);
2652 EMIT(for_iter_end);
2653 } else {
2654 // shouldn't happen
2655 assert(0);
2656 }
2657}
2658
Damiend99b0522013-12-21 18:17:45 +00002659void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002660 // see http://www.python.org/dev/peps/pep-0257/
2661
2662 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002663 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002664 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002665 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002666 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002667 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2668 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002669 for (int i = 0; i < num_nodes; i++) {
2670 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002671 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 +00002672 // not a newline, so this is the first statement; finish search
2673 break;
2674 }
2675 }
2676 // 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 +00002677 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002678 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002679 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002680 } else {
2681 return;
2682 }
2683
2684 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002685 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2686 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2687 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2688 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2689 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002690 compile_node(comp, pns->nodes[0]); // a doc string
2691 // store doc string
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002692 EMIT(store_id, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002693 }
2694 }
2695 }
2696}
2697
2698void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2699 comp->pass = pass;
2700 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002701 comp->next_label = 1;
Damien415eb6f2013-10-05 12:19:06 +01002702 EMIT(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002703
2704 if (comp->pass == PASS_1) {
2705 scope->stack_size = 0;
2706 }
2707
Damien5ac1b2e2013-10-18 19:58:12 +01002708#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002709 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002710 scope_print_info(scope);
2711 }
Damien5ac1b2e2013-10-18 19:58:12 +01002712#endif
Damien429d7192013-10-04 19:53:11 +01002713
2714 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002715 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2716 assert(scope->kind == SCOPE_MODULE);
2717 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2718 compile_node(comp, pns->nodes[0]); // compile the expression
2719 EMIT(return_value);
2720 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002721 if (!comp->is_repl) {
2722 check_for_doc_string(comp, scope->pn);
2723 }
Damien429d7192013-10-04 19:53:11 +01002724 compile_node(comp, scope->pn);
Damiend99b0522013-12-21 18:17:45 +00002725 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002726 EMIT(return_value);
2727 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002728 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2729 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2730 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002731
2732 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002733 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002734 if (comp->pass == PASS_1) {
2735 comp->have_bare_star = false;
2736 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2737 }
2738
Damiend99b0522013-12-21 18:17:45 +00002739 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // 2 is something...
Damien429d7192013-10-04 19:53:11 +01002740
2741 compile_node(comp, pns->nodes[3]); // 3 is function body
2742 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002743 if (!EMIT(last_emit_was_return_value)) {
Damiend99b0522013-12-21 18:17:45 +00002744 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002745 EMIT(return_value);
2746 }
2747 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002748 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2749 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2750 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002751
2752 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002753 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002754 if (comp->pass == PASS_1) {
2755 comp->have_bare_star = false;
2756 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2757 }
2758
2759 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2760 EMIT(return_value);
2761 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2762 // a bit of a hack at the moment
2763
Damiend99b0522013-12-21 18:17:45 +00002764 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2765 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2766 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2767 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2768 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002769
Damien6cdd3af2013-10-05 18:08:26 +01002770 qstr qstr_arg = qstr_from_str_static(".0");
Damien429d7192013-10-04 19:53:11 +01002771 if (comp->pass == PASS_1) {
2772 bool added;
2773 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2774 assert(added);
2775 id_info->kind = ID_INFO_KIND_LOCAL;
2776 scope->num_params = 1;
2777 }
2778
2779 if (scope->kind == SCOPE_LIST_COMP) {
2780 EMIT(build_list, 0);
2781 } else if (scope->kind == SCOPE_DICT_COMP) {
2782 EMIT(build_map, 0);
2783 } else if (scope->kind == SCOPE_SET_COMP) {
2784 EMIT(build_set, 0);
2785 }
2786
Damienb05d7072013-10-05 13:37:10 +01002787 int l_end = comp_next_label(comp);
2788 int l_top = comp_next_label(comp);
Damien4b03e772013-10-05 14:17:09 +01002789 EMIT(load_id, qstr_arg);
Damien429d7192013-10-04 19:53:11 +01002790 EMIT(label_assign, l_top);
2791 EMIT(for_iter, l_end);
2792 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2793 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
2794 EMIT(jump, l_top);
2795 EMIT(label_assign, l_end);
2796 EMIT(for_iter_end);
2797
2798 if (scope->kind == SCOPE_GEN_EXPR) {
Damiend99b0522013-12-21 18:17:45 +00002799 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002800 }
2801 EMIT(return_value);
2802 } else {
2803 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00002804 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2805 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2806 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01002807
2808 if (comp->pass == PASS_1) {
2809 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002810 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01002811 assert(added);
2812 id_info->kind = ID_INFO_KIND_LOCAL;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002813 id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
Damien429d7192013-10-04 19:53:11 +01002814 assert(added);
2815 id_info->kind = ID_INFO_KIND_LOCAL;
2816 id_info->param = true;
2817 scope->num_params = 1; // __locals__ is the parameter
2818 }
2819
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002820 EMIT(load_id, MP_QSTR___locals__);
Damien429d7192013-10-04 19:53:11 +01002821 EMIT(store_locals);
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002822 EMIT(load_id, MP_QSTR___name__);
2823 EMIT(store_id, MP_QSTR___module__);
Damiend99b0522013-12-21 18:17:45 +00002824 EMIT(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002825 EMIT(store_id, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01002826
2827 check_for_doc_string(comp, pns->nodes[2]);
2828 compile_node(comp, pns->nodes[2]); // 2 is class body
2829
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002830 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01002831 assert(id != NULL);
2832 if (id->kind == ID_INFO_KIND_LOCAL) {
Damiend99b0522013-12-21 18:17:45 +00002833 EMIT(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002834 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002835#if MICROPY_EMIT_CPYTHON
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002836 EMIT(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002837#else
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002838 EMIT(load_fast, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002839#endif
Damien429d7192013-10-04 19:53:11 +01002840 }
2841 EMIT(return_value);
2842 }
2843
Damien415eb6f2013-10-05 12:19:06 +01002844 EMIT(end_pass);
Damien826005c2013-10-05 23:17:28 +01002845}
2846
2847void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2848 comp->pass = pass;
2849 comp->scope_cur = scope;
2850 comp->next_label = 1;
2851
2852 if (scope->kind != SCOPE_FUNCTION) {
2853 printf("Error: inline assembler must be a function\n");
2854 return;
2855 }
2856
Damiena2f2f7d2013-10-06 00:14:13 +01002857 if (comp->pass > PASS_1) {
2858 EMIT_INLINE_ASM(start_pass, comp->pass, comp->scope_cur);
2859 }
2860
Damien826005c2013-10-05 23:17:28 +01002861 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002862 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2863 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2864 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002865
Damiend99b0522013-12-21 18:17:45 +00002866 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002867
Damiena2f2f7d2013-10-06 00:14:13 +01002868 // parameters are in pns->nodes[1]
2869 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002870 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002871 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
2872 scope->num_params = EMIT_INLINE_ASM(count_params, n_params, pn_params);
2873 }
2874
Damiend99b0522013-12-21 18:17:45 +00002875 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002876
Damiend99b0522013-12-21 18:17:45 +00002877 mp_parse_node_t pn_body = pns->nodes[3]; // body
2878 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002879 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2880
Damien Georgecbd2f742014-01-19 11:48:48 +00002881 /*
Damien826005c2013-10-05 23:17:28 +01002882 if (comp->pass == PASS_3) {
2883 //printf("----\n");
2884 scope_print_info(scope);
2885 }
Damien Georgecbd2f742014-01-19 11:48:48 +00002886 */
Damien826005c2013-10-05 23:17:28 +01002887
2888 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002889 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2890 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2891 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2892 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2893 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2894 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2895 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2896 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2897 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2898 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2899 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2900 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2901 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002902 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2903
2904 // emit instructions
2905 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00002906 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien826005c2013-10-05 23:17:28 +01002907 printf("SyntaxError: inline assembler 'label' requires 1 argument\n");
2908 return;
2909 }
2910 int lab = comp_next_label(comp);
2911 if (pass > PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00002912 EMIT_INLINE_ASM(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01002913 }
2914 } else {
2915 if (pass > PASS_1) {
2916 EMIT_INLINE_ASM(op, op, n_args, pn_arg);
2917 }
2918 }
2919 }
2920
2921 if (comp->pass > PASS_1) {
2922 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01002923 }
Damien429d7192013-10-04 19:53:11 +01002924}
2925
2926void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
2927 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00002928 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01002929 scope->num_locals = 0;
2930 for (int i = 0; i < scope->id_info_len; i++) {
2931 id_info_t *id = &scope->id_info[i];
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002932 if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01002933 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
2934 continue;
2935 }
2936 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
2937 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
2938 }
Damien9ecbcff2013-12-11 00:41:43 +00002939 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01002940 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
2941 id->local_num = scope->num_locals;
2942 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002943 }
2944 }
2945
2946 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00002947#if MICROPY_EMIT_CPYTHON
2948 int num_cell = 0;
2949#endif
Damien9ecbcff2013-12-11 00:41:43 +00002950 for (int i = 0; i < scope->id_info_len; i++) {
2951 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00002952#if MICROPY_EMIT_CPYTHON
2953 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00002954 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00002955 id->local_num = num_cell;
2956 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002957 }
Damien George6baf76e2013-12-30 22:32:17 +00002958#else
2959 // in Micro Python the cells come right after the fast locals
2960 // parameters are not counted here, since they remain at the start
2961 // of the locals, even if they are cell vars
2962 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
2963 id->local_num = scope->num_locals;
2964 scope->num_locals += 1;
2965 }
2966#endif
Damien9ecbcff2013-12-11 00:41:43 +00002967 }
Damien9ecbcff2013-12-11 00:41:43 +00002968
2969 // compute the index of free vars (freevars[idx] in CPython)
2970 // make sure they are in the order of the parent scope
2971 if (scope->parent != NULL) {
2972 int num_free = 0;
2973 for (int i = 0; i < scope->parent->id_info_len; i++) {
2974 id_info_t *id = &scope->parent->id_info[i];
2975 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
2976 for (int j = 0; j < scope->id_info_len; j++) {
2977 id_info_t *id2 = &scope->id_info[j];
2978 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00002979 assert(!id2->param); // free vars should not be params
2980#if MICROPY_EMIT_CPYTHON
2981 // in CPython the frees are numbered after the cells
2982 id2->local_num = num_cell + num_free;
2983#else
2984 // in Micro Python the frees come first, before the params
2985 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00002986#endif
2987 num_free += 1;
2988 }
2989 }
2990 }
Damien429d7192013-10-04 19:53:11 +01002991 }
Damien George6baf76e2013-12-30 22:32:17 +00002992#if !MICROPY_EMIT_CPYTHON
2993 // in Micro Python shift all other locals after the free locals
2994 if (num_free > 0) {
2995 for (int i = 0; i < scope->id_info_len; i++) {
2996 id_info_t *id = &scope->id_info[i];
2997 if (id->param || id->kind != ID_INFO_KIND_FREE) {
2998 id->local_num += num_free;
2999 }
3000 }
3001 scope->num_params += num_free; // free vars are counted as params for passing them into the function
3002 scope->num_locals += num_free;
3003 }
3004#endif
Damien429d7192013-10-04 19:53:11 +01003005 }
3006
3007 // compute flags
3008 //scope->flags = 0; since we set some things in parameters
3009 if (scope->kind != SCOPE_MODULE) {
3010 scope->flags |= SCOPE_FLAG_NEWLOCALS;
3011 }
3012 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) {
3013 assert(scope->parent != NULL);
3014 scope->flags |= SCOPE_FLAG_OPTIMISED;
3015
3016 // TODO possibly other ways it can be nested
3017 if (scope->parent->kind == SCOPE_FUNCTION || (scope->parent->kind == SCOPE_CLASS && scope->parent->parent->kind == SCOPE_FUNCTION)) {
3018 scope->flags |= SCOPE_FLAG_NESTED;
3019 }
3020 }
3021 int num_free = 0;
3022 for (int i = 0; i < scope->id_info_len; i++) {
3023 id_info_t *id = &scope->id_info[i];
3024 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3025 num_free += 1;
3026 }
3027 }
3028 if (num_free == 0) {
3029 scope->flags |= SCOPE_FLAG_NOFREE;
3030 }
3031}
3032
Damien George08335002014-01-18 23:24:36 +00003033mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003034 compiler_t *comp = m_new(compiler_t, 1);
3035
Damien Georgecbd2f742014-01-19 11:48:48 +00003036 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003037 comp->is_repl = is_repl;
3038 comp->had_error = false;
3039
Damien429d7192013-10-04 19:53:11 +01003040 comp->break_label = 0;
3041 comp->continue_label = 0;
3042 comp->except_nest_level = 0;
3043 comp->scope_head = NULL;
3044 comp->scope_cur = NULL;
3045
Damien826005c2013-10-05 23:17:28 +01003046 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003047 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003048
3049 // set the outer scope
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003050 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003051
Damien826005c2013-10-05 23:17:28 +01003052 // compile pass 1
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003053 comp->emit = emit_pass1_new(MP_QSTR___class__);
Damien826005c2013-10-05 23:17:28 +01003054 comp->emit_method_table = &emit_pass1_method_table;
3055 comp->emit_inline_asm = NULL;
3056 comp->emit_inline_asm_method_table = NULL;
3057 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003058 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003059 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003060#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003061 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003062 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003063#endif
Damien826005c2013-10-05 23:17:28 +01003064 } else {
3065 compile_scope(comp, s, PASS_1);
3066 }
3067
3068 // update maximim number of labels needed
3069 if (comp->next_label > max_num_labels) {
3070 max_num_labels = comp->next_label;
3071 }
Damien429d7192013-10-04 19:53:11 +01003072 }
3073
Damien826005c2013-10-05 23:17:28 +01003074 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003075 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003076 compile_scope_compute_things(comp, s);
3077 }
3078
Damien826005c2013-10-05 23:17:28 +01003079 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003080 emit_pass1_free(comp->emit);
3081
Damien826005c2013-10-05 23:17:28 +01003082 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003083#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003084 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003085#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003086 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003087#endif
Damien3ef4abb2013-10-12 16:53:13 +01003088#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003089 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003090#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003091#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003092 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003093 if (false) {
3094 // dummy
3095
Damien3ef4abb2013-10-12 16:53:13 +01003096#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003097 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3098 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003099 if (emit_inline_thumb == NULL) {
3100 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3101 }
3102 comp->emit = NULL;
3103 comp->emit_method_table = NULL;
3104 comp->emit_inline_asm = emit_inline_thumb;
3105 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3106 compile_scope_inline_asm(comp, s, PASS_2);
3107 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003108#endif
3109
Damien826005c2013-10-05 23:17:28 +01003110 } else {
Damienc025ebb2013-10-12 14:30:21 +01003111
3112 // choose the emit type
3113
Damien3ef4abb2013-10-12 16:53:13 +01003114#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003115 comp->emit = emit_cpython_new(max_num_labels);
3116 comp->emit_method_table = &emit_cpython_method_table;
3117#else
Damien826005c2013-10-05 23:17:28 +01003118 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003119
3120#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003121 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003122 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003123#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003124 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003125 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003126 }
Damien13ed3a62013-10-08 09:05:10 +01003127 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003128#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003129 if (emit_native == NULL) {
3130 emit_native = emit_native_thumb_new(max_num_labels);
3131 }
3132 comp->emit_method_table = &emit_native_thumb_method_table;
3133#endif
3134 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003135 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003136 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003137#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003138
Damien826005c2013-10-05 23:17:28 +01003139 default:
3140 if (emit_bc == NULL) {
Damien Georgecbd2f742014-01-19 11:48:48 +00003141 emit_bc = emit_bc_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003142 }
3143 comp->emit = emit_bc;
3144 comp->emit_method_table = &emit_bc_method_table;
3145 break;
3146 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003147#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003148
3149 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003150 compile_scope(comp, s, PASS_2);
3151 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003152 }
Damien429d7192013-10-04 19:53:11 +01003153 }
3154
Damien George1fb03172014-01-03 14:22:03 +00003155 bool had_error = comp->had_error;
Damien732407f2013-12-29 19:33:23 +00003156 m_del_obj(compiler_t, comp);
Damien5ac1b2e2013-10-18 19:58:12 +01003157
Damien George1fb03172014-01-03 14:22:03 +00003158 if (had_error) {
3159 // TODO return a proper error message
3160 return mp_const_none;
3161 } else {
3162#if MICROPY_EMIT_CPYTHON
3163 // can't create code, so just return true
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003164 (void)module_scope; // to suppress warning that module_scope is unused
Damien George1fb03172014-01-03 14:22:03 +00003165 return mp_const_true;
3166#else
3167 // return function that executes the outer module
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003168 return rt_make_function_from_id(module_scope->unique_code_id);
Damien George1fb03172014-01-03 14:22:03 +00003169#endif
3170 }
Damien429d7192013-10-04 19:53:11 +01003171}