blob: 5415757f3d1c6ca0508e43d1b495c48020bc7280 [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <unistd.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <string.h>
6#include <assert.h>
7
8#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +000010#include "qstr.h"
Damien429d7192013-10-04 19:53:11 +010011#include "lexer.h"
Damien429d7192013-10-04 19:53:11 +010012#include "parse.h"
13#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000014#include "runtime0.h"
Damien429d7192013-10-04 19:53:11 +010015#include "emit.h"
Damien George1fb03172014-01-03 14:22:03 +000016#include "obj.h"
17#include "compile.h"
18#include "runtime.h"
Damien429d7192013-10-04 19:53:11 +010019
20// TODO need to mangle __attr names
21
Damience89a212013-10-15 22:25:17 +010022#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)
23
Damien429d7192013-10-04 19:53:11 +010024typedef enum {
25 PN_none = 0,
Damien George00208ce2014-01-23 00:00:53 +000026#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
Damien429d7192013-10-04 19:53:11 +010027#include "grammar.h"
28#undef DEF_RULE
29 PN_maximum_number_of,
30} pn_kind_t;
31
Damien Georgeb9791222014-01-23 00:34:21 +000032#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
33#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
34#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
35#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
Damien429d7192013-10-04 19:53:11 +010036
Damien6cdd3af2013-10-05 18:08:26 +010037#define EMIT_OPT_NONE (0)
38#define EMIT_OPT_BYTE_CODE (1)
39#define EMIT_OPT_NATIVE_PYTHON (2)
Damien7af3d192013-10-07 00:02:49 +010040#define EMIT_OPT_VIPER (3)
41#define EMIT_OPT_ASM_THUMB (4)
Damien6cdd3af2013-10-05 18:08:26 +010042
Damien429d7192013-10-04 19:53:11 +010043typedef struct _compiler_t {
Damien Georgecbd2f742014-01-19 11:48:48 +000044 qstr source_file;
Damien5ac1b2e2013-10-18 19:58:12 +010045 bool is_repl;
Damien429d7192013-10-04 19:53:11 +010046 pass_kind_t pass;
Damien5ac1b2e2013-10-18 19:58:12 +010047 bool had_error; // try to keep compiler clean from nlr
Damien429d7192013-10-04 19:53:11 +010048
Damienb05d7072013-10-05 13:37:10 +010049 int next_label;
Damienb05d7072013-10-05 13:37:10 +010050
Damien429d7192013-10-04 19:53:11 +010051 int break_label;
52 int continue_label;
Damien Georgecbddb272014-02-01 20:08:18 +000053 int break_continue_except_level;
54 int cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
Damien429d7192013-10-04 19:53:11 +010055
56 int n_arg_keyword;
57 bool have_star_arg;
58 bool have_dbl_star_arg;
59 bool have_bare_star;
60 int param_pass;
61 int param_pass_num_dict_params;
62 int param_pass_num_default_params;
63
64 scope_t *scope_head;
65 scope_t *scope_cur;
66
Damien6cdd3af2013-10-05 18:08:26 +010067 emit_t *emit; // current emitter
68 const emit_method_table_t *emit_method_table; // current emit method table
Damien826005c2013-10-05 23:17:28 +010069
70 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
71 const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
Damien429d7192013-10-04 19:53:11 +010072} compiler_t;
73
Damiend99b0522013-12-21 18:17:45 +000074mp_parse_node_t fold_constants(mp_parse_node_t pn) {
75 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
76 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
77 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +010078
79 // fold arguments first
80 for (int i = 0; i < n; i++) {
81 pns->nodes[i] = fold_constants(pns->nodes[i]);
82 }
83
Damiend99b0522013-12-21 18:17:45 +000084 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +010085 case PN_shift_expr:
Damiend99b0522013-12-21 18:17:45 +000086 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
87 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
88 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
89 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
Damien3ef4abb2013-10-12 16:53:13 +010090#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +010091 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +000092 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
Damien0efb3a12013-10-12 16:16:56 +010093#endif
Damiend99b0522013-12-21 18:17:45 +000094 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
95 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien429d7192013-10-04 19:53:11 +010096 } else {
97 // shouldn't happen
98 assert(0);
99 }
100 }
101 break;
102
103 case PN_arith_expr:
Damien0efb3a12013-10-12 16:16:56 +0100104 // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
Damiend99b0522013-12-21 18:17:45 +0000105 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
106 machine_int_t arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
107 machine_int_t arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
Damien0efb3a12013-10-12 16:16:56 +0100108 machine_int_t res;
Damiend99b0522013-12-21 18:17:45 +0000109 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100110 res = arg0 + arg1;
Damiend99b0522013-12-21 18:17:45 +0000111 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100112 res = arg0 - arg1;
Damien429d7192013-10-04 19:53:11 +0100113 } else {
114 // shouldn't happen
115 assert(0);
Damien0efb3a12013-10-12 16:16:56 +0100116 res = 0;
117 }
Damiend99b0522013-12-21 18:17:45 +0000118 if (MP_FIT_SMALL_INT(res)) {
119 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
Damien429d7192013-10-04 19:53:11 +0100120 }
121 }
122 break;
123
124 case PN_term:
Damiend99b0522013-12-21 18:17:45 +0000125 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
126 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
127 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
128 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien3ef4abb2013-10-12 16:53:13 +0100129#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100130 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000131 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
Damien0efb3a12013-10-12 16:16:56 +0100132#endif
Damiend99b0522013-12-21 18:17:45 +0000133 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +0100134 ; // pass
Damiend99b0522013-12-21 18:17:45 +0000135 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
Damien0efb3a12013-10-12 16:16:56 +0100136 // XXX implement this properly as Python's % operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000137 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1);
138 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
Damien0efb3a12013-10-12 16:16:56 +0100139 // XXX implement this properly as Python's // operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000140 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1);
Damien429d7192013-10-04 19:53:11 +0100141 } else {
142 // shouldn't happen
143 assert(0);
144 }
145 }
146 break;
147
148 case PN_factor_2:
Damiend99b0522013-12-21 18:17:45 +0000149 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
150 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
151 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
152 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
153 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
154 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
155 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
156 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien429d7192013-10-04 19:53:11 +0100157 } else {
158 // shouldn't happen
159 assert(0);
160 }
161 }
162 break;
163
Damien3ef4abb2013-10-12 16:53:13 +0100164#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +0100165 case PN_power:
Damien0efb3a12013-10-12 16:16:56 +0100166 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000167 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_NULL(pns->nodes[1]) && !MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
168 mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
169 if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
170 int power = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100171 if (power >= 0) {
172 int ans = 1;
Damiend99b0522013-12-21 18:17:45 +0000173 int base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100174 for (; power > 0; power--) {
175 ans *= base;
176 }
Damiend99b0522013-12-21 18:17:45 +0000177 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien429d7192013-10-04 19:53:11 +0100178 }
179 }
180 }
181 break;
Damien0efb3a12013-10-12 16:16:56 +0100182#endif
Damien429d7192013-10-04 19:53:11 +0100183 }
184 }
185
186 return pn;
187}
188
Damiend99b0522013-12-21 18:17:45 +0000189void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100190
Damienb05d7072013-10-05 13:37:10 +0100191static int comp_next_label(compiler_t *comp) {
192 return comp->next_label++;
193}
194
Damiend99b0522013-12-21 18:17:45 +0000195static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
Damien Georgecbd2f742014-01-19 11:48:48 +0000196 scope_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
Damien429d7192013-10-04 19:53:11 +0100197 scope->parent = comp->scope_cur;
198 scope->next = NULL;
199 if (comp->scope_head == NULL) {
200 comp->scope_head = scope;
201 } else {
202 scope_t *s = comp->scope_head;
203 while (s->next != NULL) {
204 s = s->next;
205 }
206 s->next = scope;
207 }
208 return scope;
209}
210
Damiend99b0522013-12-21 18:17:45 +0000211static int list_len(mp_parse_node_t pn, int pn_kind) {
212 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100213 return 0;
Damiend99b0522013-12-21 18:17:45 +0000214 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100215 return 1;
216 } else {
Damiend99b0522013-12-21 18:17:45 +0000217 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
218 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100219 return 1;
220 } else {
Damiend99b0522013-12-21 18:17:45 +0000221 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100222 }
223 }
224}
225
Damiend99b0522013-12-21 18:17:45 +0000226static void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, int pn_list_kind, void (*f)(compiler_t*, mp_parse_node_t)) {
227 if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
228 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
229 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100230 for (int i = 0; i < num_nodes; i++) {
231 f(comp, pns->nodes[i]);
232 }
Damiend99b0522013-12-21 18:17:45 +0000233 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100234 f(comp, pn);
235 }
236}
237
Damiend99b0522013-12-21 18:17:45 +0000238static int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
239 if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100240 *nodes = NULL;
241 return 0;
Damiend99b0522013-12-21 18:17:45 +0000242 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100243 *nodes = pn;
244 return 1;
245 } else {
Damiend99b0522013-12-21 18:17:45 +0000246 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
247 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100248 *nodes = pn;
249 return 1;
250 } else {
251 *nodes = pns->nodes;
Damiend99b0522013-12-21 18:17:45 +0000252 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100253 }
254 }
255}
256
Damiend99b0522013-12-21 18:17:45 +0000257void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100258}
259
Damiend99b0522013-12-21 18:17:45 +0000260void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
261 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100262 for (int i = 0; i < num_nodes; i++) {
263 compile_node(comp, pns->nodes[i]);
264 }
265}
266
Damien3ef4abb2013-10-12 16:53:13 +0100267#if MICROPY_EMIT_CPYTHON
Damiend99b0522013-12-21 18:17:45 +0000268static bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
269 if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100270 return false;
271 }
Damiend99b0522013-12-21 18:17:45 +0000272 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +0100273 return false;
274 }
275 return true;
276}
277
Damien02f89412013-12-12 15:13:36 +0000278static void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
Damien George55baff42014-01-21 21:40:13 +0000279 uint len;
280 const byte *str = qstr_data(qstr, &len);
Damien02f89412013-12-12 15:13:36 +0000281 bool has_single_quote = false;
282 bool has_double_quote = false;
283 for (int i = 0; i < len; i++) {
284 if (str[i] == '\'') {
285 has_single_quote = true;
286 } else if (str[i] == '"') {
287 has_double_quote = true;
288 }
289 }
290 if (bytes) {
291 vstr_printf(vstr, "b");
292 }
293 bool quote_single = false;
294 if (has_single_quote && !has_double_quote) {
295 vstr_printf(vstr, "\"");
296 } else {
297 quote_single = true;
298 vstr_printf(vstr, "'");
299 }
300 for (int i = 0; i < len; i++) {
301 if (str[i] == '\n') {
302 vstr_printf(vstr, "\\n");
303 } else if (str[i] == '\\') {
304 vstr_printf(vstr, "\\\\");
305 } else if (str[i] == '\'' && quote_single) {
306 vstr_printf(vstr, "\\'");
307 } else {
308 vstr_printf(vstr, "%c", str[i]);
309 }
310 }
311 if (has_single_quote && !has_double_quote) {
312 vstr_printf(vstr, "\"");
313 } else {
314 vstr_printf(vstr, "'");
315 }
316}
317
Damiend99b0522013-12-21 18:17:45 +0000318static void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
319 assert(MP_PARSE_NODE_IS_LEAF(pn));
320 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
321 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
322 case MP_PARSE_NODE_ID: assert(0);
323 case MP_PARSE_NODE_SMALL_INT: vstr_printf(vstr, "%d", arg); break;
324 case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
325 case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
326 case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
327 case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
328 case MP_PARSE_NODE_TOKEN:
Damien429d7192013-10-04 19:53:11 +0100329 switch (arg) {
Damiend99b0522013-12-21 18:17:45 +0000330 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
331 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
332 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
Damien429d7192013-10-04 19:53:11 +0100333 default: assert(0);
334 }
335 break;
336 default: assert(0);
337 }
338}
339
Damiend99b0522013-12-21 18:17:45 +0000340static void cpython_c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien429d7192013-10-04 19:53:11 +0100341 int n = 0;
342 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000343 n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien429d7192013-10-04 19:53:11 +0100344 }
345 int total = n;
346 bool is_const = true;
Damiend99b0522013-12-21 18:17:45 +0000347 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100348 total += 1;
Damien3a205172013-10-12 15:01:56 +0100349 if (!cpython_c_tuple_is_const(pn)) {
Damien429d7192013-10-04 19:53:11 +0100350 is_const = false;
351 }
352 }
353 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100354 if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien429d7192013-10-04 19:53:11 +0100355 is_const = false;
356 break;
357 }
358 }
359 if (total > 0 && is_const) {
360 bool need_comma = false;
Damien02f89412013-12-12 15:13:36 +0000361 vstr_t *vstr = vstr_new();
362 vstr_printf(vstr, "(");
Damiend99b0522013-12-21 18:17:45 +0000363 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien02f89412013-12-12 15:13:36 +0000364 cpython_c_tuple_emit_const(comp, pn, vstr);
Damien429d7192013-10-04 19:53:11 +0100365 need_comma = true;
366 }
367 for (int i = 0; i < n; i++) {
368 if (need_comma) {
Damien02f89412013-12-12 15:13:36 +0000369 vstr_printf(vstr, ", ");
Damien429d7192013-10-04 19:53:11 +0100370 }
Damien02f89412013-12-12 15:13:36 +0000371 cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien429d7192013-10-04 19:53:11 +0100372 need_comma = true;
373 }
374 if (total == 1) {
Damien02f89412013-12-12 15:13:36 +0000375 vstr_printf(vstr, ",)");
Damien429d7192013-10-04 19:53:11 +0100376 } else {
Damien02f89412013-12-12 15:13:36 +0000377 vstr_printf(vstr, ")");
Damien429d7192013-10-04 19:53:11 +0100378 }
Damien Georgeb9791222014-01-23 00:34:21 +0000379 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +0000380 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +0100381 } else {
Damiend99b0522013-12-21 18:17:45 +0000382 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100383 compile_node(comp, pn);
384 }
385 for (int i = 0; i < n; i++) {
386 compile_node(comp, pns_list->nodes[i]);
387 }
Damien Georgeb9791222014-01-23 00:34:21 +0000388 EMIT_ARG(build_tuple, total);
Damien429d7192013-10-04 19:53:11 +0100389 }
390}
Damien3a205172013-10-12 15:01:56 +0100391#endif
392
393// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
Damiend99b0522013-12-21 18:17:45 +0000394void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3ef4abb2013-10-12 16:53:13 +0100395#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100396 cpython_c_tuple(comp, pn, pns_list);
397#else
398 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000399 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100400 compile_node(comp, pn);
401 total += 1;
402 }
403 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000404 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100405 for (int i = 0; i < n; i++) {
406 compile_node(comp, pns_list->nodes[i]);
407 }
408 total += n;
409 }
Damien Georgeb9791222014-01-23 00:34:21 +0000410 EMIT_ARG(build_tuple, total);
Damien3a205172013-10-12 15:01:56 +0100411#endif
412}
Damien429d7192013-10-04 19:53:11 +0100413
Damiend99b0522013-12-21 18:17:45 +0000414void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100415 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000416 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100417}
418
Damiend99b0522013-12-21 18:17:45 +0000419static bool node_is_const_false(mp_parse_node_t pn) {
420 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
421 // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100422}
423
Damiend99b0522013-12-21 18:17:45 +0000424static bool node_is_const_true(mp_parse_node_t pn) {
425 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100426}
427
Damien3ef4abb2013-10-12 16:53:13 +0100428#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100429// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
Damiend99b0522013-12-21 18:17:45 +0000430static void cpython_c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label, bool is_nested) {
Damien429d7192013-10-04 19:53:11 +0100431 if (node_is_const_false(pn)) {
432 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000433 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100434 }
435 return;
436 } else if (node_is_const_true(pn)) {
437 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000438 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100439 }
440 return;
Damiend99b0522013-12-21 18:17:45 +0000441 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
442 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
443 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
444 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien429d7192013-10-04 19:53:11 +0100445 if (jump_if == false) {
Damienb05d7072013-10-05 13:37:10 +0100446 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100447 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100448 cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien429d7192013-10-04 19:53:11 +0100449 }
Damien3a205172013-10-12 15:01:56 +0100450 cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000451 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100452 } else {
453 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100454 cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100455 }
456 }
457 return;
Damiend99b0522013-12-21 18:17:45 +0000458 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien429d7192013-10-04 19:53:11 +0100459 if (jump_if == false) {
460 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100461 cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100462 }
463 } else {
Damienb05d7072013-10-05 13:37:10 +0100464 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100465 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100466 cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien429d7192013-10-04 19:53:11 +0100467 }
Damien3a205172013-10-12 15:01:56 +0100468 cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000469 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100470 }
471 return;
Damiend99b0522013-12-21 18:17:45 +0000472 } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100473 cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien429d7192013-10-04 19:53:11 +0100474 return;
475 }
476 }
477
478 // nothing special, fall back to default compiling for node and jump
479 compile_node(comp, pn);
480 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000481 EMIT_ARG(pop_jump_if_false, label);
Damien429d7192013-10-04 19:53:11 +0100482 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000483 EMIT_ARG(pop_jump_if_true, label);
Damien429d7192013-10-04 19:53:11 +0100484 }
485}
Damien3a205172013-10-12 15:01:56 +0100486#endif
Damien429d7192013-10-04 19:53:11 +0100487
Damiend99b0522013-12-21 18:17:45 +0000488static void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien3ef4abb2013-10-12 16:53:13 +0100489#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100490 cpython_c_if_cond(comp, pn, jump_if, label, false);
491#else
492 if (node_is_const_false(pn)) {
493 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000494 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100495 }
496 return;
497 } else if (node_is_const_true(pn)) {
498 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000499 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100500 }
501 return;
Damiend99b0522013-12-21 18:17:45 +0000502 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
503 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
504 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
505 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100506 if (jump_if == false) {
507 int label2 = comp_next_label(comp);
508 for (int i = 0; i < n - 1; i++) {
509 c_if_cond(comp, pns->nodes[i], true, label2);
510 }
511 c_if_cond(comp, pns->nodes[n - 1], false, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000512 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100513 } else {
514 for (int i = 0; i < n; i++) {
515 c_if_cond(comp, pns->nodes[i], true, label);
516 }
517 }
518 return;
Damiend99b0522013-12-21 18:17:45 +0000519 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100520 if (jump_if == false) {
521 for (int i = 0; i < n; i++) {
522 c_if_cond(comp, pns->nodes[i], false, label);
523 }
524 } else {
525 int label2 = comp_next_label(comp);
526 for (int i = 0; i < n - 1; i++) {
527 c_if_cond(comp, pns->nodes[i], false, label2);
528 }
529 c_if_cond(comp, pns->nodes[n - 1], true, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000530 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100531 }
532 return;
Damiend99b0522013-12-21 18:17:45 +0000533 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100534 c_if_cond(comp, pns->nodes[0], !jump_if, label);
535 return;
536 }
537 }
538
539 // nothing special, fall back to default compiling for node and jump
540 compile_node(comp, pn);
541 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000542 EMIT_ARG(pop_jump_if_false, label);
Damien3a205172013-10-12 15:01:56 +0100543 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000544 EMIT_ARG(pop_jump_if_true, label);
Damien3a205172013-10-12 15:01:56 +0100545 }
546#endif
Damien429d7192013-10-04 19:53:11 +0100547}
548
549typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damiend99b0522013-12-21 18:17:45 +0000550void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100551
Damiend99b0522013-12-21 18:17:45 +0000552void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100553 if (assign_kind != ASSIGN_AUG_STORE) {
554 compile_node(comp, pns->nodes[0]);
555 }
556
Damiend99b0522013-12-21 18:17:45 +0000557 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
558 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
559 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
560 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100561 if (assign_kind != ASSIGN_AUG_STORE) {
562 for (int i = 0; i < n - 1; i++) {
563 compile_node(comp, pns1->nodes[i]);
564 }
565 }
Damiend99b0522013-12-21 18:17:45 +0000566 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
567 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100568 }
Damiend99b0522013-12-21 18:17:45 +0000569 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +0100570 printf("SyntaxError: can't assign to function call\n");
571 return;
Damiend99b0522013-12-21 18:17:45 +0000572 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100573 if (assign_kind == ASSIGN_AUG_STORE) {
574 EMIT(rot_three);
575 EMIT(store_subscr);
576 } else {
577 compile_node(comp, pns1->nodes[0]);
578 if (assign_kind == ASSIGN_AUG_LOAD) {
579 EMIT(dup_top_two);
Damien Georgeb9791222014-01-23 00:34:21 +0000580 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +0100581 } else {
582 EMIT(store_subscr);
583 }
584 }
Damiend99b0522013-12-21 18:17:45 +0000585 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
586 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100587 if (assign_kind == ASSIGN_AUG_LOAD) {
588 EMIT(dup_top);
Damien Georgeb9791222014-01-23 00:34:21 +0000589 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100590 } else {
591 if (assign_kind == ASSIGN_AUG_STORE) {
592 EMIT(rot_two);
593 }
Damien Georgeb9791222014-01-23 00:34:21 +0000594 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100595 }
596 } else {
597 // shouldn't happen
598 assert(0);
599 }
600 } else {
601 // shouldn't happen
602 assert(0);
603 }
604
Damiend99b0522013-12-21 18:17:45 +0000605 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100606 // SyntaxError, cannot assign
607 assert(0);
608 }
609}
610
Damiend99b0522013-12-21 18:17:45 +0000611void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
Damien429d7192013-10-04 19:53:11 +0100612 assert(n >= 0);
613 int have_star_index = -1;
614 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000615 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) {
Damien429d7192013-10-04 19:53:11 +0100616 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000617 EMIT_ARG(unpack_ex, i, n - i - 1);
Damien429d7192013-10-04 19:53:11 +0100618 have_star_index = i;
619 } else {
620 printf("SyntaxError: two starred expressions in assignment\n");
621 return;
622 }
623 }
624 }
625 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000626 EMIT_ARG(unpack_sequence, n);
Damien429d7192013-10-04 19:53:11 +0100627 }
628 for (int i = 0; i < n; i++) {
629 if (i == have_star_index) {
Damiend99b0522013-12-21 18:17:45 +0000630 c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100631 } else {
632 c_assign(comp, nodes[i], ASSIGN_STORE);
633 }
634 }
635}
636
637// assigns top of stack to pn
Damiend99b0522013-12-21 18:17:45 +0000638void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100639 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +0000640 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100641 assert(0);
Damiend99b0522013-12-21 18:17:45 +0000642 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
643 if (MP_PARSE_NODE_IS_ID(pn)) {
644 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100645 switch (assign_kind) {
646 case ASSIGN_STORE:
647 case ASSIGN_AUG_STORE:
Damien Georgeb9791222014-01-23 00:34:21 +0000648 EMIT_ARG(store_id, arg);
Damien429d7192013-10-04 19:53:11 +0100649 break;
650 case ASSIGN_AUG_LOAD:
Damien Georgeb9791222014-01-23 00:34:21 +0000651 EMIT_ARG(load_id, arg);
Damien429d7192013-10-04 19:53:11 +0100652 break;
653 }
654 } else {
655 printf("SyntaxError: can't assign to literal\n");
656 return;
657 }
658 } else {
Damiend99b0522013-12-21 18:17:45 +0000659 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
660 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +0100661 case PN_power:
662 // lhs is an index or attribute
663 c_assign_power(comp, pns, assign_kind);
664 break;
665
666 case PN_testlist_star_expr:
667 case PN_exprlist:
668 // lhs is a tuple
669 if (assign_kind != ASSIGN_STORE) {
670 goto bad_aug;
671 }
Damiend99b0522013-12-21 18:17:45 +0000672 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100673 break;
674
675 case PN_atom_paren:
676 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000677 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100678 // empty tuple
679 printf("SyntaxError: can't assign to ()\n");
680 return;
Damiend99b0522013-12-21 18:17:45 +0000681 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
682 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100683 goto testlist_comp;
684 } else {
685 // parenthesis around 1 item, is just that item
686 pn = pns->nodes[0];
687 goto tail_recursion;
688 }
689 break;
690
691 case PN_atom_bracket:
692 // lhs is something in brackets
693 if (assign_kind != ASSIGN_STORE) {
694 goto bad_aug;
695 }
Damiend99b0522013-12-21 18:17:45 +0000696 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100697 // empty list, assignment allowed
698 c_assign_tuple(comp, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000699 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
700 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100701 goto testlist_comp;
702 } else {
703 // brackets around 1 item
704 c_assign_tuple(comp, 1, &pns->nodes[0]);
705 }
706 break;
707
708 default:
Damiend99b0522013-12-21 18:17:45 +0000709 printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien429d7192013-10-04 19:53:11 +0100710 assert(0);
711 }
712 return;
713
714 testlist_comp:
715 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000716 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
717 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
718 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100719 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000720 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100721 c_assign_tuple(comp, 1, &pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000722 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100723 // sequence of many items
724 // TODO call c_assign_tuple instead
Damiend99b0522013-12-21 18:17:45 +0000725 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
Damien Georgeb9791222014-01-23 00:34:21 +0000726 EMIT_ARG(unpack_sequence, 1 + n);
Damien429d7192013-10-04 19:53:11 +0100727 c_assign(comp, pns->nodes[0], ASSIGN_STORE);
728 for (int i = 0; i < n; i++) {
729 c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
730 }
Damiend99b0522013-12-21 18:17:45 +0000731 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +0100732 // TODO not implemented
733 assert(0);
734 } else {
735 // sequence with 2 items
736 goto sequence_with_2_items;
737 }
738 } else {
739 // sequence with 2 items
740 sequence_with_2_items:
741 c_assign_tuple(comp, 2, pns->nodes);
742 }
743 return;
744 }
745 return;
746
747 bad_aug:
748 printf("SyntaxError: illegal expression for augmented assignment\n");
749}
750
751// stuff for lambda and comprehensions and generators
752void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
753 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000754 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100755 int nfree = 0;
756 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000757 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
758 id_info_t *id = &comp->scope_cur->id_info[i];
759 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
760 for (int j = 0; j < this_scope->id_info_len; j++) {
761 id_info_t *id2 = &this_scope->id_info[j];
762 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +0000763#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +0000764 EMIT_ARG(load_closure, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000765#else
766 // in Micro Python we load closures using LOAD_FAST
Damien Georgeb9791222014-01-23 00:34:21 +0000767 EMIT_ARG(load_fast, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000768#endif
Damien318aec62013-12-10 18:28:17 +0000769 nfree += 1;
770 }
771 }
Damien429d7192013-10-04 19:53:11 +0100772 }
773 }
774 }
775 if (nfree > 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000776 EMIT_ARG(build_tuple, nfree);
Damien429d7192013-10-04 19:53:11 +0100777 }
778
779 // make the function/closure
780 if (nfree == 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000781 EMIT_ARG(make_function, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100782 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000783 EMIT_ARG(make_closure, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100784 }
785}
786
Damiend99b0522013-12-21 18:17:45 +0000787void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
788 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
789 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
790 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100791 // this parameter has a default value
792 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
793 if (comp->have_bare_star) {
794 comp->param_pass_num_dict_params += 1;
795 if (comp->param_pass == 1) {
Damien Georgeb9791222014-01-23 00:34:21 +0000796 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100797 compile_node(comp, pns->nodes[2]);
798 }
799 } else {
800 comp->param_pass_num_default_params += 1;
801 if (comp->param_pass == 2) {
802 compile_node(comp, pns->nodes[2]);
803 }
804 }
805 }
Damiend99b0522013-12-21 18:17:45 +0000806 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
807 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
808 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100809 // bare star
810 comp->have_bare_star = true;
811 }
812 }
813}
814
815// leaves function object on stack
816// returns function name
Damiend99b0522013-12-21 18:17:45 +0000817qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100818 if (comp->pass == PASS_1) {
819 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000820 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100821 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000822 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100823 }
824
825 // save variables (probably don't need to do this, since we can't have nested definitions..?)
826 bool old_have_bare_star = comp->have_bare_star;
827 int old_param_pass = comp->param_pass;
828 int old_param_pass_num_dict_params = comp->param_pass_num_dict_params;
829 int old_param_pass_num_default_params = comp->param_pass_num_default_params;
830
831 // compile default parameters
832 comp->have_bare_star = false;
833 comp->param_pass = 1; // pass 1 does any default parameters after bare star
834 comp->param_pass_num_dict_params = 0;
835 comp->param_pass_num_default_params = 0;
836 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
837 comp->have_bare_star = false;
838 comp->param_pass = 2; // pass 2 does any default parameters before bare star
839 comp->param_pass_num_dict_params = 0;
840 comp->param_pass_num_default_params = 0;
841 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
842
843 // get the scope for this function
844 scope_t *fscope = (scope_t*)pns->nodes[4];
845
846 // make the function
847 close_over_variables_etc(comp, fscope, comp->param_pass_num_dict_params, comp->param_pass_num_default_params);
848
849 // restore variables
850 comp->have_bare_star = old_have_bare_star;
851 comp->param_pass = old_param_pass;
852 comp->param_pass_num_dict_params = old_param_pass_num_dict_params;
853 comp->param_pass_num_default_params = old_param_pass_num_default_params;
854
855 // return its name (the 'f' in "def f(...):")
856 return fscope->simple_name;
857}
858
859// leaves class object on stack
860// returns class name
Damiend99b0522013-12-21 18:17:45 +0000861qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100862 if (comp->pass == PASS_1) {
863 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000864 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100865 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000866 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100867 }
868
869 EMIT(load_build_class);
870
871 // scope for this class
872 scope_t *cscope = (scope_t*)pns->nodes[3];
873
874 // compile the class
875 close_over_variables_etc(comp, cscope, 0, 0);
876
877 // get its name
Damien Georgeb9791222014-01-23 00:34:21 +0000878 EMIT_ARG(load_const_id, cscope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100879
880 // nodes[1] has parent classes, if any
Damiend99b0522013-12-21 18:17:45 +0000881 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +0100882 // no parent classes
Damien Georgeb9791222014-01-23 00:34:21 +0000883 EMIT_ARG(call_function, 2, 0, false, false);
Damien429d7192013-10-04 19:53:11 +0100884 } else {
885 // have a parent class or classes
886 // TODO what if we have, eg, *a or **a in the parent list?
887 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +0000888 EMIT_ARG(call_function, 2 + list_len(pns->nodes[1], PN_arglist), 0, false, false);
Damien429d7192013-10-04 19:53:11 +0100889 }
890
891 // return its name (the 'C' in class C(...):")
892 return cscope->simple_name;
893}
894
Damien6cdd3af2013-10-05 18:08:26 +0100895// returns true if it was a built-in decorator (even if the built-in had an error)
Damiend99b0522013-12-21 18:17:45 +0000896static bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000897 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100898 return false;
899 }
900
901 if (name_len != 2) {
902 printf("SyntaxError: invalid micropython decorator\n");
903 return true;
904 }
905
Damiend99b0522013-12-21 18:17:45 +0000906 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000907 if (attr == MP_QSTR_byte_code) {
Damien5ac1b2e2013-10-18 19:58:12 +0100908 *emit_options = EMIT_OPT_BYTE_CODE;
Damience89a212013-10-15 22:25:17 +0100909#if MICROPY_EMIT_NATIVE
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000910 } else if (attr == MP_QSTR_native) {
Damien6cdd3af2013-10-05 18:08:26 +0100911 *emit_options = EMIT_OPT_NATIVE_PYTHON;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000912 } else if (attr == MP_QSTR_viper) {
Damien7af3d192013-10-07 00:02:49 +0100913 *emit_options = EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100914#endif
Damien3ef4abb2013-10-12 16:53:13 +0100915#if MICROPY_EMIT_INLINE_THUMB
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000916 } else if (attr == MP_QSTR_asm_thumb) {
Damien5bfb7592013-10-05 18:41:24 +0100917 *emit_options = EMIT_OPT_ASM_THUMB;
Damienc025ebb2013-10-12 14:30:21 +0100918#endif
Damien6cdd3af2013-10-05 18:08:26 +0100919 } else {
Damience89a212013-10-15 22:25:17 +0100920 printf("SyntaxError: invalid micropython decorator '%s'\n", qstr_str(attr));
Damien6cdd3af2013-10-05 18:08:26 +0100921 }
922
923 return true;
924}
925
Damiend99b0522013-12-21 18:17:45 +0000926void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100927 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000928 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +0100929 int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
930
Damien6cdd3af2013-10-05 18:08:26 +0100931 // inherit emit options for this function/class definition
932 uint emit_options = comp->scope_cur->emit_options;
933
934 // compile each decorator
935 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100936 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000937 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
938 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100939
940 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +0000941 mp_parse_node_t *name_nodes;
Damien6cdd3af2013-10-05 18:08:26 +0100942 int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
943
944 // check for built-in decorators
945 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
946 // this was a built-in
947 num_built_in_decorators += 1;
948
949 } else {
950 // not a built-in, compile normally
951
952 // compile the decorator function
953 compile_node(comp, name_nodes[0]);
954 for (int i = 1; i < name_len; i++) {
Damiend99b0522013-12-21 18:17:45 +0000955 assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be
Damien Georgeb9791222014-01-23 00:34:21 +0000956 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i]));
Damien6cdd3af2013-10-05 18:08:26 +0100957 }
958
959 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +0000960 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +0100961 // call the decorator function with the arguments in nodes[1]
962 compile_node(comp, pns_decorator->nodes[1]);
963 }
Damien429d7192013-10-04 19:53:11 +0100964 }
965 }
966
967 // compile the body (funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +0000968 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +0100969 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +0000970 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100971 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Damiend99b0522013-12-21 18:17:45 +0000972 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100973 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +0100974 } else {
975 // shouldn't happen
976 assert(0);
977 }
978
979 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +0100980 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +0000981 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +0100982 }
983
984 // store func/class object into name
Damien Georgeb9791222014-01-23 00:34:21 +0000985 EMIT_ARG(store_id, body_name);
Damien429d7192013-10-04 19:53:11 +0100986}
987
Damiend99b0522013-12-21 18:17:45 +0000988void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +0100989 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +0100990 // store function object into function name
Damien Georgeb9791222014-01-23 00:34:21 +0000991 EMIT_ARG(store_id, fname);
Damien429d7192013-10-04 19:53:11 +0100992}
993
Damiend99b0522013-12-21 18:17:45 +0000994void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
995 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +0000996 EMIT_ARG(delete_id, MP_PARSE_NODE_LEAF_ARG(pn));
Damiend99b0522013-12-21 18:17:45 +0000997 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
998 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +0100999
1000 compile_node(comp, pns->nodes[0]); // base of the power node
1001
Damiend99b0522013-12-21 18:17:45 +00001002 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1003 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1004 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
1005 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001006 for (int i = 0; i < n - 1; i++) {
1007 compile_node(comp, pns1->nodes[i]);
1008 }
Damiend99b0522013-12-21 18:17:45 +00001009 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
1010 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +01001011 }
Damiend99b0522013-12-21 18:17:45 +00001012 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +01001013 // SyntaxError: can't delete a function call
1014 assert(0);
Damiend99b0522013-12-21 18:17:45 +00001015 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +01001016 compile_node(comp, pns1->nodes[0]);
1017 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +00001018 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
1019 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien Georgeb9791222014-01-23 00:34:21 +00001020 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001021 } else {
1022 // shouldn't happen
1023 assert(0);
1024 }
1025 } else {
1026 // shouldn't happen
1027 assert(0);
1028 }
1029
Damiend99b0522013-12-21 18:17:45 +00001030 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001031 // SyntaxError, cannot delete
1032 assert(0);
1033 }
Damiend99b0522013-12-21 18:17:45 +00001034 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
1035 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
1036 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) {
1037 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001038 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
1039
Damiend99b0522013-12-21 18:17:45 +00001040 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1041 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1042 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01001043 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00001044 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001045 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00001046 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01001047 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +00001048 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001049 c_del_stmt(comp, pns->nodes[0]);
1050 for (int i = 0; i < n; i++) {
1051 c_del_stmt(comp, pns1->nodes[i]);
1052 }
Damiend99b0522013-12-21 18:17:45 +00001053 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01001054 // TODO not implemented; can't del comprehension?
1055 assert(0);
1056 } else {
1057 // sequence with 2 items
1058 goto sequence_with_2_items;
1059 }
1060 } else {
1061 // sequence with 2 items
1062 sequence_with_2_items:
1063 c_del_stmt(comp, pns->nodes[0]);
1064 c_del_stmt(comp, pns->nodes[1]);
1065 }
1066 } else {
1067 // tuple with 1 element
1068 c_del_stmt(comp, pn);
1069 }
1070 } else {
1071 // not implemented
1072 assert(0);
1073 }
1074}
1075
Damiend99b0522013-12-21 18:17:45 +00001076void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001077 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
1078}
1079
Damiend99b0522013-12-21 18:17:45 +00001080void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001081 if (comp->break_label == 0) {
1082 printf("ERROR: cannot break from here\n");
1083 }
Damien Georgecbddb272014-02-01 20:08:18 +00001084 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001085}
1086
Damiend99b0522013-12-21 18:17:45 +00001087void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001088 if (comp->continue_label == 0) {
1089 printf("ERROR: cannot continue from here\n");
1090 }
Damien Georgecbddb272014-02-01 20:08:18 +00001091 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001092}
1093
Damiend99b0522013-12-21 18:17:45 +00001094void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +01001095 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
1096 printf("SyntaxError: 'return' outside function\n");
1097 comp->had_error = true;
1098 return;
1099 }
Damiend99b0522013-12-21 18:17:45 +00001100 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001101 // no argument to 'return', so return None
Damien Georgeb9791222014-01-23 00:34:21 +00001102 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damiend99b0522013-12-21 18:17:45 +00001103 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +01001104 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +00001105 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
1106 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001107
Damienb05d7072013-10-05 13:37:10 +01001108 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001109 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1110 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
1111 EMIT(return_value);
Damien Georgeb9791222014-01-23 00:34:21 +00001112 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001113 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1114 } else {
1115 compile_node(comp, pns->nodes[0]);
1116 }
1117 EMIT(return_value);
1118}
1119
Damiend99b0522013-12-21 18:17:45 +00001120void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001121 compile_node(comp, pns->nodes[0]);
1122 EMIT(pop_top);
1123}
1124
Damiend99b0522013-12-21 18:17:45 +00001125void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1126 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001127 // raise
Damien Georgeb9791222014-01-23 00:34:21 +00001128 EMIT_ARG(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001129 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001130 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001131 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001132 compile_node(comp, pns->nodes[0]);
1133 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001134 EMIT_ARG(raise_varargs, 2);
Damien429d7192013-10-04 19:53:11 +01001135 } else {
1136 // raise x
1137 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001138 EMIT_ARG(raise_varargs, 1);
Damien429d7192013-10-04 19:53:11 +01001139 }
1140}
1141
1142// q1 holds the base, q2 the full name
1143// eg a -> q1=q2=a
1144// a.b.c -> q1=a, q2=a.b.c
Damiend99b0522013-12-21 18:17:45 +00001145void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
Damien429d7192013-10-04 19:53:11 +01001146 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001147 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1148 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001149 // a name of the form x as y; unwrap it
Damiend99b0522013-12-21 18:17:45 +00001150 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001151 pn = pns->nodes[0];
1152 is_as = true;
1153 }
Damiend99b0522013-12-21 18:17:45 +00001154 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001155 // just a simple name
Damiend99b0522013-12-21 18:17:45 +00001156 *q2 = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001157 if (!is_as) {
1158 *q1 = *q2;
1159 }
Damien Georgeb9791222014-01-23 00:34:21 +00001160 EMIT_ARG(import_name, *q2);
Damiend99b0522013-12-21 18:17:45 +00001161 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
1162 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
1163 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) {
Damien429d7192013-10-04 19:53:11 +01001164 // a name of the form a.b.c
1165 if (!is_as) {
Damiend99b0522013-12-21 18:17:45 +00001166 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001167 }
Damiend99b0522013-12-21 18:17:45 +00001168 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001169 int len = n - 1;
1170 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00001171 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001172 }
Damien George55baff42014-01-21 21:40:13 +00001173 byte *q_ptr;
1174 byte *str_dest = qstr_build_start(len, &q_ptr);
Damien429d7192013-10-04 19:53:11 +01001175 for (int i = 0; i < n; i++) {
1176 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001177 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001178 }
Damien George55baff42014-01-21 21:40:13 +00001179 uint str_src_len;
1180 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00001181 memcpy(str_dest, str_src, str_src_len);
1182 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001183 }
Damien George55baff42014-01-21 21:40:13 +00001184 *q2 = qstr_build_end(q_ptr);
Damien Georgeb9791222014-01-23 00:34:21 +00001185 EMIT_ARG(import_name, *q2);
Damien429d7192013-10-04 19:53:11 +01001186 if (is_as) {
1187 for (int i = 1; i < n; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001188 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001189 }
1190 }
1191 } else {
1192 // TODO not implemented
1193 assert(0);
1194 }
1195 } else {
1196 // TODO not implemented
1197 assert(0);
1198 }
1199}
1200
Damiend99b0522013-12-21 18:17:45 +00001201void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgeb9791222014-01-23 00:34:21 +00001202 EMIT_ARG(load_const_small_int, 0); // ??
1203 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001204 qstr q1, q2;
1205 do_import_name(comp, pn, &q1, &q2);
Damien Georgeb9791222014-01-23 00:34:21 +00001206 EMIT_ARG(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001207}
1208
Damiend99b0522013-12-21 18:17:45 +00001209void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001210 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1211}
1212
Damiend99b0522013-12-21 18:17:45 +00001213void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1214 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001215 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001216
1217 // build the "fromlist" tuple
1218#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001219 EMIT_ARG(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001220#else
Damien Georgeb9791222014-01-23 00:34:21 +00001221 EMIT_ARG(load_const_str, QSTR_FROM_STR_STATIC("*"), false);
1222 EMIT_ARG(build_tuple, 1);
Damiendb4c3612013-12-10 17:27:24 +00001223#endif
1224
1225 // do the import
Damien429d7192013-10-04 19:53:11 +01001226 qstr dummy_q, id1;
1227 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1228 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001229
Damien429d7192013-10-04 19:53:11 +01001230 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001231 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001232
1233 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001234 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001235 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001236#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001237 {
1238 vstr_t *vstr = vstr_new();
1239 vstr_printf(vstr, "(");
1240 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001241 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1242 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1243 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001244 if (i > 0) {
1245 vstr_printf(vstr, ", ");
1246 }
1247 vstr_printf(vstr, "'");
Damien George55baff42014-01-21 21:40:13 +00001248 uint len;
1249 const byte *str = qstr_data(id2, &len);
1250 vstr_add_strn(vstr, (const char*)str, len);
Damien02f89412013-12-12 15:13:36 +00001251 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001252 }
Damien02f89412013-12-12 15:13:36 +00001253 if (n == 1) {
1254 vstr_printf(vstr, ",");
1255 }
1256 vstr_printf(vstr, ")");
Damien Georgeb9791222014-01-23 00:34:21 +00001257 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001258 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001259 }
Damiendb4c3612013-12-10 17:27:24 +00001260#else
1261 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001262 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1263 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1264 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001265 EMIT_ARG(load_const_str, id2, false);
Damiendb4c3612013-12-10 17:27:24 +00001266 }
Damien Georgeb9791222014-01-23 00:34:21 +00001267 EMIT_ARG(build_tuple, n);
Damiendb4c3612013-12-10 17:27:24 +00001268#endif
1269
1270 // do the import
Damien429d7192013-10-04 19:53:11 +01001271 qstr dummy_q, id1;
1272 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1273 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001274 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1275 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1276 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001277 EMIT_ARG(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001278 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001279 EMIT_ARG(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001280 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001281 EMIT_ARG(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001282 }
1283 }
1284 EMIT(pop_top);
1285 }
1286}
1287
Damiend99b0522013-12-21 18:17:45 +00001288void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001289 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001290 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1291 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001292 } else {
Damiend99b0522013-12-21 18:17:45 +00001293 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1294 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001295 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001296 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001297 }
Damien429d7192013-10-04 19:53:11 +01001298 }
1299 }
1300}
1301
Damiend99b0522013-12-21 18:17:45 +00001302void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001303 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001304 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1305 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001306 } else {
Damiend99b0522013-12-21 18:17:45 +00001307 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1308 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001309 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001310 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001311 }
Damien429d7192013-10-04 19:53:11 +01001312 }
1313 }
1314}
1315
Damiend99b0522013-12-21 18:17:45 +00001316void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001317 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001318 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien Georgeb9791222014-01-23 00:34:21 +00001319 EMIT_ARG(load_global, MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
Damiend99b0522013-12-21 18:17:45 +00001320 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001321 // assertion message
1322 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001323 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001324 }
Damien Georgeb9791222014-01-23 00:34:21 +00001325 EMIT_ARG(raise_varargs, 1);
1326 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001327}
1328
Damiend99b0522013-12-21 18:17:45 +00001329void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001330 // TODO proper and/or short circuiting
1331
Damienb05d7072013-10-05 13:37:10 +01001332 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001333
Damienb05d7072013-10-05 13:37:10 +01001334 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001335 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1336
1337 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001338 //if (!(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))) { // optimisation; doesn't align with CPython
Damien429d7192013-10-04 19:53:11 +01001339 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001340 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001341 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001342 }
1343 //}
Damien Georgeb9791222014-01-23 00:34:21 +00001344 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001345
Damiend99b0522013-12-21 18:17:45 +00001346 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001347 // compile elif blocks
1348
Damiend99b0522013-12-21 18:17:45 +00001349 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001350
Damiend99b0522013-12-21 18:17:45 +00001351 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001352 // multiple elif blocks
1353
Damiend99b0522013-12-21 18:17:45 +00001354 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001355 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001356 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
Damienb05d7072013-10-05 13:37:10 +01001357 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001358 c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition
1359
1360 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001361 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001362 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001363 }
Damien Georgeb9791222014-01-23 00:34:21 +00001364 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001365 }
1366
1367 } else {
1368 // a single elif block
1369
Damienb05d7072013-10-05 13:37:10 +01001370 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001371 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1372
1373 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001374 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001375 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001376 }
Damien Georgeb9791222014-01-23 00:34:21 +00001377 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001378 }
1379 }
1380
1381 // compile else block
1382 compile_node(comp, pns->nodes[3]); // can be null
1383
Damien Georgeb9791222014-01-23 00:34:21 +00001384 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001385}
1386
Damien Georgecbddb272014-02-01 20:08:18 +00001387#define START_BREAK_CONTINUE_BLOCK \
1388 int old_break_label = comp->break_label; \
1389 int old_continue_label = comp->continue_label; \
1390 int break_label = comp_next_label(comp); \
1391 int continue_label = comp_next_label(comp); \
1392 comp->break_label = break_label; \
1393 comp->continue_label = continue_label; \
1394 comp->break_continue_except_level = comp->cur_except_level;
1395
1396#define END_BREAK_CONTINUE_BLOCK \
1397 comp->break_label = old_break_label; \
1398 comp->continue_label = old_continue_label; \
1399 comp->break_continue_except_level = comp->cur_except_level;
1400
Damiend99b0522013-12-21 18:17:45 +00001401void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgecbddb272014-02-01 20:08:18 +00001402 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001403
Damience89a212013-10-15 22:25:17 +01001404 // compared to CPython, we have an optimised version of while loops
1405#if MICROPY_EMIT_CPYTHON
1406 int done_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001407 EMIT_ARG(setup_loop, break_label);
1408 EMIT_ARG(label_assign, continue_label);
Damien429d7192013-10-04 19:53:11 +01001409 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1410 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001411 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001412 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001413 }
Damien Georgeb9791222014-01-23 00:34:21 +00001414 EMIT_ARG(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001415 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1416 // this is a small hack to agree with CPython
1417 if (!node_is_const_true(pns->nodes[0])) {
1418 EMIT(pop_block);
1419 }
Damience89a212013-10-15 22:25:17 +01001420#else
1421 int top_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001422 EMIT_ARG(jump, continue_label);
1423 EMIT_ARG(label_assign, top_label);
Damience89a212013-10-15 22:25:17 +01001424 compile_node(comp, pns->nodes[1]); // body
Damien Georgeb9791222014-01-23 00:34:21 +00001425 EMIT_ARG(label_assign, continue_label);
Damience89a212013-10-15 22:25:17 +01001426 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1427#endif
1428
1429 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001430 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001431
1432 compile_node(comp, pns->nodes[2]); // else
1433
Damien Georgeb9791222014-01-23 00:34:21 +00001434 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001435}
1436
Damienf72fd0e2013-11-06 20:20:49 +00001437// TODO preload end and step onto stack if they are not constants
1438// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001439void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) {
Damien Georgecbddb272014-02-01 20:08:18 +00001440 START_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001441
1442 int top_label = comp_next_label(comp);
Damien George600ae732014-01-21 23:48:04 +00001443 int entry_label = comp_next_label(comp);
Damienf72fd0e2013-11-06 20:20:49 +00001444
1445 // compile: var = start
1446 compile_node(comp, pn_start);
1447 c_assign(comp, pn_var, ASSIGN_STORE);
1448
Damien Georgeb9791222014-01-23 00:34:21 +00001449 EMIT_ARG(jump, entry_label);
1450 EMIT_ARG(label_assign, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001451
Damienf3822fc2013-11-09 20:12:03 +00001452 // compile body
1453 compile_node(comp, pn_body);
1454
Damien Georgeb9791222014-01-23 00:34:21 +00001455 EMIT_ARG(label_assign, continue_label);
Damien George600ae732014-01-21 23:48:04 +00001456
Damienf72fd0e2013-11-06 20:20:49 +00001457 // compile: var += step
1458 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1459 compile_node(comp, pn_step);
Damien Georgeb9791222014-01-23 00:34:21 +00001460 EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_ADD);
Damienf72fd0e2013-11-06 20:20:49 +00001461 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1462
Damien Georgeb9791222014-01-23 00:34:21 +00001463 EMIT_ARG(label_assign, entry_label);
Damienf72fd0e2013-11-06 20:20:49 +00001464
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001465 // compile: if var <cond> end: goto top
Damienf72fd0e2013-11-06 20:20:49 +00001466 compile_node(comp, pn_var);
1467 compile_node(comp, pn_end);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001468 if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001469 EMIT_ARG(binary_op, RT_COMPARE_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001470 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001471 EMIT_ARG(binary_op, RT_COMPARE_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001472 }
Damien Georgeb9791222014-01-23 00:34:21 +00001473 EMIT_ARG(pop_jump_if_true, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001474
1475 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001476 END_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001477
1478 compile_node(comp, pn_else);
1479
Damien Georgeb9791222014-01-23 00:34:21 +00001480 EMIT_ARG(label_assign, break_label);
Damienf72fd0e2013-11-06 20:20:49 +00001481}
1482
Damiend99b0522013-12-21 18:17:45 +00001483void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001484#if !MICROPY_EMIT_CPYTHON
1485 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1486 // this is actually slower, but uses no heap memory
1487 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001488 if (/*comp->scope_cur->emit_options == EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_power)) {
1489 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001490 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1491 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1492 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
1493 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
Damiend99b0522013-12-21 18:17:45 +00001494 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1495 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001496 int n_args = list_get(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001497 mp_parse_node_t pn_range_start;
1498 mp_parse_node_t pn_range_end;
1499 mp_parse_node_t pn_range_step;
1500 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001501 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001502 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001503 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001504 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001505 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001506 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001507 } else if (n_args == 2) {
1508 pn_range_start = args[0];
1509 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001510 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001511 } else {
1512 pn_range_start = args[0];
1513 pn_range_end = args[1];
1514 pn_range_step = args[2];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001515 // We need to know sign of step. This is possible only if it's constant
1516 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
1517 optimize = false;
1518 }
Damienf72fd0e2013-11-06 20:20:49 +00001519 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001520 }
1521 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001522 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1523 return;
1524 }
1525 }
1526 }
1527#endif
1528
Damien Georgecbddb272014-02-01 20:08:18 +00001529 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001530
Damienb05d7072013-10-05 13:37:10 +01001531 int pop_label = comp_next_label(comp);
1532 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001533
Damience89a212013-10-15 22:25:17 +01001534 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1535#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001536 EMIT_ARG(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001537#endif
1538
Damien429d7192013-10-04 19:53:11 +01001539 compile_node(comp, pns->nodes[1]); // iterator
1540 EMIT(get_iter);
Damien Georgecbddb272014-02-01 20:08:18 +00001541 EMIT_ARG(label_assign, continue_label);
Damien Georgeb9791222014-01-23 00:34:21 +00001542 EMIT_ARG(for_iter, pop_label);
Damien429d7192013-10-04 19:53:11 +01001543 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1544 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001545 if (!EMIT(last_emit_was_return_value)) {
Damien Georgecbddb272014-02-01 20:08:18 +00001546 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001547 }
Damien Georgeb9791222014-01-23 00:34:21 +00001548 EMIT_ARG(label_assign, pop_label);
Damien429d7192013-10-04 19:53:11 +01001549 EMIT(for_iter_end);
1550
1551 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001552 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001553
Damience89a212013-10-15 22:25:17 +01001554#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001555 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001556#endif
Damien429d7192013-10-04 19:53:11 +01001557
1558 compile_node(comp, pns->nodes[3]); // else (not tested)
1559
Damien Georgeb9791222014-01-23 00:34:21 +00001560 EMIT_ARG(label_assign, break_label);
1561 EMIT_ARG(label_assign, end_label);
Damien429d7192013-10-04 19:53:11 +01001562}
1563
Damiend99b0522013-12-21 18:17:45 +00001564void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) {
Damien429d7192013-10-04 19:53:11 +01001565 // this function is a bit of a hack at the moment
1566 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1567
1568 // setup code
1569 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001570 int l1 = comp_next_label(comp);
1571 int success_label = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001572
Damien Georgeb9791222014-01-23 00:34:21 +00001573 EMIT_ARG(setup_except, l1);
Damien Georgecbddb272014-02-01 20:08:18 +00001574 comp->cur_except_level += 1;
1575
Damien429d7192013-10-04 19:53:11 +01001576 compile_node(comp, pn_body); // body
1577 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001578 EMIT_ARG(jump, success_label);
1579 EMIT_ARG(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001580 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001581
1582 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001583 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1584 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001585
1586 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001587 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001588
Damiend99b0522013-12-21 18:17:45 +00001589 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001590 // this is a catch all exception handler
1591 if (i + 1 != n_except) {
1592 printf("SyntaxError: default 'except:' must be last\n");
1593 return;
1594 }
1595 } else {
1596 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001597 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1598 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1599 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1600 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001601 // handler binds the exception to a local
1602 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001603 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001604 }
1605 }
1606 EMIT(dup_top);
1607 compile_node(comp, pns_exception_expr);
Damien Georgeb9791222014-01-23 00:34:21 +00001608 EMIT_ARG(binary_op, RT_COMPARE_OP_EXCEPTION_MATCH);
1609 EMIT_ARG(pop_jump_if_false, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001610 }
1611
1612 EMIT(pop_top);
1613
1614 if (qstr_exception_local == 0) {
1615 EMIT(pop_top);
1616 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001617 EMIT_ARG(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001618 }
1619
1620 EMIT(pop_top);
1621
Damiene2880aa2013-12-20 14:22:59 +00001622 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001623 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001624 l3 = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001625 EMIT_ARG(setup_finally, l3);
Damien Georgecbddb272014-02-01 20:08:18 +00001626 comp->cur_except_level += 1;
Damien429d7192013-10-04 19:53:11 +01001627 }
1628 compile_node(comp, pns_except->nodes[1]);
1629 if (qstr_exception_local != 0) {
1630 EMIT(pop_block);
1631 }
1632 EMIT(pop_except);
1633 if (qstr_exception_local != 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001634 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1635 EMIT_ARG(label_assign, l3);
1636 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1637 EMIT_ARG(store_id, qstr_exception_local);
1638 EMIT_ARG(delete_id, qstr_exception_local);
Damien Georgecbddb272014-02-01 20:08:18 +00001639
1640 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001641 EMIT(end_finally);
1642 }
Damien Georgeb9791222014-01-23 00:34:21 +00001643 EMIT_ARG(jump, l2);
1644 EMIT_ARG(label_assign, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001645 }
1646
Damien Georgecbddb272014-02-01 20:08:18 +00001647 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001648 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001649
Damien Georgeb9791222014-01-23 00:34:21 +00001650 EMIT_ARG(label_assign, success_label);
Damien429d7192013-10-04 19:53:11 +01001651 compile_node(comp, pn_else); // else block, can be null
Damien Georgeb9791222014-01-23 00:34:21 +00001652 EMIT_ARG(label_assign, l2);
1653 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001654}
1655
Damiend99b0522013-12-21 18:17:45 +00001656void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) {
Damien429d7192013-10-04 19:53:11 +01001657 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1658 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001659 int l_finally_block = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001660
Damien Georgeb9791222014-01-23 00:34:21 +00001661 EMIT_ARG(setup_finally, l_finally_block);
Damien Georgecbddb272014-02-01 20:08:18 +00001662 comp->cur_except_level += 1;
1663
Damien429d7192013-10-04 19:53:11 +01001664 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001665 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001666 compile_node(comp, pn_body);
1667 } else {
1668 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1669 }
1670 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001671 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1672 EMIT_ARG(label_assign, l_finally_block);
Damien429d7192013-10-04 19:53:11 +01001673 compile_node(comp, pn_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001674
1675 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001676 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001677
Damien Georgeb9791222014-01-23 00:34:21 +00001678 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001679}
1680
Damiend99b0522013-12-21 18:17:45 +00001681void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1682 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1683 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1684 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001685 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001686 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1687 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001688 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001689 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001690 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001691 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001692 // no finally
1693 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1694 } else {
1695 // have finally
Damiend99b0522013-12-21 18:17:45 +00001696 compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((mp_parse_node_struct_t*)pns2->nodes[2])->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001697 }
1698 } else {
1699 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001700 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001701 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001702 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001703 }
1704 } else {
1705 // shouldn't happen
1706 assert(0);
1707 }
1708}
1709
Damiend99b0522013-12-21 18:17:45 +00001710void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) {
Damien429d7192013-10-04 19:53:11 +01001711 if (n == 0) {
1712 // no more pre-bits, compile the body of the with
1713 compile_node(comp, body);
1714 } else {
Damienb05d7072013-10-05 13:37:10 +01001715 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001716 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001717 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001718 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001719 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001720 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001721 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1722 } else {
1723 // this pre-bit is just an expression
1724 compile_node(comp, nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001725 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001726 EMIT(pop_top);
1727 }
1728 // compile additional pre-bits and the body
1729 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1730 // finish this with block
1731 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001732 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1733 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001734 EMIT(with_cleanup);
1735 EMIT(end_finally);
1736 }
1737}
1738
Damiend99b0522013-12-21 18:17:45 +00001739void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001740 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001741 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001742 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1743 assert(n > 0);
1744
1745 // compile in a nested fashion
1746 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1747}
1748
Damiend99b0522013-12-21 18:17:45 +00001749void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1750 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001751 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1752 // for REPL, evaluate then print the expression
Damien Georgeb9791222014-01-23 00:34:21 +00001753 EMIT_ARG(load_id, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001754 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001755 EMIT_ARG(call_function, 1, 0, false, false);
Damien5ac1b2e2013-10-18 19:58:12 +01001756 EMIT(pop_top);
1757
Damien429d7192013-10-04 19:53:11 +01001758 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001759 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001760 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001761 // do nothing with a lonely constant
1762 } else {
1763 compile_node(comp, pns->nodes[0]); // just an expression
1764 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1765 }
Damien429d7192013-10-04 19:53:11 +01001766 }
1767 } else {
Damiend99b0522013-12-21 18:17:45 +00001768 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1769 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001770 if (kind == PN_expr_stmt_augassign) {
1771 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1772 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001773 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001774 // note that we don't really need to implement separate inplace ops, just normal binary ops will suffice
Damiend99b0522013-12-21 18:17:45 +00001775 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001776 case MP_TOKEN_DEL_PIPE_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_OR); break;
1777 case MP_TOKEN_DEL_CARET_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_XOR); break;
1778 case MP_TOKEN_DEL_AMPERSAND_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_AND); break;
1779 case MP_TOKEN_DEL_DBL_LESS_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_LSHIFT); break;
1780 case MP_TOKEN_DEL_DBL_MORE_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_RSHIFT); break;
1781 case MP_TOKEN_DEL_PLUS_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_ADD); break;
1782 case MP_TOKEN_DEL_MINUS_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_SUBTRACT); break;
1783 case MP_TOKEN_DEL_STAR_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_MULTIPLY); break;
1784 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_FLOOR_DIVIDE); break;
1785 case MP_TOKEN_DEL_SLASH_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_TRUE_DIVIDE); break;
1786 case MP_TOKEN_DEL_PERCENT_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_MODULO); break;
1787 case MP_TOKEN_DEL_DBL_STAR_EQUAL: EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_POWER); break;
Damien429d7192013-10-04 19:53:11 +01001788 default: assert(0); // shouldn't happen
1789 }
1790 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1791 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001792 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1793 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001794 // following CPython, we store left-most first
1795 if (rhs > 0) {
1796 EMIT(dup_top);
1797 }
1798 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1799 for (int i = 0; i < rhs; i++) {
1800 if (i + 1 < rhs) {
1801 EMIT(dup_top);
1802 }
Damiend99b0522013-12-21 18:17:45 +00001803 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001804 }
1805 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001806 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1807 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1808 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1809 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001810 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001811 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1812 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001813 compile_node(comp, pns10->nodes[0]); // rhs
1814 compile_node(comp, pns10->nodes[1]); // rhs
1815 EMIT(rot_two);
1816 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1817 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001818 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1819 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1820 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1821 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001822 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001823 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1824 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001825 compile_node(comp, pns10->nodes[0]); // rhs
1826 compile_node(comp, pns10->nodes[1]); // rhs
1827 compile_node(comp, pns10->nodes[2]); // rhs
1828 EMIT(rot_three);
1829 EMIT(rot_two);
1830 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1831 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1832 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1833 } else {
1834 compile_node(comp, pns1->nodes[0]); // rhs
1835 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1836 }
1837 } else {
1838 // shouldn't happen
1839 assert(0);
1840 }
1841 }
1842}
1843
Damiend99b0522013-12-21 18:17:45 +00001844void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1845 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001846 compile_node(comp, pns->nodes[0]);
1847 for (int i = 1; i < num_nodes; i += 1) {
1848 compile_node(comp, pns->nodes[i]);
Damien Georgeb9791222014-01-23 00:34:21 +00001849 EMIT_ARG(binary_op, binary_op);
Damien429d7192013-10-04 19:53:11 +01001850 }
1851}
1852
Damiend99b0522013-12-21 18:17:45 +00001853void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1854 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1855 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001856
1857 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001858 int l_fail = comp_next_label(comp);
1859 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001860 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1861 compile_node(comp, pns->nodes[0]); // success value
Damien Georgeb9791222014-01-23 00:34:21 +00001862 EMIT_ARG(jump, l_end);
1863 EMIT_ARG(label_assign, l_fail);
1864 EMIT_ARG(set_stack_size, stack_size); // force stack size reset
Damien429d7192013-10-04 19:53:11 +01001865 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
Damien Georgeb9791222014-01-23 00:34:21 +00001866 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001867}
1868
Damiend99b0522013-12-21 18:17:45 +00001869void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001870 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001871 //mp_parse_node_t pn_params = pns->nodes[0];
1872 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001873
1874 if (comp->pass == PASS_1) {
1875 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001876 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 +01001877 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001878 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001879 }
1880
1881 // get the scope for this lambda
1882 scope_t *this_scope = (scope_t*)pns->nodes[2];
1883
1884 // make the lambda
1885 close_over_variables_etc(comp, this_scope, 0, 0);
1886}
1887
Damiend99b0522013-12-21 18:17:45 +00001888void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001889 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001890 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001891 for (int i = 0; i < n; i += 1) {
1892 compile_node(comp, pns->nodes[i]);
1893 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001894 EMIT_ARG(jump_if_true_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001895 }
1896 }
Damien Georgeb9791222014-01-23 00:34:21 +00001897 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001898}
1899
Damiend99b0522013-12-21 18:17:45 +00001900void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001901 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001902 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001903 for (int i = 0; i < n; i += 1) {
1904 compile_node(comp, pns->nodes[i]);
1905 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001906 EMIT_ARG(jump_if_false_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001907 }
1908 }
Damien Georgeb9791222014-01-23 00:34:21 +00001909 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001910}
1911
Damiend99b0522013-12-21 18:17:45 +00001912void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001913 compile_node(comp, pns->nodes[0]);
Damien Georgee4b6a072014-01-28 23:27:35 +00001914#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001915 EMIT_ARG(unary_op, RT_UNARY_OP_NOT);
Damien Georgee4b6a072014-01-28 23:27:35 +00001916#else
1917 // eliminate use of NOT byte code
1918 int l_load_false = comp_next_label(comp);
1919 int l_done = comp_next_label(comp);
1920 int stack_size = EMIT(get_stack_size);
1921 EMIT_ARG(pop_jump_if_true, l_load_false);
1922 EMIT_ARG(load_const_tok, MP_TOKEN_KW_TRUE);
1923 EMIT_ARG(jump, l_done);
1924 EMIT_ARG(label_assign, l_load_false);
1925 EMIT_ARG(load_const_tok, MP_TOKEN_KW_FALSE);
1926 EMIT_ARG(label_assign, l_done);
1927 EMIT_ARG(set_stack_size, stack_size); // force stack size since it counts 1 pop and 2 pushes statically, but really it's 1 pop and 1 push dynamically
1928#endif
Damien429d7192013-10-04 19:53:11 +01001929}
1930
Damiend99b0522013-12-21 18:17:45 +00001931void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001932 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001933 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001934 compile_node(comp, pns->nodes[0]);
1935 bool multi = (num_nodes > 3);
1936 int l_fail = 0;
1937 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001938 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001939 }
1940 for (int i = 1; i + 1 < num_nodes; i += 2) {
1941 compile_node(comp, pns->nodes[i + 1]);
1942 if (i + 2 < num_nodes) {
1943 EMIT(dup_top);
1944 EMIT(rot_three);
1945 }
Damiend99b0522013-12-21 18:17:45 +00001946 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001947 EMIT_ARG(binary_op, RT_COMPARE_OP_LESS);
Damiend99b0522013-12-21 18:17:45 +00001948 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001949 EMIT_ARG(binary_op, RT_COMPARE_OP_MORE);
Damiend99b0522013-12-21 18:17:45 +00001950 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_EQUAL)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001951 EMIT_ARG(binary_op, RT_COMPARE_OP_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001952 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_LESS_EQUAL)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001953 EMIT_ARG(binary_op, RT_COMPARE_OP_LESS_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001954 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MORE_EQUAL)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001955 EMIT_ARG(binary_op, RT_COMPARE_OP_MORE_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001956 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_NOT_EQUAL)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001957 EMIT_ARG(binary_op, RT_COMPARE_OP_NOT_EQUAL);
Damiend99b0522013-12-21 18:17:45 +00001958 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_KW_IN)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001959 EMIT_ARG(binary_op, RT_COMPARE_OP_IN);
Damiend99b0522013-12-21 18:17:45 +00001960 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
1961 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
1962 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01001963 if (kind == PN_comp_op_not_in) {
Damien Georgeb9791222014-01-23 00:34:21 +00001964 EMIT_ARG(binary_op, RT_COMPARE_OP_NOT_IN);
Damien429d7192013-10-04 19:53:11 +01001965 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00001966 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001967 EMIT_ARG(binary_op, RT_COMPARE_OP_IS);
Damien429d7192013-10-04 19:53:11 +01001968 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001969 EMIT_ARG(binary_op, RT_COMPARE_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01001970 }
1971 } else {
1972 // shouldn't happen
1973 assert(0);
1974 }
1975 } else {
1976 // shouldn't happen
1977 assert(0);
1978 }
1979 if (i + 2 < num_nodes) {
Damien Georgeb9791222014-01-23 00:34:21 +00001980 EMIT_ARG(jump_if_false_or_pop, l_fail);
Damien429d7192013-10-04 19:53:11 +01001981 }
1982 }
1983 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001984 int l_end = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001985 EMIT_ARG(jump, l_end);
1986 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001987 EMIT(rot_two);
1988 EMIT(pop_top);
Damien Georgeb9791222014-01-23 00:34:21 +00001989 EMIT_ARG(label_assign, l_end);
1990 EMIT_ARG(set_stack_size, stack_size + 1); // force stack size
Damien429d7192013-10-04 19:53:11 +01001991 }
1992}
1993
Damiend99b0522013-12-21 18:17:45 +00001994void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001995 // TODO
1996 assert(0);
1997 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001998 //EMIT_ARG(unary_op, "UNARY_STAR");
Damien429d7192013-10-04 19:53:11 +01001999}
2000
Damiend99b0522013-12-21 18:17:45 +00002001void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002002 c_binary_op(comp, pns, RT_BINARY_OP_OR);
2003}
2004
Damiend99b0522013-12-21 18:17:45 +00002005void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002006 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
2007}
2008
Damiend99b0522013-12-21 18:17:45 +00002009void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002010 c_binary_op(comp, pns, RT_BINARY_OP_AND);
2011}
2012
Damiend99b0522013-12-21 18:17:45 +00002013void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2014 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002015 compile_node(comp, pns->nodes[0]);
2016 for (int i = 1; i + 1 < num_nodes; i += 2) {
2017 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002018 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002019 EMIT_ARG(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00002020 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002021 EMIT_ARG(binary_op, RT_BINARY_OP_RSHIFT);
Damien429d7192013-10-04 19:53:11 +01002022 } else {
2023 // shouldn't happen
2024 assert(0);
2025 }
2026 }
2027}
2028
Damiend99b0522013-12-21 18:17:45 +00002029void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2030 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002031 compile_node(comp, pns->nodes[0]);
2032 for (int i = 1; i + 1 < num_nodes; i += 2) {
2033 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002034 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002035 EMIT_ARG(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002036 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002037 EMIT_ARG(binary_op, RT_BINARY_OP_SUBTRACT);
Damien429d7192013-10-04 19:53:11 +01002038 } else {
2039 // shouldn't happen
2040 assert(0);
2041 }
2042 }
2043}
2044
Damiend99b0522013-12-21 18:17:45 +00002045void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2046 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002047 compile_node(comp, pns->nodes[0]);
2048 for (int i = 1; i + 1 < num_nodes; i += 2) {
2049 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002050 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002051 EMIT_ARG(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002052 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002053 EMIT_ARG(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002054 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002055 EMIT_ARG(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002056 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002057 EMIT_ARG(binary_op, RT_BINARY_OP_MODULO);
Damien429d7192013-10-04 19:53:11 +01002058 } else {
2059 // shouldn't happen
2060 assert(0);
2061 }
2062 }
2063}
2064
Damiend99b0522013-12-21 18:17:45 +00002065void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002066 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002067 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002068 EMIT_ARG(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002069 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002070 EMIT_ARG(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002071 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002072 EMIT_ARG(unary_op, RT_UNARY_OP_INVERT);
Damien429d7192013-10-04 19:53:11 +01002073 } else {
2074 // shouldn't happen
2075 assert(0);
2076 }
2077}
2078
Damiend99b0522013-12-21 18:17:45 +00002079void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool is_method_call) {
Damien429d7192013-10-04 19:53:11 +01002080 // function to call is on top of stack
2081
2082 int old_n_arg_keyword = comp->n_arg_keyword;
2083 bool old_have_star_arg = comp->have_star_arg;
2084 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2085 comp->n_arg_keyword = 0;
2086 comp->have_star_arg = false;
2087 comp->have_dbl_star_arg = false;
2088
2089 compile_node(comp, pns->nodes[0]); // arguments to function call; can be null
2090
2091 // compute number of positional arguments
2092 int n_positional = list_len(pns->nodes[0], PN_arglist) - comp->n_arg_keyword;
2093 if (comp->have_star_arg) {
2094 n_positional -= 1;
2095 }
2096 if (comp->have_dbl_star_arg) {
2097 n_positional -= 1;
2098 }
2099
2100 if (is_method_call) {
Damien Georgeb9791222014-01-23 00:34:21 +00002101 EMIT_ARG(call_method, n_positional, comp->n_arg_keyword, comp->have_star_arg, comp->have_dbl_star_arg);
Damien429d7192013-10-04 19:53:11 +01002102 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002103 EMIT_ARG(call_function, n_positional, comp->n_arg_keyword, comp->have_star_arg, comp->have_dbl_star_arg);
Damien429d7192013-10-04 19:53:11 +01002104 }
2105
2106 comp->n_arg_keyword = old_n_arg_keyword;
2107 comp->have_star_arg = old_have_star_arg;
2108 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2109}
2110
Damiend99b0522013-12-21 18:17:45 +00002111void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2112 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002113 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002114 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 +01002115 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002116 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2117 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
Damien Georgeb9791222014-01-23 00:34:21 +00002118 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien429d7192013-10-04 19:53:11 +01002119 compile_trailer_paren_helper(comp, pns_paren, true);
2120 i += 1;
2121 } else {
2122 compile_node(comp, pns->nodes[i]);
2123 }
2124 }
2125}
2126
Damiend99b0522013-12-21 18:17:45 +00002127void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002128 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002129 EMIT_ARG(binary_op, RT_BINARY_OP_POWER);
Damien429d7192013-10-04 19:53:11 +01002130}
2131
Damiend99b0522013-12-21 18:17:45 +00002132void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002133 // a list of strings
Damien63321742013-12-10 17:41:49 +00002134
2135 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002136 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002137 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002138 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002139 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002140 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2141 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2142 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002143 if (i == 0) {
2144 string_kind = pn_kind;
2145 } else if (pn_kind != string_kind) {
2146 printf("SyntaxError: cannot mix bytes and nonbytes literals\n");
2147 return;
2148 }
Damien George55baff42014-01-21 21:40:13 +00002149 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01002150 }
Damien63321742013-12-10 17:41:49 +00002151
Damien63321742013-12-10 17:41:49 +00002152 // concatenate string/bytes
Damien George55baff42014-01-21 21:40:13 +00002153 byte *q_ptr;
2154 byte *s_dest = qstr_build_start(n_bytes, &q_ptr);
Damien63321742013-12-10 17:41:49 +00002155 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00002156 uint s_len;
2157 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00002158 memcpy(s_dest, s, s_len);
2159 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002160 }
Damien George55baff42014-01-21 21:40:13 +00002161 qstr q = qstr_build_end(q_ptr);
Damien63321742013-12-10 17:41:49 +00002162
Damien Georgeb9791222014-01-23 00:34:21 +00002163 EMIT_ARG(load_const_str, q, string_kind == MP_PARSE_NODE_BYTES);
Damien429d7192013-10-04 19:53:11 +01002164}
2165
2166// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002167void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2168 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2169 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2170 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002171
2172 if (comp->pass == PASS_1) {
2173 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002174 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 +01002175 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002176 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002177 }
2178
2179 // get the scope for this comprehension
2180 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2181
2182 // compile the comprehension
2183 close_over_variables_etc(comp, this_scope, 0, 0);
2184
2185 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2186 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002187 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01002188}
2189
Damiend99b0522013-12-21 18:17:45 +00002190void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2191 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002192 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002193 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2194 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2195 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2196 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2197 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2198 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2199 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002200 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002201 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002202 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002203 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002204 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002205 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002206 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002207 // generator expression
2208 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2209 } else {
2210 // tuple with 2 items
2211 goto tuple_with_2_items;
2212 }
2213 } else {
2214 // tuple with 2 items
2215 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002216 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002217 }
2218 } else {
2219 // parenthesis around a single item, is just that item
2220 compile_node(comp, pns->nodes[0]);
2221 }
2222}
2223
Damiend99b0522013-12-21 18:17:45 +00002224void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2225 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002226 // empty list
Damien Georgeb9791222014-01-23 00:34:21 +00002227 EMIT_ARG(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002228 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2229 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2230 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2231 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2232 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002233 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002234 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002235 compile_node(comp, pns2->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002236 EMIT_ARG(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002237 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002238 // list of many items
2239 compile_node(comp, pns2->nodes[0]);
2240 compile_generic_all_nodes(comp, pns3);
Damien Georgeb9791222014-01-23 00:34:21 +00002241 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
Damiend99b0522013-12-21 18:17:45 +00002242 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002243 // list comprehension
2244 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2245 } else {
2246 // list with 2 items
2247 goto list_with_2_items;
2248 }
2249 } else {
2250 // list with 2 items
2251 list_with_2_items:
2252 compile_node(comp, pns2->nodes[0]);
2253 compile_node(comp, pns2->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00002254 EMIT_ARG(build_list, 2);
Damien429d7192013-10-04 19:53:11 +01002255 }
2256 } else {
2257 // list with 1 item
2258 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002259 EMIT_ARG(build_list, 1);
Damien429d7192013-10-04 19:53:11 +01002260 }
2261}
2262
Damiend99b0522013-12-21 18:17:45 +00002263void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2264 mp_parse_node_t pn = pns->nodes[0];
2265 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002266 // empty dict
Damien Georgeb9791222014-01-23 00:34:21 +00002267 EMIT_ARG(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002268 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2269 pns = (mp_parse_node_struct_t*)pn;
2270 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002271 // dict with one element
Damien Georgeb9791222014-01-23 00:34:21 +00002272 EMIT_ARG(build_map, 1);
Damien429d7192013-10-04 19:53:11 +01002273 compile_node(comp, pn);
2274 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002275 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2276 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2277 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2278 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002279 // dict/set with multiple elements
2280
2281 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002282 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002283 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2284
2285 // first element sets whether it's a dict or set
2286 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002287 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002288 // a dictionary
Damien Georgeb9791222014-01-23 00:34:21 +00002289 EMIT_ARG(build_map, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002290 compile_node(comp, pns->nodes[0]);
2291 EMIT(store_map);
2292 is_dict = true;
2293 } else {
2294 // a set
2295 compile_node(comp, pns->nodes[0]); // 1st value of set
2296 is_dict = false;
2297 }
2298
2299 // process rest of elements
2300 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002301 mp_parse_node_t pn = nodes[i];
2302 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002303 compile_node(comp, pn);
2304 if (is_dict) {
2305 if (!is_key_value) {
2306 printf("SyntaxError?: expecting key:value for dictionary");
2307 return;
2308 }
2309 EMIT(store_map);
2310 } else {
2311 if (is_key_value) {
2312 printf("SyntaxError?: expecting just a value for set");
2313 return;
2314 }
2315 }
2316 }
2317
2318 // if it's a set, build it
2319 if (!is_dict) {
Damien Georgeb9791222014-01-23 00:34:21 +00002320 EMIT_ARG(build_set, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002321 }
Damiend99b0522013-12-21 18:17:45 +00002322 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002323 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002324 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002325 // a dictionary comprehension
2326 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2327 } else {
2328 // a set comprehension
2329 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2330 }
2331 } else {
2332 // shouldn't happen
2333 assert(0);
2334 }
2335 } else {
2336 // set with one element
2337 goto set_with_one_element;
2338 }
2339 } else {
2340 // set with one element
2341 set_with_one_element:
2342 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002343 EMIT_ARG(build_set, 1);
Damien429d7192013-10-04 19:53:11 +01002344 }
2345}
2346
Damiend99b0522013-12-21 18:17:45 +00002347void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002348 compile_trailer_paren_helper(comp, pns, false);
2349}
2350
Damiend99b0522013-12-21 18:17:45 +00002351void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002352 // object who's index we want is on top of stack
2353 compile_node(comp, pns->nodes[0]); // the index
Damien Georgeb9791222014-01-23 00:34:21 +00002354 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +01002355}
2356
Damiend99b0522013-12-21 18:17:45 +00002357void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002358 // object who's attribute we want is on top of stack
Damien Georgeb9791222014-01-23 00:34:21 +00002359 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002360}
2361
Damiend99b0522013-12-21 18:17:45 +00002362void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2363 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2364 mp_parse_node_t pn = pns->nodes[0];
2365 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002366 // [?:]
Damien Georgeb9791222014-01-23 00:34:21 +00002367 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
2368 EMIT_ARG(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002369 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2370 pns = (mp_parse_node_struct_t*)pn;
2371 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
Damien Georgeb9791222014-01-23 00:34:21 +00002372 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002373 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002374 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002375 // [?::]
Damien Georgeb9791222014-01-23 00:34:21 +00002376 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002377 } else {
2378 // [?::x]
2379 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002380 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002381 }
Damiend99b0522013-12-21 18:17:45 +00002382 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002383 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002384 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2385 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2386 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2387 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002388 // [?:x:]
Damien Georgeb9791222014-01-23 00:34:21 +00002389 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002390 } else {
2391 // [?:x:x]
2392 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002393 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002394 }
2395 } else {
2396 // [?:x]
2397 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002398 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002399 }
2400 } else {
2401 // [?:x]
2402 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002403 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002404 }
2405}
2406
Damiend99b0522013-12-21 18:17:45 +00002407void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002408 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002409 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2410 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002411}
2412
Damiend99b0522013-12-21 18:17:45 +00002413void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgeb9791222014-01-23 00:34:21 +00002414 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002415 compile_subscript_3_helper(comp, pns);
2416}
2417
Damiend99b0522013-12-21 18:17:45 +00002418void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002419 // if this is called then we are compiling a dict key:value pair
2420 compile_node(comp, pns->nodes[1]); // value
2421 compile_node(comp, pns->nodes[0]); // key
2422}
2423
Damiend99b0522013-12-21 18:17:45 +00002424void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002425 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002426 // store class object into class name
Damien Georgeb9791222014-01-23 00:34:21 +00002427 EMIT_ARG(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002428}
2429
Damiend99b0522013-12-21 18:17:45 +00002430void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002431 if (comp->have_star_arg) {
2432 printf("SyntaxError?: can't have multiple *x\n");
2433 return;
2434 }
2435 comp->have_star_arg = true;
2436 compile_node(comp, pns->nodes[0]);
2437}
2438
Damiend99b0522013-12-21 18:17:45 +00002439void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002440 if (comp->have_dbl_star_arg) {
2441 printf("SyntaxError?: can't have multiple **x\n");
2442 return;
2443 }
2444 comp->have_dbl_star_arg = true;
2445 compile_node(comp, pns->nodes[0]);
2446}
2447
Damiend99b0522013-12-21 18:17:45 +00002448void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2449 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2450 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2451 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2452 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002453 printf("SyntaxError?: lhs of keyword argument must be an id\n");
2454 return;
2455 }
Damien Georgeb9791222014-01-23 00:34:21 +00002456 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002457 compile_node(comp, pns2->nodes[0]);
2458 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002459 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002460 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2461 } else {
2462 // shouldn't happen
2463 assert(0);
2464 }
2465}
2466
Damiend99b0522013-12-21 18:17:45 +00002467void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002468 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
2469 printf("SyntaxError: 'yield' outside function\n");
2470 return;
2471 }
Damiend99b0522013-12-21 18:17:45 +00002472 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00002473 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002474 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002475 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2476 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002477 compile_node(comp, pns->nodes[0]);
2478 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002479 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002480 EMIT(yield_from);
2481 } else {
2482 compile_node(comp, pns->nodes[0]);
2483 EMIT(yield_value);
2484 }
2485}
2486
Damiend99b0522013-12-21 18:17:45 +00002487typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Damien429d7192013-10-04 19:53:11 +01002488static compile_function_t compile_function[] = {
2489 NULL,
2490#define nc NULL
2491#define c(f) compile_##f
2492#define DEF_RULE(rule, comp, kind, arg...) comp,
2493#include "grammar.h"
2494#undef nc
2495#undef c
2496#undef DEF_RULE
2497};
2498
Damiend99b0522013-12-21 18:17:45 +00002499void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2500 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002501 // pass
Damiend99b0522013-12-21 18:17:45 +00002502 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien George08d07552014-01-29 18:58:52 +00002503 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +00002504 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002505 case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
2506 case MP_PARSE_NODE_SMALL_INT: EMIT_ARG(load_const_small_int, arg); break;
2507 case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
2508 case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
2509 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
2510 case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
Damiend99b0522013-12-21 18:17:45 +00002511 case MP_PARSE_NODE_TOKEN:
2512 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002513 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002514 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002515 // do nothing
2516 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002517 EMIT_ARG(load_const_tok, arg);
Damien91d387d2013-10-09 15:09:52 +01002518 }
2519 break;
Damien429d7192013-10-04 19:53:11 +01002520 default: assert(0);
2521 }
2522 } else {
Damiend99b0522013-12-21 18:17:45 +00002523 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien Georgeb9791222014-01-23 00:34:21 +00002524 EMIT_ARG(set_line_number, pns->source_line);
Damiend99b0522013-12-21 18:17:45 +00002525 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002526 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002527 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien Georgecbd2f742014-01-19 11:48:48 +00002528#if MICROPY_DEBUG_PRINTERS
2529 mp_parse_node_print(pn, 0);
2530#endif
Damien429d7192013-10-04 19:53:11 +01002531 assert(0);
2532 } else {
2533 f(comp, pns);
2534 }
2535 }
2536}
2537
Damiend99b0522013-12-21 18:17:45 +00002538void 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 +01002539 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002540 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002541 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2542 if (MP_PARSE_NODE_IS_ID(pn)) {
2543 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002544 if (comp->have_bare_star) {
2545 // comes after a bare star, so doesn't count as a parameter
2546 } else {
2547 comp->scope_cur->num_params += 1;
2548 }
Damienb14de212013-10-06 00:28:28 +01002549 } else {
Damiend99b0522013-12-21 18:17:45 +00002550 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2551 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2552 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2553 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002554 //int node_index = 1; unused
2555 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002556 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002557 // this parameter has an annotation
2558 pn_annotation = pns->nodes[1];
2559 }
2560 //node_index = 2; unused
2561 }
2562 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002563 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002564 // this parameter has a default value
2565 if (comp->have_bare_star) {
2566 comp->scope_cur->num_dict_params += 1;
2567 } else {
2568 comp->scope_cur->num_default_params += 1;
2569 }
2570 }
2571 */
2572 if (comp->have_bare_star) {
2573 // comes after a bare star, so doesn't count as a parameter
2574 } else {
2575 comp->scope_cur->num_params += 1;
2576 }
Damiend99b0522013-12-21 18:17:45 +00002577 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2578 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002579 // bare star
2580 // TODO see http://www.python.org/dev/peps/pep-3102/
2581 comp->have_bare_star = true;
2582 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002583 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002584 // named star
2585 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002586 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2587 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002588 // named star with annotation
2589 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002590 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2591 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002592 pn_annotation = pns->nodes[1];
2593 } else {
2594 // shouldn't happen
2595 assert(0);
2596 }
Damiend99b0522013-12-21 18:17:45 +00002597 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2598 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2599 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002600 // this parameter has an annotation
2601 pn_annotation = pns->nodes[1];
2602 }
2603 comp->scope_cur->flags |= SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002604 } else {
Damienb14de212013-10-06 00:28:28 +01002605 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002606 assert(0);
2607 }
Damien429d7192013-10-04 19:53:11 +01002608 }
2609
2610 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002611 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002612 // TODO this parameter has an annotation
2613 }
2614 bool added;
2615 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2616 if (!added) {
2617 printf("SyntaxError?: same name used for parameter; %s\n", qstr_str(param_name));
2618 return;
2619 }
2620 id_info->param = true;
2621 id_info->kind = ID_INFO_KIND_LOCAL;
2622 }
2623}
2624
Damiend99b0522013-12-21 18:17:45 +00002625void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002626 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2627}
2628
Damiend99b0522013-12-21 18:17:45 +00002629void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002630 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2631}
2632
Damiend99b0522013-12-21 18:17:45 +00002633void 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 +01002634 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002635 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002636 // no more nested if/for; compile inner expression
2637 compile_node(comp, pn_inner_expr);
2638 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002639 EMIT_ARG(list_append, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002640 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002641 EMIT_ARG(map_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002642 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002643 EMIT_ARG(set_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002644 } else {
2645 EMIT(yield_value);
2646 EMIT(pop_top);
2647 }
Damiend99b0522013-12-21 18:17:45 +00002648 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002649 // if condition
Damiend99b0522013-12-21 18:17:45 +00002650 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002651 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2652 pn_iter = pns_comp_if->nodes[1];
2653 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002654 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002655 // for loop
Damiend99b0522013-12-21 18:17:45 +00002656 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002657 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002658 int l_end2 = comp_next_label(comp);
2659 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002660 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002661 EMIT_ARG(label_assign, l_top2);
2662 EMIT_ARG(for_iter, l_end2);
Damien429d7192013-10-04 19:53:11 +01002663 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2664 compile_scope_comp_iter(comp, pns_comp_for2->nodes[2], pn_inner_expr, l_top2, for_depth + 1);
Damien Georgeb9791222014-01-23 00:34:21 +00002665 EMIT_ARG(jump, l_top2);
2666 EMIT_ARG(label_assign, l_end2);
Damien429d7192013-10-04 19:53:11 +01002667 EMIT(for_iter_end);
2668 } else {
2669 // shouldn't happen
2670 assert(0);
2671 }
2672}
2673
Damiend99b0522013-12-21 18:17:45 +00002674void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002675 // see http://www.python.org/dev/peps/pep-0257/
2676
2677 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002678 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002679 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002680 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002681 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002682 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2683 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002684 for (int i = 0; i < num_nodes; i++) {
2685 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002686 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 +00002687 // not a newline, so this is the first statement; finish search
2688 break;
2689 }
2690 }
2691 // 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 +00002692 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002693 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002694 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002695 } else {
2696 return;
2697 }
2698
2699 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002700 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2701 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2702 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2703 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2704 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002705 compile_node(comp, pns->nodes[0]); // a doc string
2706 // store doc string
Damien Georgeb9791222014-01-23 00:34:21 +00002707 EMIT_ARG(store_id, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002708 }
2709 }
2710 }
2711}
2712
2713void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2714 comp->pass = pass;
2715 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002716 comp->next_label = 1;
Damien Georgeb9791222014-01-23 00:34:21 +00002717 EMIT_ARG(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002718
2719 if (comp->pass == PASS_1) {
2720 scope->stack_size = 0;
2721 }
2722
Damien5ac1b2e2013-10-18 19:58:12 +01002723#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002724 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002725 scope_print_info(scope);
2726 }
Damien5ac1b2e2013-10-18 19:58:12 +01002727#endif
Damien429d7192013-10-04 19:53:11 +01002728
2729 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002730 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2731 assert(scope->kind == SCOPE_MODULE);
2732 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2733 compile_node(comp, pns->nodes[0]); // compile the expression
2734 EMIT(return_value);
2735 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002736 if (!comp->is_repl) {
2737 check_for_doc_string(comp, scope->pn);
2738 }
Damien429d7192013-10-04 19:53:11 +01002739 compile_node(comp, scope->pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002740 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002741 EMIT(return_value);
2742 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002743 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2744 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2745 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002746
2747 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002748 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002749 if (comp->pass == PASS_1) {
2750 comp->have_bare_star = false;
2751 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2752 }
2753
Damiend99b0522013-12-21 18:17:45 +00002754 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // 2 is something...
Damien429d7192013-10-04 19:53:11 +01002755
2756 compile_node(comp, pns->nodes[3]); // 3 is function body
2757 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002758 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002759 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002760 EMIT(return_value);
2761 }
2762 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002763 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2764 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2765 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002766
2767 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002768 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002769 if (comp->pass == PASS_1) {
2770 comp->have_bare_star = false;
2771 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2772 }
2773
2774 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2775 EMIT(return_value);
2776 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2777 // a bit of a hack at the moment
2778
Damiend99b0522013-12-21 18:17:45 +00002779 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2780 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2781 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2782 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2783 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002784
Damien George55baff42014-01-21 21:40:13 +00002785 qstr qstr_arg = QSTR_FROM_STR_STATIC(".0");
Damien429d7192013-10-04 19:53:11 +01002786 if (comp->pass == PASS_1) {
2787 bool added;
2788 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2789 assert(added);
2790 id_info->kind = ID_INFO_KIND_LOCAL;
2791 scope->num_params = 1;
2792 }
2793
2794 if (scope->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002795 EMIT_ARG(build_list, 0);
Damien429d7192013-10-04 19:53:11 +01002796 } else if (scope->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002797 EMIT_ARG(build_map, 0);
Damien429d7192013-10-04 19:53:11 +01002798 } else if (scope->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002799 EMIT_ARG(build_set, 0);
Damien429d7192013-10-04 19:53:11 +01002800 }
2801
Damienb05d7072013-10-05 13:37:10 +01002802 int l_end = comp_next_label(comp);
2803 int l_top = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002804 EMIT_ARG(load_id, qstr_arg);
2805 EMIT_ARG(label_assign, l_top);
2806 EMIT_ARG(for_iter, l_end);
Damien429d7192013-10-04 19:53:11 +01002807 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2808 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
Damien Georgeb9791222014-01-23 00:34:21 +00002809 EMIT_ARG(jump, l_top);
2810 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002811 EMIT(for_iter_end);
2812
2813 if (scope->kind == SCOPE_GEN_EXPR) {
Damien Georgeb9791222014-01-23 00:34:21 +00002814 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002815 }
2816 EMIT(return_value);
2817 } else {
2818 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00002819 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2820 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2821 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01002822
2823 if (comp->pass == PASS_1) {
2824 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002825 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01002826 assert(added);
2827 id_info->kind = ID_INFO_KIND_LOCAL;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002828 id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
Damien429d7192013-10-04 19:53:11 +01002829 assert(added);
2830 id_info->kind = ID_INFO_KIND_LOCAL;
2831 id_info->param = true;
2832 scope->num_params = 1; // __locals__ is the parameter
2833 }
2834
Damien Georgeb9791222014-01-23 00:34:21 +00002835 EMIT_ARG(load_id, MP_QSTR___locals__);
Damien429d7192013-10-04 19:53:11 +01002836 EMIT(store_locals);
Damien Georgeb9791222014-01-23 00:34:21 +00002837 EMIT_ARG(load_id, MP_QSTR___name__);
2838 EMIT_ARG(store_id, MP_QSTR___module__);
2839 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
2840 EMIT_ARG(store_id, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01002841
2842 check_for_doc_string(comp, pns->nodes[2]);
2843 compile_node(comp, pns->nodes[2]); // 2 is class body
2844
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002845 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01002846 assert(id != NULL);
2847 if (id->kind == ID_INFO_KIND_LOCAL) {
Damien Georgeb9791222014-01-23 00:34:21 +00002848 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002849 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002850#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00002851 EMIT_ARG(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002852#else
Damien Georgeb9791222014-01-23 00:34:21 +00002853 EMIT_ARG(load_fast, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002854#endif
Damien429d7192013-10-04 19:53:11 +01002855 }
2856 EMIT(return_value);
2857 }
2858
Damien415eb6f2013-10-05 12:19:06 +01002859 EMIT(end_pass);
Damien826005c2013-10-05 23:17:28 +01002860}
2861
2862void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2863 comp->pass = pass;
2864 comp->scope_cur = scope;
2865 comp->next_label = 1;
2866
2867 if (scope->kind != SCOPE_FUNCTION) {
2868 printf("Error: inline assembler must be a function\n");
2869 return;
2870 }
2871
Damiena2f2f7d2013-10-06 00:14:13 +01002872 if (comp->pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002873 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur);
Damiena2f2f7d2013-10-06 00:14:13 +01002874 }
2875
Damien826005c2013-10-05 23:17:28 +01002876 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002877 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2878 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2879 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002880
Damiend99b0522013-12-21 18:17:45 +00002881 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002882
Damiena2f2f7d2013-10-06 00:14:13 +01002883 // parameters are in pns->nodes[1]
2884 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002885 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002886 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
Damien Georgeb9791222014-01-23 00:34:21 +00002887 scope->num_params = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
Damiena2f2f7d2013-10-06 00:14:13 +01002888 }
2889
Damiend99b0522013-12-21 18:17:45 +00002890 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002891
Damiend99b0522013-12-21 18:17:45 +00002892 mp_parse_node_t pn_body = pns->nodes[3]; // body
2893 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002894 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2895
Damien Georgecbd2f742014-01-19 11:48:48 +00002896 /*
Damien826005c2013-10-05 23:17:28 +01002897 if (comp->pass == PASS_3) {
2898 //printf("----\n");
2899 scope_print_info(scope);
2900 }
Damien Georgecbd2f742014-01-19 11:48:48 +00002901 */
Damien826005c2013-10-05 23:17:28 +01002902
2903 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002904 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2905 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2906 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2907 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2908 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2909 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2910 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2911 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2912 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2913 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2914 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2915 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2916 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002917 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2918
2919 // emit instructions
2920 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00002921 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien826005c2013-10-05 23:17:28 +01002922 printf("SyntaxError: inline assembler 'label' requires 1 argument\n");
2923 return;
2924 }
2925 int lab = comp_next_label(comp);
2926 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002927 EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01002928 }
2929 } else {
2930 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002931 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
Damien826005c2013-10-05 23:17:28 +01002932 }
2933 }
2934 }
2935
2936 if (comp->pass > PASS_1) {
2937 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01002938 }
Damien429d7192013-10-04 19:53:11 +01002939}
2940
2941void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
2942 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00002943 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01002944 scope->num_locals = 0;
2945 for (int i = 0; i < scope->id_info_len; i++) {
2946 id_info_t *id = &scope->id_info[i];
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002947 if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01002948 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
2949 continue;
2950 }
2951 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
2952 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
2953 }
Damien9ecbcff2013-12-11 00:41:43 +00002954 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01002955 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
2956 id->local_num = scope->num_locals;
2957 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002958 }
2959 }
2960
2961 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00002962#if MICROPY_EMIT_CPYTHON
2963 int num_cell = 0;
2964#endif
Damien9ecbcff2013-12-11 00:41:43 +00002965 for (int i = 0; i < scope->id_info_len; i++) {
2966 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00002967#if MICROPY_EMIT_CPYTHON
2968 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00002969 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00002970 id->local_num = num_cell;
2971 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002972 }
Damien George6baf76e2013-12-30 22:32:17 +00002973#else
2974 // in Micro Python the cells come right after the fast locals
2975 // parameters are not counted here, since they remain at the start
2976 // of the locals, even if they are cell vars
2977 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
2978 id->local_num = scope->num_locals;
2979 scope->num_locals += 1;
2980 }
2981#endif
Damien9ecbcff2013-12-11 00:41:43 +00002982 }
Damien9ecbcff2013-12-11 00:41:43 +00002983
2984 // compute the index of free vars (freevars[idx] in CPython)
2985 // make sure they are in the order of the parent scope
2986 if (scope->parent != NULL) {
2987 int num_free = 0;
2988 for (int i = 0; i < scope->parent->id_info_len; i++) {
2989 id_info_t *id = &scope->parent->id_info[i];
2990 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
2991 for (int j = 0; j < scope->id_info_len; j++) {
2992 id_info_t *id2 = &scope->id_info[j];
2993 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00002994 assert(!id2->param); // free vars should not be params
2995#if MICROPY_EMIT_CPYTHON
2996 // in CPython the frees are numbered after the cells
2997 id2->local_num = num_cell + num_free;
2998#else
2999 // in Micro Python the frees come first, before the params
3000 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00003001#endif
3002 num_free += 1;
3003 }
3004 }
3005 }
Damien429d7192013-10-04 19:53:11 +01003006 }
Damien George6baf76e2013-12-30 22:32:17 +00003007#if !MICROPY_EMIT_CPYTHON
3008 // in Micro Python shift all other locals after the free locals
3009 if (num_free > 0) {
3010 for (int i = 0; i < scope->id_info_len; i++) {
3011 id_info_t *id = &scope->id_info[i];
3012 if (id->param || id->kind != ID_INFO_KIND_FREE) {
3013 id->local_num += num_free;
3014 }
3015 }
3016 scope->num_params += num_free; // free vars are counted as params for passing them into the function
3017 scope->num_locals += num_free;
3018 }
3019#endif
Damien429d7192013-10-04 19:53:11 +01003020 }
3021
3022 // compute flags
3023 //scope->flags = 0; since we set some things in parameters
3024 if (scope->kind != SCOPE_MODULE) {
3025 scope->flags |= SCOPE_FLAG_NEWLOCALS;
3026 }
3027 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) {
3028 assert(scope->parent != NULL);
3029 scope->flags |= SCOPE_FLAG_OPTIMISED;
3030
3031 // TODO possibly other ways it can be nested
Damien George08d07552014-01-29 18:58:52 +00003032 // Note that we don't actually use this information at the moment (for CPython compat only)
3033 if ((SCOPE_FUNCTION <= scope->parent->kind && scope->parent->kind <= SCOPE_SET_COMP) || (scope->parent->kind == SCOPE_CLASS && scope->parent->parent->kind == SCOPE_FUNCTION)) {
Damien429d7192013-10-04 19:53:11 +01003034 scope->flags |= SCOPE_FLAG_NESTED;
3035 }
3036 }
3037 int num_free = 0;
3038 for (int i = 0; i < scope->id_info_len; i++) {
3039 id_info_t *id = &scope->id_info[i];
3040 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3041 num_free += 1;
3042 }
3043 }
3044 if (num_free == 0) {
3045 scope->flags |= SCOPE_FLAG_NOFREE;
3046 }
3047}
3048
Damien George08335002014-01-18 23:24:36 +00003049mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003050 compiler_t *comp = m_new(compiler_t, 1);
3051
Damien Georgecbd2f742014-01-19 11:48:48 +00003052 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003053 comp->is_repl = is_repl;
3054 comp->had_error = false;
3055
Damien429d7192013-10-04 19:53:11 +01003056 comp->break_label = 0;
3057 comp->continue_label = 0;
Damien Georgecbddb272014-02-01 20:08:18 +00003058 comp->break_continue_except_level = 0;
3059 comp->cur_except_level = 0;
3060
Damien429d7192013-10-04 19:53:11 +01003061 comp->scope_head = NULL;
3062 comp->scope_cur = NULL;
3063
Damien826005c2013-10-05 23:17:28 +01003064 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003065 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003066
3067 // set the outer scope
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003068 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003069
Damien826005c2013-10-05 23:17:28 +01003070 // compile pass 1
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003071 comp->emit = emit_pass1_new(MP_QSTR___class__);
Damien826005c2013-10-05 23:17:28 +01003072 comp->emit_method_table = &emit_pass1_method_table;
3073 comp->emit_inline_asm = NULL;
3074 comp->emit_inline_asm_method_table = NULL;
3075 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003076 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003077 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003078#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003079 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003080 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003081#endif
Damien826005c2013-10-05 23:17:28 +01003082 } else {
3083 compile_scope(comp, s, PASS_1);
3084 }
3085
3086 // update maximim number of labels needed
3087 if (comp->next_label > max_num_labels) {
3088 max_num_labels = comp->next_label;
3089 }
Damien429d7192013-10-04 19:53:11 +01003090 }
3091
Damien826005c2013-10-05 23:17:28 +01003092 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003093 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003094 compile_scope_compute_things(comp, s);
3095 }
3096
Damien826005c2013-10-05 23:17:28 +01003097 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003098 emit_pass1_free(comp->emit);
3099
Damien826005c2013-10-05 23:17:28 +01003100 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003101#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003102 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003103#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003104 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003105#endif
Damien3ef4abb2013-10-12 16:53:13 +01003106#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003107 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003108#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003109#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003110 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003111 if (false) {
3112 // dummy
3113
Damien3ef4abb2013-10-12 16:53:13 +01003114#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003115 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3116 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003117 if (emit_inline_thumb == NULL) {
3118 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3119 }
3120 comp->emit = NULL;
3121 comp->emit_method_table = NULL;
3122 comp->emit_inline_asm = emit_inline_thumb;
3123 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3124 compile_scope_inline_asm(comp, s, PASS_2);
3125 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003126#endif
3127
Damien826005c2013-10-05 23:17:28 +01003128 } else {
Damienc025ebb2013-10-12 14:30:21 +01003129
3130 // choose the emit type
3131
Damien3ef4abb2013-10-12 16:53:13 +01003132#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003133 comp->emit = emit_cpython_new(max_num_labels);
3134 comp->emit_method_table = &emit_cpython_method_table;
3135#else
Damien826005c2013-10-05 23:17:28 +01003136 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003137
3138#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003139 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003140 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003141#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003142 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003143 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003144 }
Damien13ed3a62013-10-08 09:05:10 +01003145 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003146#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003147 if (emit_native == NULL) {
3148 emit_native = emit_native_thumb_new(max_num_labels);
3149 }
3150 comp->emit_method_table = &emit_native_thumb_method_table;
3151#endif
3152 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003153 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003154 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003155#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003156
Damien826005c2013-10-05 23:17:28 +01003157 default:
3158 if (emit_bc == NULL) {
Damien Georgecbd2f742014-01-19 11:48:48 +00003159 emit_bc = emit_bc_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003160 }
3161 comp->emit = emit_bc;
3162 comp->emit_method_table = &emit_bc_method_table;
3163 break;
3164 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003165#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003166
3167 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003168 compile_scope(comp, s, PASS_2);
3169 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003170 }
Damien429d7192013-10-04 19:53:11 +01003171 }
3172
Damien George41d02b62014-01-24 22:42:28 +00003173 // free the emitters
3174#if !MICROPY_EMIT_CPYTHON
3175 if (emit_bc != NULL) {
3176 emit_bc_free(emit_bc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +02003177 }
Damien George41d02b62014-01-24 22:42:28 +00003178#if MICROPY_EMIT_NATIVE
3179 if (emit_native != NULL) {
3180#if MICROPY_EMIT_X64
3181 emit_native_x64_free(emit_native);
3182#elif MICROPY_EMIT_THUMB
3183 emit_native_thumb_free(emit_native);
3184#endif
3185 }
3186#endif
3187#if MICROPY_EMIT_INLINE_THUMB
3188 if (emit_inline_thumb != NULL) {
3189 emit_inline_thumb_free(emit_inline_thumb);
3190 }
3191#endif
3192#endif // !MICROPY_EMIT_CPYTHON
3193
3194 // free the scopes
Paul Sokolovskyfd313582014-01-23 23:05:47 +02003195 uint unique_code_id = module_scope->unique_code_id;
3196 for (scope_t *s = module_scope; s;) {
3197 scope_t *next = s->next;
3198 scope_free(s);
3199 s = next;
3200 }
Damien5ac1b2e2013-10-18 19:58:12 +01003201
Damien George41d02b62014-01-24 22:42:28 +00003202 // free the compiler
3203 bool had_error = comp->had_error;
3204 m_del_obj(compiler_t, comp);
3205
Damien George1fb03172014-01-03 14:22:03 +00003206 if (had_error) {
3207 // TODO return a proper error message
3208 return mp_const_none;
3209 } else {
3210#if MICROPY_EMIT_CPYTHON
3211 // can't create code, so just return true
Damien George41d02b62014-01-24 22:42:28 +00003212 (void)unique_code_id; // to suppress warning that unique_code_id is unused
Damien George1fb03172014-01-03 14:22:03 +00003213 return mp_const_true;
3214#else
3215 // return function that executes the outer module
Paul Sokolovsky90750022014-02-01 15:05:04 +02003216 return rt_make_function_from_id(unique_code_id, MP_OBJ_NULL);
Damien George1fb03172014-01-03 14:22:03 +00003217#endif
3218 }
Damien429d7192013-10-04 19:53:11 +01003219}