blob: dc001cd88f507ace8f252304c94d84b762820736 [file] [log] [blame]
xbeefe34222014-03-16 00:14:26 -07001#include <stdbool.h>
Damien429d7192013-10-04 19:53:11 +01002#include <stdint.h>
3#include <stdio.h>
4#include <string.h>
5#include <assert.h>
Rachel Dowdall56402792014-03-22 20:19:24 +00006#include <math.h>
Damien429d7192013-10-04 19:53:11 +01007
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"
Rachel Dowdallcde86312014-03-22 17:29:27 +000019#include "intdivmod.h"
Damien429d7192013-10-04 19:53:11 +010020
21// TODO need to mangle __attr names
22
Damience89a212013-10-15 22:25:17 +010023#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)
24
Damien429d7192013-10-04 19:53:11 +010025typedef enum {
26 PN_none = 0,
Damien George00208ce2014-01-23 00:00:53 +000027#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
Damien429d7192013-10-04 19:53:11 +010028#include "grammar.h"
29#undef DEF_RULE
30 PN_maximum_number_of,
31} pn_kind_t;
32
Damien Georgeb9791222014-01-23 00:34:21 +000033#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
34#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
35#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
36#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 +010037
Damien6cdd3af2013-10-05 18:08:26 +010038#define EMIT_OPT_NONE (0)
39#define EMIT_OPT_BYTE_CODE (1)
40#define EMIT_OPT_NATIVE_PYTHON (2)
Damien7af3d192013-10-07 00:02:49 +010041#define EMIT_OPT_VIPER (3)
42#define EMIT_OPT_ASM_THUMB (4)
Damien6cdd3af2013-10-05 18:08:26 +010043
Damien429d7192013-10-04 19:53:11 +010044typedef struct _compiler_t {
Damien Georgecbd2f742014-01-19 11:48:48 +000045 qstr source_file;
Damien5ac1b2e2013-10-18 19:58:12 +010046 bool is_repl;
Damien429d7192013-10-04 19:53:11 +010047 pass_kind_t pass;
Damien5ac1b2e2013-10-18 19:58:12 +010048 bool had_error; // try to keep compiler clean from nlr
Damien429d7192013-10-04 19:53:11 +010049
Damienb05d7072013-10-05 13:37:10 +010050 int next_label;
Damienb05d7072013-10-05 13:37:10 +010051
Damien429d7192013-10-04 19:53:11 +010052 int break_label;
53 int continue_label;
Damien Georgecbddb272014-02-01 20:08:18 +000054 int break_continue_except_level;
55 int cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
Damien429d7192013-10-04 19:53:11 +010056
57 int n_arg_keyword;
58 bool have_star_arg;
59 bool have_dbl_star_arg;
60 bool have_bare_star;
61 int param_pass;
62 int param_pass_num_dict_params;
63 int param_pass_num_default_params;
64
Damien George35e2a4e2014-02-05 00:51:47 +000065 bool func_arg_is_super; // used to compile special case of super() function call
66
Damien429d7192013-10-04 19:53:11 +010067 scope_t *scope_head;
68 scope_t *scope_cur;
69
Damien6cdd3af2013-10-05 18:08:26 +010070 emit_t *emit; // current emitter
71 const emit_method_table_t *emit_method_table; // current emit method table
Damien826005c2013-10-05 23:17:28 +010072
73 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
74 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 +010075} compiler_t;
76
Damien Georgef41fdd02014-03-03 23:19:11 +000077STATIC void compile_syntax_error(compiler_t *comp, const char *msg) {
78 // TODO store the error message to a variable in compiler_t instead of printing it
79 printf("SyntaxError: %s\n", msg);
80 comp->had_error = true;
81}
82
Damiend99b0522013-12-21 18:17:45 +000083mp_parse_node_t fold_constants(mp_parse_node_t pn) {
84 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
85 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
86 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +010087
88 // fold arguments first
89 for (int i = 0; i < n; i++) {
90 pns->nodes[i] = fold_constants(pns->nodes[i]);
91 }
92
Damiend99b0522013-12-21 18:17:45 +000093 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +010094 case PN_shift_expr:
Damiend99b0522013-12-21 18:17:45 +000095 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +020096 int arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
97 int arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damiend99b0522013-12-21 18:17:45 +000098 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
Damien3ef4abb2013-10-12 16:53:13 +010099#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100100 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000101 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
Damien0efb3a12013-10-12 16:16:56 +0100102#endif
Damiend99b0522013-12-21 18:17:45 +0000103 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
104 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien429d7192013-10-04 19:53:11 +0100105 } else {
106 // shouldn't happen
107 assert(0);
108 }
109 }
110 break;
111
112 case PN_arith_expr:
Damien0efb3a12013-10-12 16:16:56 +0100113 // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
Damiend99b0522013-12-21 18:17:45 +0000114 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200115 machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
116 machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damien0efb3a12013-10-12 16:16:56 +0100117 machine_int_t res;
Damiend99b0522013-12-21 18:17:45 +0000118 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100119 res = arg0 + arg1;
Damiend99b0522013-12-21 18:17:45 +0000120 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100121 res = arg0 - arg1;
Damien429d7192013-10-04 19:53:11 +0100122 } else {
123 // shouldn't happen
124 assert(0);
Damien0efb3a12013-10-12 16:16:56 +0100125 res = 0;
126 }
Paul Sokolovskybbf0e2f2014-02-21 02:04:32 +0200127 if (MP_PARSE_FITS_SMALL_INT(res)) {
Damiend99b0522013-12-21 18:17:45 +0000128 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
Damien429d7192013-10-04 19:53:11 +0100129 }
130 }
131 break;
132
133 case PN_term:
Damiend99b0522013-12-21 18:17:45 +0000134 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200135 int arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
136 int arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damiend99b0522013-12-21 18:17:45 +0000137 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien3ef4abb2013-10-12 16:53:13 +0100138#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100139 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000140 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
Damien0efb3a12013-10-12 16:16:56 +0100141#endif
Damiend99b0522013-12-21 18:17:45 +0000142 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +0100143 ; // pass
Damiend99b0522013-12-21 18:17:45 +0000144 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
Rachel Dowdallcde86312014-03-22 17:29:27 +0000145 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, python_modulo(arg0, arg1));
Damiend99b0522013-12-21 18:17:45 +0000146 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
Rachel Dowdall56402792014-03-22 20:19:24 +0000147 //pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT,
148 // floor((mp_float_t)arg0 / arg1));
149 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT,
150 python_floor_divide(arg0, arg1));
151
Damien429d7192013-10-04 19:53:11 +0100152 } else {
153 // shouldn't happen
154 assert(0);
155 }
156 }
157 break;
158
159 case PN_factor_2:
Damiend99b0522013-12-21 18:17:45 +0000160 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200161 machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +0000162 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
163 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
164 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
165 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
166 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
167 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien429d7192013-10-04 19:53:11 +0100168 } else {
169 // shouldn't happen
170 assert(0);
171 }
172 }
173 break;
174
Damien3ef4abb2013-10-12 16:53:13 +0100175#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +0100176 case PN_power:
Damien0efb3a12013-10-12 16:16:56 +0100177 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000178 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])) {
179 mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
180 if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200181 int power = MP_PARSE_NODE_LEAF_SMALL_INT(pns2->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100182 if (power >= 0) {
183 int ans = 1;
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200184 int base = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100185 for (; power > 0; power--) {
186 ans *= base;
187 }
Damiend99b0522013-12-21 18:17:45 +0000188 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien429d7192013-10-04 19:53:11 +0100189 }
190 }
191 }
192 break;
Damien0efb3a12013-10-12 16:16:56 +0100193#endif
Damien429d7192013-10-04 19:53:11 +0100194 }
195 }
196
197 return pn;
198}
199
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200200STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
Damiend99b0522013-12-21 18:17:45 +0000201void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100202
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200203STATIC int comp_next_label(compiler_t *comp) {
Damienb05d7072013-10-05 13:37:10 +0100204 return comp->next_label++;
205}
206
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200207STATIC 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 +0000208 scope_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
Damien429d7192013-10-04 19:53:11 +0100209 scope->parent = comp->scope_cur;
210 scope->next = NULL;
211 if (comp->scope_head == NULL) {
212 comp->scope_head = scope;
213 } else {
214 scope_t *s = comp->scope_head;
215 while (s->next != NULL) {
216 s = s->next;
217 }
218 s->next = scope;
219 }
220 return scope;
221}
222
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200223STATIC int list_len(mp_parse_node_t pn, int pn_kind) {
Damiend99b0522013-12-21 18:17:45 +0000224 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100225 return 0;
Damiend99b0522013-12-21 18:17:45 +0000226 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100227 return 1;
228 } else {
Damiend99b0522013-12-21 18:17:45 +0000229 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
230 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100231 return 1;
232 } else {
Damiend99b0522013-12-21 18:17:45 +0000233 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100234 }
235 }
236}
237
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200238STATIC 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)) {
Damiend99b0522013-12-21 18:17:45 +0000239 if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
240 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
241 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100242 for (int i = 0; i < num_nodes; i++) {
243 f(comp, pns->nodes[i]);
244 }
Damiend99b0522013-12-21 18:17:45 +0000245 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100246 f(comp, pn);
247 }
248}
249
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200250STATIC int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
Damiend99b0522013-12-21 18:17:45 +0000251 if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100252 *nodes = NULL;
253 return 0;
Damiend99b0522013-12-21 18:17:45 +0000254 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100255 *nodes = pn;
256 return 1;
257 } else {
Damiend99b0522013-12-21 18:17:45 +0000258 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
259 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100260 *nodes = pn;
261 return 1;
262 } else {
263 *nodes = pns->nodes;
Damiend99b0522013-12-21 18:17:45 +0000264 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100265 }
266 }
267}
268
Damiend99b0522013-12-21 18:17:45 +0000269void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100270}
271
Damiend99b0522013-12-21 18:17:45 +0000272void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
273 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100274 for (int i = 0; i < num_nodes; i++) {
275 compile_node(comp, pns->nodes[i]);
276 }
277}
278
Damien3ef4abb2013-10-12 16:53:13 +0100279#if MICROPY_EMIT_CPYTHON
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200280STATIC bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000281 if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100282 return false;
283 }
Damiend99b0522013-12-21 18:17:45 +0000284 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +0100285 return false;
286 }
287 return true;
288}
289
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200290STATIC void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
Damien George55baff42014-01-21 21:40:13 +0000291 uint len;
292 const byte *str = qstr_data(qstr, &len);
Damien02f89412013-12-12 15:13:36 +0000293 bool has_single_quote = false;
294 bool has_double_quote = false;
295 for (int i = 0; i < len; i++) {
296 if (str[i] == '\'') {
297 has_single_quote = true;
298 } else if (str[i] == '"') {
299 has_double_quote = true;
300 }
301 }
302 if (bytes) {
303 vstr_printf(vstr, "b");
304 }
305 bool quote_single = false;
306 if (has_single_quote && !has_double_quote) {
307 vstr_printf(vstr, "\"");
308 } else {
309 quote_single = true;
310 vstr_printf(vstr, "'");
311 }
312 for (int i = 0; i < len; i++) {
313 if (str[i] == '\n') {
314 vstr_printf(vstr, "\\n");
315 } else if (str[i] == '\\') {
316 vstr_printf(vstr, "\\\\");
317 } else if (str[i] == '\'' && quote_single) {
318 vstr_printf(vstr, "\\'");
319 } else {
320 vstr_printf(vstr, "%c", str[i]);
321 }
322 }
323 if (has_single_quote && !has_double_quote) {
324 vstr_printf(vstr, "\"");
325 } else {
326 vstr_printf(vstr, "'");
327 }
328}
329
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200330STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
Damiend99b0522013-12-21 18:17:45 +0000331 assert(MP_PARSE_NODE_IS_LEAF(pn));
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200332 if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
333 vstr_printf(vstr, INT_FMT, MP_PARSE_NODE_LEAF_SMALL_INT(pn));
334 return;
335 }
336
Damiend99b0522013-12-21 18:17:45 +0000337 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
338 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
339 case MP_PARSE_NODE_ID: assert(0);
Damiend99b0522013-12-21 18:17:45 +0000340 case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
341 case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
342 case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
343 case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
344 case MP_PARSE_NODE_TOKEN:
Damien429d7192013-10-04 19:53:11 +0100345 switch (arg) {
Damiend99b0522013-12-21 18:17:45 +0000346 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
347 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
348 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
Damien429d7192013-10-04 19:53:11 +0100349 default: assert(0);
350 }
351 break;
352 default: assert(0);
353 }
354}
355
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200356STATIC 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 +0100357 int n = 0;
358 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000359 n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien429d7192013-10-04 19:53:11 +0100360 }
361 int total = n;
362 bool is_const = true;
Damiend99b0522013-12-21 18:17:45 +0000363 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100364 total += 1;
Damien3a205172013-10-12 15:01:56 +0100365 if (!cpython_c_tuple_is_const(pn)) {
Damien429d7192013-10-04 19:53:11 +0100366 is_const = false;
367 }
368 }
369 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100370 if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien429d7192013-10-04 19:53:11 +0100371 is_const = false;
372 break;
373 }
374 }
375 if (total > 0 && is_const) {
376 bool need_comma = false;
Damien02f89412013-12-12 15:13:36 +0000377 vstr_t *vstr = vstr_new();
378 vstr_printf(vstr, "(");
Damiend99b0522013-12-21 18:17:45 +0000379 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien02f89412013-12-12 15:13:36 +0000380 cpython_c_tuple_emit_const(comp, pn, vstr);
Damien429d7192013-10-04 19:53:11 +0100381 need_comma = true;
382 }
383 for (int i = 0; i < n; i++) {
384 if (need_comma) {
Damien02f89412013-12-12 15:13:36 +0000385 vstr_printf(vstr, ", ");
Damien429d7192013-10-04 19:53:11 +0100386 }
Damien02f89412013-12-12 15:13:36 +0000387 cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien429d7192013-10-04 19:53:11 +0100388 need_comma = true;
389 }
390 if (total == 1) {
Damien02f89412013-12-12 15:13:36 +0000391 vstr_printf(vstr, ",)");
Damien429d7192013-10-04 19:53:11 +0100392 } else {
Damien02f89412013-12-12 15:13:36 +0000393 vstr_printf(vstr, ")");
Damien429d7192013-10-04 19:53:11 +0100394 }
Damien Georgeb9791222014-01-23 00:34:21 +0000395 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +0000396 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +0100397 } else {
Damiend99b0522013-12-21 18:17:45 +0000398 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100399 compile_node(comp, pn);
400 }
401 for (int i = 0; i < n; i++) {
402 compile_node(comp, pns_list->nodes[i]);
403 }
Damien Georgeb9791222014-01-23 00:34:21 +0000404 EMIT_ARG(build_tuple, total);
Damien429d7192013-10-04 19:53:11 +0100405 }
406}
Damien3a205172013-10-12 15:01:56 +0100407#endif
408
409// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
Damiend99b0522013-12-21 18:17:45 +0000410void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3ef4abb2013-10-12 16:53:13 +0100411#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100412 cpython_c_tuple(comp, pn, pns_list);
413#else
414 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000415 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100416 compile_node(comp, pn);
417 total += 1;
418 }
419 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000420 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100421 for (int i = 0; i < n; i++) {
422 compile_node(comp, pns_list->nodes[i]);
423 }
424 total += n;
425 }
Damien Georgeb9791222014-01-23 00:34:21 +0000426 EMIT_ARG(build_tuple, total);
Damien3a205172013-10-12 15:01:56 +0100427#endif
428}
Damien429d7192013-10-04 19:53:11 +0100429
Damiend99b0522013-12-21 18:17:45 +0000430void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100431 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000432 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100433}
434
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200435STATIC bool node_is_const_false(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000436 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200437 // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
Damien429d7192013-10-04 19:53:11 +0100438}
439
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200440STATIC bool node_is_const_true(mp_parse_node_t pn) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200441 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100442}
443
Damien3ef4abb2013-10-12 16:53:13 +0100444#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100445// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200446STATIC 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 +0100447 if (node_is_const_false(pn)) {
448 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000449 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100450 }
451 return;
452 } else if (node_is_const_true(pn)) {
453 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000454 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100455 }
456 return;
Damiend99b0522013-12-21 18:17:45 +0000457 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
458 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
459 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
460 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien429d7192013-10-04 19:53:11 +0100461 if (jump_if == false) {
Damienb05d7072013-10-05 13:37:10 +0100462 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100463 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100464 cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien429d7192013-10-04 19:53:11 +0100465 }
Damien3a205172013-10-12 15:01:56 +0100466 cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000467 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100468 } else {
469 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100470 cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100471 }
472 }
473 return;
Damiend99b0522013-12-21 18:17:45 +0000474 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien429d7192013-10-04 19:53:11 +0100475 if (jump_if == false) {
476 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100477 cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100478 }
479 } else {
Damienb05d7072013-10-05 13:37:10 +0100480 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100481 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100482 cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien429d7192013-10-04 19:53:11 +0100483 }
Damien3a205172013-10-12 15:01:56 +0100484 cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000485 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100486 }
487 return;
Damiend99b0522013-12-21 18:17:45 +0000488 } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100489 cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien429d7192013-10-04 19:53:11 +0100490 return;
491 }
492 }
493
494 // nothing special, fall back to default compiling for node and jump
495 compile_node(comp, pn);
496 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000497 EMIT_ARG(pop_jump_if_false, label);
Damien429d7192013-10-04 19:53:11 +0100498 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000499 EMIT_ARG(pop_jump_if_true, label);
Damien429d7192013-10-04 19:53:11 +0100500 }
501}
Damien3a205172013-10-12 15:01:56 +0100502#endif
Damien429d7192013-10-04 19:53:11 +0100503
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200504STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien3ef4abb2013-10-12 16:53:13 +0100505#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100506 cpython_c_if_cond(comp, pn, jump_if, label, false);
507#else
508 if (node_is_const_false(pn)) {
509 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000510 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100511 }
512 return;
513 } else if (node_is_const_true(pn)) {
514 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000515 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100516 }
517 return;
Damiend99b0522013-12-21 18:17:45 +0000518 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
519 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
520 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
521 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100522 if (jump_if == false) {
523 int label2 = comp_next_label(comp);
524 for (int i = 0; i < n - 1; i++) {
525 c_if_cond(comp, pns->nodes[i], true, label2);
526 }
527 c_if_cond(comp, pns->nodes[n - 1], false, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000528 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100529 } else {
530 for (int i = 0; i < n; i++) {
531 c_if_cond(comp, pns->nodes[i], true, label);
532 }
533 }
534 return;
Damiend99b0522013-12-21 18:17:45 +0000535 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100536 if (jump_if == false) {
537 for (int i = 0; i < n; i++) {
538 c_if_cond(comp, pns->nodes[i], false, label);
539 }
540 } else {
541 int label2 = comp_next_label(comp);
542 for (int i = 0; i < n - 1; i++) {
543 c_if_cond(comp, pns->nodes[i], false, label2);
544 }
545 c_if_cond(comp, pns->nodes[n - 1], true, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000546 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100547 }
548 return;
Damiend99b0522013-12-21 18:17:45 +0000549 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100550 c_if_cond(comp, pns->nodes[0], !jump_if, label);
551 return;
552 }
553 }
554
555 // nothing special, fall back to default compiling for node and jump
556 compile_node(comp, pn);
557 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000558 EMIT_ARG(pop_jump_if_false, label);
Damien3a205172013-10-12 15:01:56 +0100559 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000560 EMIT_ARG(pop_jump_if_true, label);
Damien3a205172013-10-12 15:01:56 +0100561 }
562#endif
Damien429d7192013-10-04 19:53:11 +0100563}
564
565typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damiend99b0522013-12-21 18:17:45 +0000566void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100567
Damiend99b0522013-12-21 18:17:45 +0000568void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100569 if (assign_kind != ASSIGN_AUG_STORE) {
570 compile_node(comp, pns->nodes[0]);
571 }
572
Damiend99b0522013-12-21 18:17:45 +0000573 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
574 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
575 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
576 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100577 if (assign_kind != ASSIGN_AUG_STORE) {
578 for (int i = 0; i < n - 1; i++) {
579 compile_node(comp, pns1->nodes[i]);
580 }
581 }
Damiend99b0522013-12-21 18:17:45 +0000582 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
583 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100584 }
Damiend99b0522013-12-21 18:17:45 +0000585 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000586 compile_syntax_error(comp, "can't assign to function call");
Damien429d7192013-10-04 19:53:11 +0100587 return;
Damiend99b0522013-12-21 18:17:45 +0000588 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100589 if (assign_kind == ASSIGN_AUG_STORE) {
590 EMIT(rot_three);
591 EMIT(store_subscr);
592 } else {
593 compile_node(comp, pns1->nodes[0]);
594 if (assign_kind == ASSIGN_AUG_LOAD) {
595 EMIT(dup_top_two);
Damien Georgeb9791222014-01-23 00:34:21 +0000596 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +0100597 } else {
598 EMIT(store_subscr);
599 }
600 }
Damiend99b0522013-12-21 18:17:45 +0000601 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
602 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100603 if (assign_kind == ASSIGN_AUG_LOAD) {
604 EMIT(dup_top);
Damien Georgeb9791222014-01-23 00:34:21 +0000605 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100606 } else {
607 if (assign_kind == ASSIGN_AUG_STORE) {
608 EMIT(rot_two);
609 }
Damien Georgeb9791222014-01-23 00:34:21 +0000610 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100611 }
612 } else {
613 // shouldn't happen
614 assert(0);
615 }
616 } else {
617 // shouldn't happen
618 assert(0);
619 }
620
Damiend99b0522013-12-21 18:17:45 +0000621 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100622 // SyntaxError, cannot assign
623 assert(0);
624 }
625}
626
Damiend99b0522013-12-21 18:17:45 +0000627void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
Damien429d7192013-10-04 19:53:11 +0100628 assert(n >= 0);
629 int have_star_index = -1;
630 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000631 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) {
Damien429d7192013-10-04 19:53:11 +0100632 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000633 EMIT_ARG(unpack_ex, i, n - i - 1);
Damien429d7192013-10-04 19:53:11 +0100634 have_star_index = i;
635 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000636 compile_syntax_error(comp, "two starred expressions in assignment");
Damien429d7192013-10-04 19:53:11 +0100637 return;
638 }
639 }
640 }
641 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000642 EMIT_ARG(unpack_sequence, n);
Damien429d7192013-10-04 19:53:11 +0100643 }
644 for (int i = 0; i < n; i++) {
645 if (i == have_star_index) {
Damiend99b0522013-12-21 18:17:45 +0000646 c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100647 } else {
648 c_assign(comp, nodes[i], ASSIGN_STORE);
649 }
650 }
651}
652
653// assigns top of stack to pn
Damiend99b0522013-12-21 18:17:45 +0000654void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100655 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +0000656 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100657 assert(0);
Damiend99b0522013-12-21 18:17:45 +0000658 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
659 if (MP_PARSE_NODE_IS_ID(pn)) {
660 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100661 switch (assign_kind) {
662 case ASSIGN_STORE:
663 case ASSIGN_AUG_STORE:
Damien Georgeb9791222014-01-23 00:34:21 +0000664 EMIT_ARG(store_id, arg);
Damien429d7192013-10-04 19:53:11 +0100665 break;
666 case ASSIGN_AUG_LOAD:
Damien Georgeb9791222014-01-23 00:34:21 +0000667 EMIT_ARG(load_id, arg);
Damien429d7192013-10-04 19:53:11 +0100668 break;
669 }
670 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000671 compile_syntax_error(comp, "can't assign to literal");
Damien429d7192013-10-04 19:53:11 +0100672 return;
673 }
674 } else {
Damiend99b0522013-12-21 18:17:45 +0000675 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
676 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +0100677 case PN_power:
678 // lhs is an index or attribute
679 c_assign_power(comp, pns, assign_kind);
680 break;
681
682 case PN_testlist_star_expr:
683 case PN_exprlist:
684 // lhs is a tuple
685 if (assign_kind != ASSIGN_STORE) {
686 goto bad_aug;
687 }
Damiend99b0522013-12-21 18:17:45 +0000688 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100689 break;
690
691 case PN_atom_paren:
692 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000693 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100694 // empty tuple
Damien Georgef41fdd02014-03-03 23:19:11 +0000695 compile_syntax_error(comp, "can't assign to ()");
Damien429d7192013-10-04 19:53:11 +0100696 return;
Damiend99b0522013-12-21 18:17:45 +0000697 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
698 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100699 goto testlist_comp;
700 } else {
701 // parenthesis around 1 item, is just that item
702 pn = pns->nodes[0];
703 goto tail_recursion;
704 }
705 break;
706
707 case PN_atom_bracket:
708 // lhs is something in brackets
709 if (assign_kind != ASSIGN_STORE) {
710 goto bad_aug;
711 }
Damiend99b0522013-12-21 18:17:45 +0000712 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100713 // empty list, assignment allowed
714 c_assign_tuple(comp, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000715 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
716 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100717 goto testlist_comp;
718 } else {
719 // brackets around 1 item
720 c_assign_tuple(comp, 1, &pns->nodes[0]);
721 }
722 break;
723
724 default:
Damiend99b0522013-12-21 18:17:45 +0000725 printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien429d7192013-10-04 19:53:11 +0100726 assert(0);
727 }
728 return;
729
730 testlist_comp:
731 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000732 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
733 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
734 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100735 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000736 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100737 c_assign_tuple(comp, 1, &pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000738 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100739 // sequence of many items
740 // TODO call c_assign_tuple instead
Damiend99b0522013-12-21 18:17:45 +0000741 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
Damien Georgeb9791222014-01-23 00:34:21 +0000742 EMIT_ARG(unpack_sequence, 1 + n);
Damien429d7192013-10-04 19:53:11 +0100743 c_assign(comp, pns->nodes[0], ASSIGN_STORE);
744 for (int i = 0; i < n; i++) {
745 c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
746 }
Damiend99b0522013-12-21 18:17:45 +0000747 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +0100748 // TODO not implemented
749 assert(0);
750 } else {
751 // sequence with 2 items
752 goto sequence_with_2_items;
753 }
754 } else {
755 // sequence with 2 items
756 sequence_with_2_items:
757 c_assign_tuple(comp, 2, pns->nodes);
758 }
759 return;
760 }
761 return;
762
763 bad_aug:
Damien Georgef41fdd02014-03-03 23:19:11 +0000764 compile_syntax_error(comp, "illegal expression for augmented assignment");
Damien429d7192013-10-04 19:53:11 +0100765}
766
767// stuff for lambda and comprehensions and generators
768void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
Paul Sokolovsky2447a5b2014-03-26 23:14:59 +0200769 if (n_default_params) {
770 EMIT_ARG(build_tuple, n_default_params);
771 }
Damien429d7192013-10-04 19:53:11 +0100772 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000773 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100774 int nfree = 0;
775 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000776 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
777 id_info_t *id = &comp->scope_cur->id_info[i];
778 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
779 for (int j = 0; j < this_scope->id_info_len; j++) {
780 id_info_t *id2 = &this_scope->id_info[j];
781 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +0000782#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +0000783 EMIT_ARG(load_closure, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000784#else
785 // in Micro Python we load closures using LOAD_FAST
Damien Georgeb9791222014-01-23 00:34:21 +0000786 EMIT_ARG(load_fast, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000787#endif
Damien318aec62013-12-10 18:28:17 +0000788 nfree += 1;
789 }
790 }
Damien429d7192013-10-04 19:53:11 +0100791 }
792 }
793 }
794 if (nfree > 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000795 EMIT_ARG(build_tuple, nfree);
Damien429d7192013-10-04 19:53:11 +0100796 }
797
798 // make the function/closure
799 if (nfree == 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000800 EMIT_ARG(make_function, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100801 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000802 EMIT_ARG(make_closure, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100803 }
804}
805
Damiend99b0522013-12-21 18:17:45 +0000806void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000807 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
Damiend99b0522013-12-21 18:17:45 +0000808 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
809 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100810 // bare star
811 comp->have_bare_star = true;
812 }
Damien Georgef41fdd02014-03-03 23:19:11 +0000813
814 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)) {
815 // TODO do we need to do anything with this?
816
817 } else {
818 mp_parse_node_t pn_id;
819 mp_parse_node_t pn_colon;
820 mp_parse_node_t pn_equal;
821 if (MP_PARSE_NODE_IS_ID(pn)) {
822 // this parameter is just an id
823
824 pn_id = pn;
825 pn_colon = MP_PARSE_NODE_NULL;
826 pn_equal = MP_PARSE_NODE_NULL;
827
828 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
829 // this parameter has a colon and/or equal specifier
830
831 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
832 pn_id = pns->nodes[0];
833 pn_colon = pns->nodes[1];
834 pn_equal = pns->nodes[2];
835
836 } else {
837 assert(0);
838 return;
839 }
840
841 if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
842 // this parameter does not have a default value
843
844 // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
845 if (!comp->have_bare_star && comp->param_pass_num_default_params != 0) {
846 compile_syntax_error(comp, "non-default argument follows default argument");
847 return;
848 }
849
850 } else {
851 // this parameter has a default value
852 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
853
854 if (comp->have_bare_star) {
855 comp->param_pass_num_dict_params += 1;
856 if (comp->param_pass == 1) {
857 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pn_id));
858 compile_node(comp, pn_equal);
859 }
860 } else {
861 comp->param_pass_num_default_params += 1;
862 if (comp->param_pass == 2) {
863 compile_node(comp, pn_equal);
864 }
865 }
866 }
867
868 // TODO pn_colon not implemented
869 (void)pn_colon;
Damien429d7192013-10-04 19:53:11 +0100870 }
871}
872
873// leaves function object on stack
874// returns function name
Damiend99b0522013-12-21 18:17:45 +0000875qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100876 if (comp->pass == PASS_1) {
877 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000878 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100879 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000880 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100881 }
882
883 // save variables (probably don't need to do this, since we can't have nested definitions..?)
884 bool old_have_bare_star = comp->have_bare_star;
885 int old_param_pass = comp->param_pass;
886 int old_param_pass_num_dict_params = comp->param_pass_num_dict_params;
887 int old_param_pass_num_default_params = comp->param_pass_num_default_params;
888
889 // compile default parameters
Damien Georgef41fdd02014-03-03 23:19:11 +0000890
891 // pass 1 does any default parameters after bare star
Damien429d7192013-10-04 19:53:11 +0100892 comp->have_bare_star = false;
Damien Georgef41fdd02014-03-03 23:19:11 +0000893 comp->param_pass = 1;
Damien429d7192013-10-04 19:53:11 +0100894 comp->param_pass_num_dict_params = 0;
895 comp->param_pass_num_default_params = 0;
896 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
Damien Georgef41fdd02014-03-03 23:19:11 +0000897
898 if (comp->had_error) {
899 return MP_QSTR_NULL;
900 }
901
902 // pass 2 does any default parameters before bare star
Damien429d7192013-10-04 19:53:11 +0100903 comp->have_bare_star = false;
Damien Georgef41fdd02014-03-03 23:19:11 +0000904 comp->param_pass = 2;
Damien429d7192013-10-04 19:53:11 +0100905 comp->param_pass_num_dict_params = 0;
906 comp->param_pass_num_default_params = 0;
907 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
908
909 // get the scope for this function
910 scope_t *fscope = (scope_t*)pns->nodes[4];
911
912 // make the function
913 close_over_variables_etc(comp, fscope, comp->param_pass_num_dict_params, comp->param_pass_num_default_params);
914
915 // restore variables
916 comp->have_bare_star = old_have_bare_star;
917 comp->param_pass = old_param_pass;
918 comp->param_pass_num_dict_params = old_param_pass_num_dict_params;
919 comp->param_pass_num_default_params = old_param_pass_num_default_params;
920
921 // return its name (the 'f' in "def f(...):")
922 return fscope->simple_name;
923}
924
925// leaves class object on stack
926// returns class name
Damiend99b0522013-12-21 18:17:45 +0000927qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100928 if (comp->pass == PASS_1) {
929 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000930 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100931 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000932 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100933 }
934
935 EMIT(load_build_class);
936
937 // scope for this class
938 scope_t *cscope = (scope_t*)pns->nodes[3];
939
940 // compile the class
941 close_over_variables_etc(comp, cscope, 0, 0);
942
943 // get its name
Damien Georgeb9791222014-01-23 00:34:21 +0000944 EMIT_ARG(load_const_id, cscope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100945
946 // nodes[1] has parent classes, if any
Damien Georgebbcd49a2014-02-06 20:30:16 +0000947 comp->func_arg_is_super = false;
948 compile_trailer_paren_helper(comp, pns->nodes[1], false, 2);
Damien429d7192013-10-04 19:53:11 +0100949
950 // return its name (the 'C' in class C(...):")
951 return cscope->simple_name;
952}
953
Damien6cdd3af2013-10-05 18:08:26 +0100954// returns true if it was a built-in decorator (even if the built-in had an error)
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200955STATIC 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 +0000956 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100957 return false;
958 }
959
960 if (name_len != 2) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000961 compile_syntax_error(comp, "invalid micropython decorator");
Damien6cdd3af2013-10-05 18:08:26 +0100962 return true;
963 }
964
Damiend99b0522013-12-21 18:17:45 +0000965 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000966 if (attr == MP_QSTR_byte_code) {
Damien5ac1b2e2013-10-18 19:58:12 +0100967 *emit_options = EMIT_OPT_BYTE_CODE;
Damience89a212013-10-15 22:25:17 +0100968#if MICROPY_EMIT_NATIVE
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000969 } else if (attr == MP_QSTR_native) {
Damien6cdd3af2013-10-05 18:08:26 +0100970 *emit_options = EMIT_OPT_NATIVE_PYTHON;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000971 } else if (attr == MP_QSTR_viper) {
Damien7af3d192013-10-07 00:02:49 +0100972 *emit_options = EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100973#endif
Damien3ef4abb2013-10-12 16:53:13 +0100974#if MICROPY_EMIT_INLINE_THUMB
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000975 } else if (attr == MP_QSTR_asm_thumb) {
Damien5bfb7592013-10-05 18:41:24 +0100976 *emit_options = EMIT_OPT_ASM_THUMB;
Damienc025ebb2013-10-12 14:30:21 +0100977#endif
Damien6cdd3af2013-10-05 18:08:26 +0100978 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000979 compile_syntax_error(comp, "invalid micropython decorator");
Damien6cdd3af2013-10-05 18:08:26 +0100980 }
981
982 return true;
983}
984
Damiend99b0522013-12-21 18:17:45 +0000985void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100986 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000987 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +0100988 int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
989
Damien6cdd3af2013-10-05 18:08:26 +0100990 // inherit emit options for this function/class definition
991 uint emit_options = comp->scope_cur->emit_options;
992
993 // compile each decorator
994 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100995 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000996 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
997 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100998
999 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +00001000 mp_parse_node_t *name_nodes;
Damien6cdd3af2013-10-05 18:08:26 +01001001 int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
1002
1003 // check for built-in decorators
1004 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
1005 // this was a built-in
1006 num_built_in_decorators += 1;
1007
1008 } else {
1009 // not a built-in, compile normally
1010
1011 // compile the decorator function
1012 compile_node(comp, name_nodes[0]);
1013 for (int i = 1; i < name_len; i++) {
Damiend99b0522013-12-21 18:17:45 +00001014 assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be
Damien Georgeb9791222014-01-23 00:34:21 +00001015 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i]));
Damien6cdd3af2013-10-05 18:08:26 +01001016 }
1017
1018 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +00001019 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +01001020 // call the decorator function with the arguments in nodes[1]
Damien George35e2a4e2014-02-05 00:51:47 +00001021 comp->func_arg_is_super = false;
Damien6cdd3af2013-10-05 18:08:26 +01001022 compile_node(comp, pns_decorator->nodes[1]);
1023 }
Damien429d7192013-10-04 19:53:11 +01001024 }
1025 }
1026
1027 // compile the body (funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +00001028 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001029 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +00001030 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +01001031 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Damiend99b0522013-12-21 18:17:45 +00001032 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) {
Damien6cdd3af2013-10-05 18:08:26 +01001033 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +01001034 } else {
1035 // shouldn't happen
1036 assert(0);
1037 }
1038
1039 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +01001040 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001041 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001042 }
1043
1044 // store func/class object into name
Damien Georgeb9791222014-01-23 00:34:21 +00001045 EMIT_ARG(store_id, body_name);
Damien429d7192013-10-04 19:53:11 +01001046}
1047
Damiend99b0522013-12-21 18:17:45 +00001048void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01001049 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01001050 // store function object into function name
Damien Georgeb9791222014-01-23 00:34:21 +00001051 EMIT_ARG(store_id, fname);
Damien429d7192013-10-04 19:53:11 +01001052}
1053
Damiend99b0522013-12-21 18:17:45 +00001054void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
1055 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001056 EMIT_ARG(delete_id, MP_PARSE_NODE_LEAF_ARG(pn));
Damiend99b0522013-12-21 18:17:45 +00001057 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
1058 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001059
1060 compile_node(comp, pns->nodes[0]); // base of the power node
1061
Damiend99b0522013-12-21 18:17:45 +00001062 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1063 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1064 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
1065 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001066 for (int i = 0; i < n - 1; i++) {
1067 compile_node(comp, pns1->nodes[i]);
1068 }
Damiend99b0522013-12-21 18:17:45 +00001069 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
1070 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +01001071 }
Damiend99b0522013-12-21 18:17:45 +00001072 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +01001073 // SyntaxError: can't delete a function call
1074 assert(0);
Damiend99b0522013-12-21 18:17:45 +00001075 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +01001076 compile_node(comp, pns1->nodes[0]);
1077 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +00001078 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
1079 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien Georgeb9791222014-01-23 00:34:21 +00001080 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001081 } else {
1082 // shouldn't happen
1083 assert(0);
1084 }
1085 } else {
1086 // shouldn't happen
1087 assert(0);
1088 }
1089
Damiend99b0522013-12-21 18:17:45 +00001090 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001091 // SyntaxError, cannot delete
1092 assert(0);
1093 }
Damiend99b0522013-12-21 18:17:45 +00001094 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
1095 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
1096 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) {
1097 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001098 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
1099
Damiend99b0522013-12-21 18:17:45 +00001100 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1101 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1102 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01001103 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00001104 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001105 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00001106 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01001107 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +00001108 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001109 c_del_stmt(comp, pns->nodes[0]);
1110 for (int i = 0; i < n; i++) {
1111 c_del_stmt(comp, pns1->nodes[i]);
1112 }
Damiend99b0522013-12-21 18:17:45 +00001113 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01001114 // TODO not implemented; can't del comprehension?
1115 assert(0);
1116 } else {
1117 // sequence with 2 items
1118 goto sequence_with_2_items;
1119 }
1120 } else {
1121 // sequence with 2 items
1122 sequence_with_2_items:
1123 c_del_stmt(comp, pns->nodes[0]);
1124 c_del_stmt(comp, pns->nodes[1]);
1125 }
1126 } else {
1127 // tuple with 1 element
1128 c_del_stmt(comp, pn);
1129 }
1130 } else {
1131 // not implemented
1132 assert(0);
1133 }
1134}
1135
Damiend99b0522013-12-21 18:17:45 +00001136void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001137 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
1138}
1139
Damiend99b0522013-12-21 18:17:45 +00001140void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001141 if (comp->break_label == 0) {
1142 printf("ERROR: cannot break from here\n");
1143 }
Damien Georgecbddb272014-02-01 20:08:18 +00001144 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001145}
1146
Damiend99b0522013-12-21 18:17:45 +00001147void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001148 if (comp->continue_label == 0) {
1149 printf("ERROR: cannot continue from here\n");
1150 }
Damien Georgecbddb272014-02-01 20:08:18 +00001151 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001152}
1153
Damiend99b0522013-12-21 18:17:45 +00001154void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +01001155 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
Damien Georgef41fdd02014-03-03 23:19:11 +00001156 compile_syntax_error(comp, "'return' outside function");
Damien5ac1b2e2013-10-18 19:58:12 +01001157 return;
1158 }
Damiend99b0522013-12-21 18:17:45 +00001159 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001160 // no argument to 'return', so return None
Damien Georgeb9791222014-01-23 00:34:21 +00001161 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damiend99b0522013-12-21 18:17:45 +00001162 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +01001163 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +00001164 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
1165 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 +01001166
Damienb05d7072013-10-05 13:37:10 +01001167 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001168 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1169 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
1170 EMIT(return_value);
Damien Georgeb9791222014-01-23 00:34:21 +00001171 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001172 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1173 } else {
1174 compile_node(comp, pns->nodes[0]);
1175 }
1176 EMIT(return_value);
1177}
1178
Damiend99b0522013-12-21 18:17:45 +00001179void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001180 compile_node(comp, pns->nodes[0]);
1181 EMIT(pop_top);
1182}
1183
Damiend99b0522013-12-21 18:17:45 +00001184void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1185 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001186 // raise
Damien Georgeb9791222014-01-23 00:34:21 +00001187 EMIT_ARG(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001188 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001189 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001190 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001191 compile_node(comp, pns->nodes[0]);
1192 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001193 EMIT_ARG(raise_varargs, 2);
Damien429d7192013-10-04 19:53:11 +01001194 } else {
1195 // raise x
1196 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001197 EMIT_ARG(raise_varargs, 1);
Damien429d7192013-10-04 19:53:11 +01001198 }
1199}
1200
1201// q1 holds the base, q2 the full name
1202// eg a -> q1=q2=a
1203// a.b.c -> q1=a, q2=a.b.c
Damiend99b0522013-12-21 18:17:45 +00001204void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
Damien429d7192013-10-04 19:53:11 +01001205 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001206 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1207 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001208 // a name of the form x as y; unwrap it
Damiend99b0522013-12-21 18:17:45 +00001209 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001210 pn = pns->nodes[0];
1211 is_as = true;
1212 }
Damiend99b0522013-12-21 18:17:45 +00001213 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001214 // just a simple name
Damiend99b0522013-12-21 18:17:45 +00001215 *q2 = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001216 if (!is_as) {
1217 *q1 = *q2;
1218 }
Damien Georgeb9791222014-01-23 00:34:21 +00001219 EMIT_ARG(import_name, *q2);
Damiend99b0522013-12-21 18:17:45 +00001220 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
1221 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
1222 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) {
Damien429d7192013-10-04 19:53:11 +01001223 // a name of the form a.b.c
1224 if (!is_as) {
Damiend99b0522013-12-21 18:17:45 +00001225 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001226 }
Damiend99b0522013-12-21 18:17:45 +00001227 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001228 int len = n - 1;
1229 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00001230 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001231 }
Damien George55baff42014-01-21 21:40:13 +00001232 byte *q_ptr;
1233 byte *str_dest = qstr_build_start(len, &q_ptr);
Damien429d7192013-10-04 19:53:11 +01001234 for (int i = 0; i < n; i++) {
1235 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001236 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001237 }
Damien George55baff42014-01-21 21:40:13 +00001238 uint str_src_len;
1239 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00001240 memcpy(str_dest, str_src, str_src_len);
1241 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001242 }
Damien George55baff42014-01-21 21:40:13 +00001243 *q2 = qstr_build_end(q_ptr);
Damien Georgeb9791222014-01-23 00:34:21 +00001244 EMIT_ARG(import_name, *q2);
Damien429d7192013-10-04 19:53:11 +01001245 if (is_as) {
1246 for (int i = 1; i < n; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001247 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001248 }
1249 }
1250 } else {
1251 // TODO not implemented
Paul Sokolovskya1aba362014-02-20 13:21:31 +02001252 // This covers relative imports starting with dot(s) like "from .foo import"
Damien429d7192013-10-04 19:53:11 +01001253 assert(0);
1254 }
1255 } else {
1256 // TODO not implemented
Paul Sokolovskya1aba362014-02-20 13:21:31 +02001257 // This covers relative imports with dots only like "from .. import"
Damien429d7192013-10-04 19:53:11 +01001258 assert(0);
1259 }
1260}
1261
Damiend99b0522013-12-21 18:17:45 +00001262void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgeb9791222014-01-23 00:34:21 +00001263 EMIT_ARG(load_const_small_int, 0); // ??
1264 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001265 qstr q1, q2;
1266 do_import_name(comp, pn, &q1, &q2);
Damien Georgeb9791222014-01-23 00:34:21 +00001267 EMIT_ARG(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001268}
1269
Damiend99b0522013-12-21 18:17:45 +00001270void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001271 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1272}
1273
Damiend99b0522013-12-21 18:17:45 +00001274void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1275 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001276 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001277
1278 // build the "fromlist" tuple
1279#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001280 EMIT_ARG(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001281#else
Damien Georgeb9791222014-01-23 00:34:21 +00001282 EMIT_ARG(load_const_str, QSTR_FROM_STR_STATIC("*"), false);
1283 EMIT_ARG(build_tuple, 1);
Damiendb4c3612013-12-10 17:27:24 +00001284#endif
1285
1286 // do the import
Damien429d7192013-10-04 19:53:11 +01001287 qstr dummy_q, id1;
1288 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1289 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001290
Damien429d7192013-10-04 19:53:11 +01001291 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001292 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001293
1294 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001295 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001296 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001297#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001298 {
1299 vstr_t *vstr = vstr_new();
1300 vstr_printf(vstr, "(");
1301 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001302 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1303 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1304 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001305 if (i > 0) {
1306 vstr_printf(vstr, ", ");
1307 }
1308 vstr_printf(vstr, "'");
Damien George55baff42014-01-21 21:40:13 +00001309 uint len;
1310 const byte *str = qstr_data(id2, &len);
1311 vstr_add_strn(vstr, (const char*)str, len);
Damien02f89412013-12-12 15:13:36 +00001312 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001313 }
Damien02f89412013-12-12 15:13:36 +00001314 if (n == 1) {
1315 vstr_printf(vstr, ",");
1316 }
1317 vstr_printf(vstr, ")");
Damien Georgeb9791222014-01-23 00:34:21 +00001318 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001319 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001320 }
Damiendb4c3612013-12-10 17:27:24 +00001321#else
1322 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001323 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1324 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1325 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001326 EMIT_ARG(load_const_str, id2, false);
Damiendb4c3612013-12-10 17:27:24 +00001327 }
Damien Georgeb9791222014-01-23 00:34:21 +00001328 EMIT_ARG(build_tuple, n);
Damiendb4c3612013-12-10 17:27:24 +00001329#endif
1330
1331 // do the import
Damien429d7192013-10-04 19:53:11 +01001332 qstr dummy_q, id1;
1333 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1334 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001335 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1336 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1337 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001338 EMIT_ARG(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001339 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001340 EMIT_ARG(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001341 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001342 EMIT_ARG(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001343 }
1344 }
1345 EMIT(pop_top);
1346 }
1347}
1348
Damiend99b0522013-12-21 18:17:45 +00001349void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001350 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001351 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1352 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001353 } else {
Damiend99b0522013-12-21 18:17:45 +00001354 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1355 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001356 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001357 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001358 }
Damien429d7192013-10-04 19:53:11 +01001359 }
1360 }
1361}
1362
Damiend99b0522013-12-21 18:17:45 +00001363void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001364 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001365 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1366 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001367 } else {
Damiend99b0522013-12-21 18:17:45 +00001368 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1369 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001370 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001371 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001372 }
Damien429d7192013-10-04 19:53:11 +01001373 }
1374 }
1375}
1376
Damiend99b0522013-12-21 18:17:45 +00001377void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001378 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001379 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien Georgeb9791222014-01-23 00:34:21 +00001380 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 +00001381 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001382 // assertion message
1383 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001384 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001385 }
Damien Georgeb9791222014-01-23 00:34:21 +00001386 EMIT_ARG(raise_varargs, 1);
1387 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001388}
1389
Damiend99b0522013-12-21 18:17:45 +00001390void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001391 // TODO proper and/or short circuiting
1392
Damienb05d7072013-10-05 13:37:10 +01001393 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001394
Damienb05d7072013-10-05 13:37:10 +01001395 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001396 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1397
1398 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001399 //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 +01001400 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001401 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001402 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001403 }
1404 //}
Damien Georgeb9791222014-01-23 00:34:21 +00001405 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001406
Damiend99b0522013-12-21 18:17:45 +00001407 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001408 // compile elif blocks
1409
Damiend99b0522013-12-21 18:17:45 +00001410 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001411
Damiend99b0522013-12-21 18:17:45 +00001412 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001413 // multiple elif blocks
1414
Damiend99b0522013-12-21 18:17:45 +00001415 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001416 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001417 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
Damienb05d7072013-10-05 13:37:10 +01001418 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001419 c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition
1420
1421 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001422 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001423 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001424 }
Damien Georgeb9791222014-01-23 00:34:21 +00001425 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001426 }
1427
1428 } else {
1429 // a single elif block
1430
Damienb05d7072013-10-05 13:37:10 +01001431 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001432 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1433
1434 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001435 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001436 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001437 }
Damien Georgeb9791222014-01-23 00:34:21 +00001438 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001439 }
1440 }
1441
1442 // compile else block
1443 compile_node(comp, pns->nodes[3]); // can be null
1444
Damien Georgeb9791222014-01-23 00:34:21 +00001445 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001446}
1447
Damien Georgecbddb272014-02-01 20:08:18 +00001448#define START_BREAK_CONTINUE_BLOCK \
1449 int old_break_label = comp->break_label; \
1450 int old_continue_label = comp->continue_label; \
1451 int break_label = comp_next_label(comp); \
1452 int continue_label = comp_next_label(comp); \
1453 comp->break_label = break_label; \
1454 comp->continue_label = continue_label; \
1455 comp->break_continue_except_level = comp->cur_except_level;
1456
1457#define END_BREAK_CONTINUE_BLOCK \
1458 comp->break_label = old_break_label; \
1459 comp->continue_label = old_continue_label; \
1460 comp->break_continue_except_level = comp->cur_except_level;
1461
Damiend99b0522013-12-21 18:17:45 +00001462void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgecbddb272014-02-01 20:08:18 +00001463 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001464
Damience89a212013-10-15 22:25:17 +01001465 // compared to CPython, we have an optimised version of while loops
1466#if MICROPY_EMIT_CPYTHON
1467 int done_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001468 EMIT_ARG(setup_loop, break_label);
1469 EMIT_ARG(label_assign, continue_label);
Damien429d7192013-10-04 19:53:11 +01001470 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1471 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001472 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001473 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001474 }
Damien Georgeb9791222014-01-23 00:34:21 +00001475 EMIT_ARG(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001476 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1477 // this is a small hack to agree with CPython
1478 if (!node_is_const_true(pns->nodes[0])) {
1479 EMIT(pop_block);
1480 }
Damience89a212013-10-15 22:25:17 +01001481#else
1482 int top_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001483 EMIT_ARG(jump, continue_label);
1484 EMIT_ARG(label_assign, top_label);
Damience89a212013-10-15 22:25:17 +01001485 compile_node(comp, pns->nodes[1]); // body
Damien Georgeb9791222014-01-23 00:34:21 +00001486 EMIT_ARG(label_assign, continue_label);
Damience89a212013-10-15 22:25:17 +01001487 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1488#endif
1489
1490 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001491 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001492
1493 compile_node(comp, pns->nodes[2]); // else
1494
Damien Georgeb9791222014-01-23 00:34:21 +00001495 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001496}
1497
Damienf72fd0e2013-11-06 20:20:49 +00001498// TODO preload end and step onto stack if they are not constants
1499// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001500void 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 +00001501 START_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001502
1503 int top_label = comp_next_label(comp);
Damien George600ae732014-01-21 23:48:04 +00001504 int entry_label = comp_next_label(comp);
Damienf72fd0e2013-11-06 20:20:49 +00001505
1506 // compile: var = start
1507 compile_node(comp, pn_start);
1508 c_assign(comp, pn_var, ASSIGN_STORE);
1509
Damien Georgeb9791222014-01-23 00:34:21 +00001510 EMIT_ARG(jump, entry_label);
1511 EMIT_ARG(label_assign, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001512
Damienf3822fc2013-11-09 20:12:03 +00001513 // compile body
1514 compile_node(comp, pn_body);
1515
Damien Georgeb9791222014-01-23 00:34:21 +00001516 EMIT_ARG(label_assign, continue_label);
Damien George600ae732014-01-21 23:48:04 +00001517
Damienf72fd0e2013-11-06 20:20:49 +00001518 // compile: var += step
1519 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1520 compile_node(comp, pn_step);
Damien Georgeb9791222014-01-23 00:34:21 +00001521 EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_ADD);
Damienf72fd0e2013-11-06 20:20:49 +00001522 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1523
Damien Georgeb9791222014-01-23 00:34:21 +00001524 EMIT_ARG(label_assign, entry_label);
Damienf72fd0e2013-11-06 20:20:49 +00001525
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001526 // compile: if var <cond> end: goto top
Damienf72fd0e2013-11-06 20:20:49 +00001527 compile_node(comp, pn_var);
1528 compile_node(comp, pn_end);
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02001529 assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
1530 if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
Damien George9aa2a522014-02-01 23:04:09 +00001531 EMIT_ARG(binary_op, RT_BINARY_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001532 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001533 EMIT_ARG(binary_op, RT_BINARY_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001534 }
Damien Georgeb9791222014-01-23 00:34:21 +00001535 EMIT_ARG(pop_jump_if_true, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001536
1537 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001538 END_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001539
1540 compile_node(comp, pn_else);
1541
Damien Georgeb9791222014-01-23 00:34:21 +00001542 EMIT_ARG(label_assign, break_label);
Damienf72fd0e2013-11-06 20:20:49 +00001543}
1544
Damiend99b0522013-12-21 18:17:45 +00001545void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001546#if !MICROPY_EMIT_CPYTHON
1547 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1548 // this is actually slower, but uses no heap memory
1549 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001550 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)) {
1551 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001552 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1553 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1554 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
1555 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
Damiend99b0522013-12-21 18:17:45 +00001556 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1557 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001558 int n_args = list_get(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001559 mp_parse_node_t pn_range_start;
1560 mp_parse_node_t pn_range_end;
1561 mp_parse_node_t pn_range_step;
1562 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001563 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001564 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001565 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001566 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001567 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001568 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001569 } else if (n_args == 2) {
1570 pn_range_start = args[0];
1571 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001572 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001573 } else {
1574 pn_range_start = args[0];
1575 pn_range_end = args[1];
1576 pn_range_step = args[2];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001577 // We need to know sign of step. This is possible only if it's constant
1578 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
1579 optimize = false;
1580 }
Damienf72fd0e2013-11-06 20:20:49 +00001581 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001582 }
1583 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001584 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1585 return;
1586 }
1587 }
1588 }
1589#endif
1590
Damien Georgecbddb272014-02-01 20:08:18 +00001591 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001592
Damienb05d7072013-10-05 13:37:10 +01001593 int pop_label = comp_next_label(comp);
1594 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001595
Damience89a212013-10-15 22:25:17 +01001596 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1597#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001598 EMIT_ARG(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001599#endif
1600
Damien429d7192013-10-04 19:53:11 +01001601 compile_node(comp, pns->nodes[1]); // iterator
1602 EMIT(get_iter);
Damien Georgecbddb272014-02-01 20:08:18 +00001603 EMIT_ARG(label_assign, continue_label);
Damien Georgeb9791222014-01-23 00:34:21 +00001604 EMIT_ARG(for_iter, pop_label);
Damien429d7192013-10-04 19:53:11 +01001605 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1606 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001607 if (!EMIT(last_emit_was_return_value)) {
Damien Georgecbddb272014-02-01 20:08:18 +00001608 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001609 }
Damien Georgeb9791222014-01-23 00:34:21 +00001610 EMIT_ARG(label_assign, pop_label);
Damien429d7192013-10-04 19:53:11 +01001611 EMIT(for_iter_end);
1612
1613 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001614 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001615
Damience89a212013-10-15 22:25:17 +01001616#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001617 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001618#endif
Damien429d7192013-10-04 19:53:11 +01001619
1620 compile_node(comp, pns->nodes[3]); // else (not tested)
1621
Damien Georgeb9791222014-01-23 00:34:21 +00001622 EMIT_ARG(label_assign, break_label);
1623 EMIT_ARG(label_assign, end_label);
Damien429d7192013-10-04 19:53:11 +01001624}
1625
Damiend99b0522013-12-21 18:17:45 +00001626void 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 +01001627 // this function is a bit of a hack at the moment
1628 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1629
1630 // setup code
1631 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001632 int l1 = comp_next_label(comp);
1633 int success_label = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001634
Damien Georgeb9791222014-01-23 00:34:21 +00001635 EMIT_ARG(setup_except, l1);
Damien Georgecbddb272014-02-01 20:08:18 +00001636 comp->cur_except_level += 1;
1637
Damien429d7192013-10-04 19:53:11 +01001638 compile_node(comp, pn_body); // body
1639 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001640 EMIT_ARG(jump, success_label);
1641 EMIT_ARG(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001642 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001643
1644 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001645 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1646 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001647
1648 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001649 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001650
Damiend99b0522013-12-21 18:17:45 +00001651 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001652 // this is a catch all exception handler
1653 if (i + 1 != n_except) {
Damien Georgef41fdd02014-03-03 23:19:11 +00001654 compile_syntax_error(comp, "default 'except:' must be last");
Damien429d7192013-10-04 19:53:11 +01001655 return;
1656 }
1657 } else {
1658 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001659 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1660 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1661 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1662 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001663 // handler binds the exception to a local
1664 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001665 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001666 }
1667 }
1668 EMIT(dup_top);
1669 compile_node(comp, pns_exception_expr);
Damien George9aa2a522014-02-01 23:04:09 +00001670 EMIT_ARG(binary_op, RT_BINARY_OP_EXCEPTION_MATCH);
Damien Georgeb9791222014-01-23 00:34:21 +00001671 EMIT_ARG(pop_jump_if_false, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001672 }
1673
1674 EMIT(pop_top);
1675
1676 if (qstr_exception_local == 0) {
1677 EMIT(pop_top);
1678 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001679 EMIT_ARG(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001680 }
1681
1682 EMIT(pop_top);
1683
Damiene2880aa2013-12-20 14:22:59 +00001684 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001685 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001686 l3 = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001687 EMIT_ARG(setup_finally, l3);
Damien Georgecbddb272014-02-01 20:08:18 +00001688 comp->cur_except_level += 1;
Damien429d7192013-10-04 19:53:11 +01001689 }
1690 compile_node(comp, pns_except->nodes[1]);
1691 if (qstr_exception_local != 0) {
1692 EMIT(pop_block);
1693 }
1694 EMIT(pop_except);
1695 if (qstr_exception_local != 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001696 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1697 EMIT_ARG(label_assign, l3);
1698 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1699 EMIT_ARG(store_id, qstr_exception_local);
1700 EMIT_ARG(delete_id, qstr_exception_local);
Damien Georgecbddb272014-02-01 20:08:18 +00001701
1702 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001703 EMIT(end_finally);
1704 }
Damien Georgeb9791222014-01-23 00:34:21 +00001705 EMIT_ARG(jump, l2);
1706 EMIT_ARG(label_assign, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001707 }
1708
Damien Georgecbddb272014-02-01 20:08:18 +00001709 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001710 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001711
Damien Georgeb9791222014-01-23 00:34:21 +00001712 EMIT_ARG(label_assign, success_label);
Damien429d7192013-10-04 19:53:11 +01001713 compile_node(comp, pn_else); // else block, can be null
Damien Georgeb9791222014-01-23 00:34:21 +00001714 EMIT_ARG(label_assign, l2);
1715 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001716}
1717
Damiend99b0522013-12-21 18:17:45 +00001718void 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 +01001719 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1720 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001721 int l_finally_block = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001722
Damien Georgeb9791222014-01-23 00:34:21 +00001723 EMIT_ARG(setup_finally, l_finally_block);
Damien Georgecbddb272014-02-01 20:08:18 +00001724 comp->cur_except_level += 1;
1725
Damien429d7192013-10-04 19:53:11 +01001726 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001727 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001728 compile_node(comp, pn_body);
1729 } else {
1730 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1731 }
1732 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001733 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1734 EMIT_ARG(label_assign, l_finally_block);
Damien429d7192013-10-04 19:53:11 +01001735 compile_node(comp, pn_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001736
1737 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001738 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001739
Damien Georgeb9791222014-01-23 00:34:21 +00001740 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001741}
1742
Damiend99b0522013-12-21 18:17:45 +00001743void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1744 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1745 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1746 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001747 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001748 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1749 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001750 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001751 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001752 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001753 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001754 // no finally
1755 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1756 } else {
1757 // have finally
Damiend99b0522013-12-21 18:17:45 +00001758 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 +01001759 }
1760 } else {
1761 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001762 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001763 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001764 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001765 }
1766 } else {
1767 // shouldn't happen
1768 assert(0);
1769 }
1770}
1771
Damiend99b0522013-12-21 18:17:45 +00001772void 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 +01001773 if (n == 0) {
1774 // no more pre-bits, compile the body of the with
1775 compile_node(comp, body);
1776 } else {
Damienb05d7072013-10-05 13:37:10 +01001777 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001778 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001779 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001780 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001781 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001782 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001783 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1784 } else {
1785 // this pre-bit is just an expression
1786 compile_node(comp, nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001787 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001788 EMIT(pop_top);
1789 }
1790 // compile additional pre-bits and the body
1791 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1792 // finish this with block
1793 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001794 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1795 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001796 EMIT(with_cleanup);
1797 EMIT(end_finally);
1798 }
1799}
1800
Damiend99b0522013-12-21 18:17:45 +00001801void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001802 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001803 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001804 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1805 assert(n > 0);
1806
1807 // compile in a nested fashion
1808 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1809}
1810
Damiend99b0522013-12-21 18:17:45 +00001811void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1812 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001813 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1814 // for REPL, evaluate then print the expression
Damien Georgeb9791222014-01-23 00:34:21 +00001815 EMIT_ARG(load_id, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001816 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001817 EMIT_ARG(call_function, 1, 0, false, false);
Damien5ac1b2e2013-10-18 19:58:12 +01001818 EMIT(pop_top);
1819
Damien429d7192013-10-04 19:53:11 +01001820 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001821 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001822 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001823 // do nothing with a lonely constant
1824 } else {
1825 compile_node(comp, pns->nodes[0]); // just an expression
1826 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1827 }
Damien429d7192013-10-04 19:53:11 +01001828 }
1829 } else {
Damiend99b0522013-12-21 18:17:45 +00001830 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1831 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001832 if (kind == PN_expr_stmt_augassign) {
1833 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1834 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001835 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien George7e5fb242014-02-01 22:18:47 +00001836 rt_binary_op_t op;
Damiend99b0522013-12-21 18:17:45 +00001837 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
Damien George7e5fb242014-02-01 22:18:47 +00001838 case MP_TOKEN_DEL_PIPE_EQUAL: op = RT_BINARY_OP_INPLACE_OR; break;
1839 case MP_TOKEN_DEL_CARET_EQUAL: op = RT_BINARY_OP_INPLACE_XOR; break;
1840 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = RT_BINARY_OP_INPLACE_AND; break;
1841 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = RT_BINARY_OP_INPLACE_LSHIFT; break;
1842 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = RT_BINARY_OP_INPLACE_RSHIFT; break;
1843 case MP_TOKEN_DEL_PLUS_EQUAL: op = RT_BINARY_OP_INPLACE_ADD; break;
1844 case MP_TOKEN_DEL_MINUS_EQUAL: op = RT_BINARY_OP_INPLACE_SUBTRACT; break;
1845 case MP_TOKEN_DEL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_MULTIPLY; break;
1846 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
1847 case MP_TOKEN_DEL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
1848 case MP_TOKEN_DEL_PERCENT_EQUAL: op = RT_BINARY_OP_INPLACE_MODULO; break;
1849 case MP_TOKEN_DEL_DBL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_POWER; break;
1850 default: assert(0); op = RT_BINARY_OP_INPLACE_OR; // shouldn't happen
Damien429d7192013-10-04 19:53:11 +01001851 }
Damien George7e5fb242014-02-01 22:18:47 +00001852 EMIT_ARG(binary_op, op);
Damien429d7192013-10-04 19:53:11 +01001853 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1854 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001855 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1856 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001857 // following CPython, we store left-most first
1858 if (rhs > 0) {
1859 EMIT(dup_top);
1860 }
1861 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1862 for (int i = 0; i < rhs; i++) {
1863 if (i + 1 < rhs) {
1864 EMIT(dup_top);
1865 }
Damiend99b0522013-12-21 18:17:45 +00001866 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001867 }
1868 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001869 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1870 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1871 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1872 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001873 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001874 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1875 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001876 compile_node(comp, pns10->nodes[0]); // rhs
1877 compile_node(comp, pns10->nodes[1]); // rhs
1878 EMIT(rot_two);
1879 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1880 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001881 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1882 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1883 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1884 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001885 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001886 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1887 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001888 compile_node(comp, pns10->nodes[0]); // rhs
1889 compile_node(comp, pns10->nodes[1]); // rhs
1890 compile_node(comp, pns10->nodes[2]); // rhs
1891 EMIT(rot_three);
1892 EMIT(rot_two);
1893 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1894 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1895 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1896 } else {
1897 compile_node(comp, pns1->nodes[0]); // rhs
1898 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1899 }
1900 } else {
1901 // shouldn't happen
1902 assert(0);
1903 }
1904 }
1905}
1906
Damiend99b0522013-12-21 18:17:45 +00001907void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1908 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001909 compile_node(comp, pns->nodes[0]);
1910 for (int i = 1; i < num_nodes; i += 1) {
1911 compile_node(comp, pns->nodes[i]);
Damien Georgeb9791222014-01-23 00:34:21 +00001912 EMIT_ARG(binary_op, binary_op);
Damien429d7192013-10-04 19:53:11 +01001913 }
1914}
1915
Damiend99b0522013-12-21 18:17:45 +00001916void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1917 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1918 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001919
1920 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001921 int l_fail = comp_next_label(comp);
1922 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001923 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1924 compile_node(comp, pns->nodes[0]); // success value
Damien Georgeb9791222014-01-23 00:34:21 +00001925 EMIT_ARG(jump, l_end);
1926 EMIT_ARG(label_assign, l_fail);
1927 EMIT_ARG(set_stack_size, stack_size); // force stack size reset
Damien429d7192013-10-04 19:53:11 +01001928 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
Damien Georgeb9791222014-01-23 00:34:21 +00001929 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001930}
1931
Damiend99b0522013-12-21 18:17:45 +00001932void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001933 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001934 //mp_parse_node_t pn_params = pns->nodes[0];
1935 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001936
1937 if (comp->pass == PASS_1) {
1938 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001939 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 +01001940 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001941 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001942 }
1943
1944 // get the scope for this lambda
1945 scope_t *this_scope = (scope_t*)pns->nodes[2];
1946
1947 // make the lambda
1948 close_over_variables_etc(comp, this_scope, 0, 0);
1949}
1950
Damiend99b0522013-12-21 18:17:45 +00001951void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001952 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001953 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001954 for (int i = 0; i < n; i += 1) {
1955 compile_node(comp, pns->nodes[i]);
1956 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001957 EMIT_ARG(jump_if_true_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001958 }
1959 }
Damien Georgeb9791222014-01-23 00:34:21 +00001960 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001961}
1962
Damiend99b0522013-12-21 18:17:45 +00001963void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001964 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001965 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001966 for (int i = 0; i < n; i += 1) {
1967 compile_node(comp, pns->nodes[i]);
1968 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001969 EMIT_ARG(jump_if_false_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001970 }
1971 }
Damien Georgeb9791222014-01-23 00:34:21 +00001972 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001973}
1974
Damiend99b0522013-12-21 18:17:45 +00001975void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001976 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001977 EMIT_ARG(unary_op, RT_UNARY_OP_NOT);
Damien429d7192013-10-04 19:53:11 +01001978}
1979
Damiend99b0522013-12-21 18:17:45 +00001980void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001981 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001982 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001983 compile_node(comp, pns->nodes[0]);
1984 bool multi = (num_nodes > 3);
1985 int l_fail = 0;
1986 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001987 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001988 }
1989 for (int i = 1; i + 1 < num_nodes; i += 2) {
1990 compile_node(comp, pns->nodes[i + 1]);
1991 if (i + 2 < num_nodes) {
1992 EMIT(dup_top);
1993 EMIT(rot_three);
1994 }
Damien George7e5fb242014-02-01 22:18:47 +00001995 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
1996 rt_binary_op_t op;
1997 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
Damien George9aa2a522014-02-01 23:04:09 +00001998 case MP_TOKEN_OP_LESS: op = RT_BINARY_OP_LESS; break;
1999 case MP_TOKEN_OP_MORE: op = RT_BINARY_OP_MORE; break;
2000 case MP_TOKEN_OP_DBL_EQUAL: op = RT_BINARY_OP_EQUAL; break;
2001 case MP_TOKEN_OP_LESS_EQUAL: op = RT_BINARY_OP_LESS_EQUAL; break;
2002 case MP_TOKEN_OP_MORE_EQUAL: op = RT_BINARY_OP_MORE_EQUAL; break;
2003 case MP_TOKEN_OP_NOT_EQUAL: op = RT_BINARY_OP_NOT_EQUAL; break;
2004 case MP_TOKEN_KW_IN: op = RT_BINARY_OP_IN; break;
2005 default: assert(0); op = RT_BINARY_OP_LESS; // shouldn't happen
Damien George7e5fb242014-02-01 22:18:47 +00002006 }
2007 EMIT_ARG(binary_op, op);
Damiend99b0522013-12-21 18:17:45 +00002008 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
2009 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
2010 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01002011 if (kind == PN_comp_op_not_in) {
Damien George9aa2a522014-02-01 23:04:09 +00002012 EMIT_ARG(binary_op, RT_BINARY_OP_NOT_IN);
Damien429d7192013-10-04 19:53:11 +01002013 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00002014 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien George9aa2a522014-02-01 23:04:09 +00002015 EMIT_ARG(binary_op, RT_BINARY_OP_IS);
Damien429d7192013-10-04 19:53:11 +01002016 } else {
Damien George9aa2a522014-02-01 23:04:09 +00002017 EMIT_ARG(binary_op, RT_BINARY_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01002018 }
2019 } else {
2020 // shouldn't happen
2021 assert(0);
2022 }
2023 } else {
2024 // shouldn't happen
2025 assert(0);
2026 }
2027 if (i + 2 < num_nodes) {
Damien Georgeb9791222014-01-23 00:34:21 +00002028 EMIT_ARG(jump_if_false_or_pop, l_fail);
Damien429d7192013-10-04 19:53:11 +01002029 }
2030 }
2031 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01002032 int l_end = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002033 EMIT_ARG(jump, l_end);
2034 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01002035 EMIT(rot_two);
2036 EMIT(pop_top);
Damien Georgeb9791222014-01-23 00:34:21 +00002037 EMIT_ARG(label_assign, l_end);
2038 EMIT_ARG(set_stack_size, stack_size + 1); // force stack size
Damien429d7192013-10-04 19:53:11 +01002039 }
2040}
2041
Damiend99b0522013-12-21 18:17:45 +00002042void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002043 // TODO
2044 assert(0);
2045 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002046 //EMIT_ARG(unary_op, "UNARY_STAR");
Damien429d7192013-10-04 19:53:11 +01002047}
2048
Damiend99b0522013-12-21 18:17:45 +00002049void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002050 c_binary_op(comp, pns, RT_BINARY_OP_OR);
2051}
2052
Damiend99b0522013-12-21 18:17:45 +00002053void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002054 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
2055}
2056
Damiend99b0522013-12-21 18:17:45 +00002057void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002058 c_binary_op(comp, pns, RT_BINARY_OP_AND);
2059}
2060
Damiend99b0522013-12-21 18:17:45 +00002061void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2062 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002063 compile_node(comp, pns->nodes[0]);
2064 for (int i = 1; i + 1 < num_nodes; i += 2) {
2065 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002066 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002067 EMIT_ARG(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00002068 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002069 EMIT_ARG(binary_op, RT_BINARY_OP_RSHIFT);
Damien429d7192013-10-04 19:53:11 +01002070 } else {
2071 // shouldn't happen
2072 assert(0);
2073 }
2074 }
2075}
2076
Damiend99b0522013-12-21 18:17:45 +00002077void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2078 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002079 compile_node(comp, pns->nodes[0]);
2080 for (int i = 1; i + 1 < num_nodes; i += 2) {
2081 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002082 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002083 EMIT_ARG(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002084 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002085 EMIT_ARG(binary_op, RT_BINARY_OP_SUBTRACT);
Damien429d7192013-10-04 19:53:11 +01002086 } else {
2087 // shouldn't happen
2088 assert(0);
2089 }
2090 }
2091}
2092
Damiend99b0522013-12-21 18:17:45 +00002093void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2094 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002095 compile_node(comp, pns->nodes[0]);
2096 for (int i = 1; i + 1 < num_nodes; i += 2) {
2097 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002098 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002099 EMIT_ARG(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002100 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002101 EMIT_ARG(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002102 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002103 EMIT_ARG(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002104 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002105 EMIT_ARG(binary_op, RT_BINARY_OP_MODULO);
Damien429d7192013-10-04 19:53:11 +01002106 } else {
2107 // shouldn't happen
2108 assert(0);
2109 }
2110 }
2111}
2112
Damiend99b0522013-12-21 18:17:45 +00002113void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002114 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002115 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002116 EMIT_ARG(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002117 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002118 EMIT_ARG(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002119 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002120 EMIT_ARG(unary_op, RT_UNARY_OP_INVERT);
Damien429d7192013-10-04 19:53:11 +01002121 } else {
2122 // shouldn't happen
2123 assert(0);
2124 }
2125}
2126
Damien George35e2a4e2014-02-05 00:51:47 +00002127void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
2128 // this is to handle special super() call
2129 comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
2130
2131 compile_generic_all_nodes(comp, pns);
2132}
2133
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002134STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) {
Damien429d7192013-10-04 19:53:11 +01002135 // function to call is on top of stack
2136
Damien George35e2a4e2014-02-05 00:51:47 +00002137#if !MICROPY_EMIT_CPYTHON
2138 // this is to handle special super() call
Damien Georgebbcd49a2014-02-06 20:30:16 +00002139 if (MP_PARSE_NODE_IS_NULL(pn_arglist) && comp->func_arg_is_super && comp->scope_cur->kind == SCOPE_FUNCTION) {
Damien George35e2a4e2014-02-05 00:51:47 +00002140 EMIT_ARG(load_id, MP_QSTR___class__);
2141 // get first argument to function
2142 bool found = false;
2143 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
2144 if (comp->scope_cur->id_info[i].param) {
2145 EMIT_ARG(load_fast, MP_QSTR_, comp->scope_cur->id_info[i].local_num);
2146 found = true;
2147 break;
2148 }
2149 }
2150 if (!found) {
2151 printf("TypeError: super() call cannot find self\n");
2152 return;
2153 }
2154 EMIT_ARG(call_function, 2, 0, false, false);
2155 return;
2156 }
2157#endif
2158
Damien429d7192013-10-04 19:53:11 +01002159 int old_n_arg_keyword = comp->n_arg_keyword;
2160 bool old_have_star_arg = comp->have_star_arg;
2161 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2162 comp->n_arg_keyword = 0;
2163 comp->have_star_arg = false;
2164 comp->have_dbl_star_arg = false;
2165
Damien Georgebbcd49a2014-02-06 20:30:16 +00002166 compile_node(comp, pn_arglist); // arguments to function call; can be null
Damien429d7192013-10-04 19:53:11 +01002167
2168 // compute number of positional arguments
Damien Georgebbcd49a2014-02-06 20:30:16 +00002169 int n_positional = n_positional_extra + list_len(pn_arglist, PN_arglist) - comp->n_arg_keyword;
Damien429d7192013-10-04 19:53:11 +01002170 if (comp->have_star_arg) {
2171 n_positional -= 1;
2172 }
2173 if (comp->have_dbl_star_arg) {
2174 n_positional -= 1;
2175 }
2176
2177 if (is_method_call) {
Damien Georgeb9791222014-01-23 00:34:21 +00002178 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 +01002179 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002180 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 +01002181 }
2182
2183 comp->n_arg_keyword = old_n_arg_keyword;
2184 comp->have_star_arg = old_have_star_arg;
2185 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2186}
2187
Damiend99b0522013-12-21 18:17:45 +00002188void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2189 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002190 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002191 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 +01002192 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002193 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2194 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
Damien Georgeb9791222014-01-23 00:34:21 +00002195 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien Georgebbcd49a2014-02-06 20:30:16 +00002196 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
Damien429d7192013-10-04 19:53:11 +01002197 i += 1;
2198 } else {
2199 compile_node(comp, pns->nodes[i]);
2200 }
Damien George35e2a4e2014-02-05 00:51:47 +00002201 comp->func_arg_is_super = false;
Damien429d7192013-10-04 19:53:11 +01002202 }
2203}
2204
Damiend99b0522013-12-21 18:17:45 +00002205void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002206 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002207 EMIT_ARG(binary_op, RT_BINARY_OP_POWER);
Damien429d7192013-10-04 19:53:11 +01002208}
2209
Damiend99b0522013-12-21 18:17:45 +00002210void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002211 // a list of strings
Damien63321742013-12-10 17:41:49 +00002212
2213 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002214 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002215 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002216 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002217 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002218 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2219 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2220 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002221 if (i == 0) {
2222 string_kind = pn_kind;
2223 } else if (pn_kind != string_kind) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002224 compile_syntax_error(comp, "cannot mix bytes and nonbytes literals");
Damien63321742013-12-10 17:41:49 +00002225 return;
2226 }
Damien George55baff42014-01-21 21:40:13 +00002227 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01002228 }
Damien63321742013-12-10 17:41:49 +00002229
Damien63321742013-12-10 17:41:49 +00002230 // concatenate string/bytes
Damien George55baff42014-01-21 21:40:13 +00002231 byte *q_ptr;
2232 byte *s_dest = qstr_build_start(n_bytes, &q_ptr);
Damien63321742013-12-10 17:41:49 +00002233 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00002234 uint s_len;
2235 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00002236 memcpy(s_dest, s, s_len);
2237 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002238 }
Damien George55baff42014-01-21 21:40:13 +00002239 qstr q = qstr_build_end(q_ptr);
Damien63321742013-12-10 17:41:49 +00002240
Damien Georgeb9791222014-01-23 00:34:21 +00002241 EMIT_ARG(load_const_str, q, string_kind == MP_PARSE_NODE_BYTES);
Damien429d7192013-10-04 19:53:11 +01002242}
2243
2244// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002245void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2246 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2247 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2248 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002249
2250 if (comp->pass == PASS_1) {
2251 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002252 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 +01002253 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002254 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002255 }
2256
2257 // get the scope for this comprehension
2258 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2259
2260 // compile the comprehension
2261 close_over_variables_etc(comp, this_scope, 0, 0);
2262
2263 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2264 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002265 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01002266}
2267
Damiend99b0522013-12-21 18:17:45 +00002268void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2269 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002270 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002271 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2272 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2273 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2274 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2275 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2276 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2277 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002278 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002279 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002280 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002281 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002282 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002283 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002284 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002285 // generator expression
2286 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2287 } else {
2288 // tuple with 2 items
2289 goto tuple_with_2_items;
2290 }
2291 } else {
2292 // tuple with 2 items
2293 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002294 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002295 }
2296 } else {
2297 // parenthesis around a single item, is just that item
2298 compile_node(comp, pns->nodes[0]);
2299 }
2300}
2301
Damiend99b0522013-12-21 18:17:45 +00002302void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2303 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002304 // empty list
Damien Georgeb9791222014-01-23 00:34:21 +00002305 EMIT_ARG(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002306 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2307 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2308 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2309 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2310 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002311 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002312 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002313 compile_node(comp, pns2->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002314 EMIT_ARG(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002315 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002316 // list of many items
2317 compile_node(comp, pns2->nodes[0]);
2318 compile_generic_all_nodes(comp, pns3);
Damien Georgeb9791222014-01-23 00:34:21 +00002319 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
Damiend99b0522013-12-21 18:17:45 +00002320 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002321 // list comprehension
2322 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2323 } else {
2324 // list with 2 items
2325 goto list_with_2_items;
2326 }
2327 } else {
2328 // list with 2 items
2329 list_with_2_items:
2330 compile_node(comp, pns2->nodes[0]);
2331 compile_node(comp, pns2->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00002332 EMIT_ARG(build_list, 2);
Damien429d7192013-10-04 19:53:11 +01002333 }
2334 } else {
2335 // list with 1 item
2336 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002337 EMIT_ARG(build_list, 1);
Damien429d7192013-10-04 19:53:11 +01002338 }
2339}
2340
Damiend99b0522013-12-21 18:17:45 +00002341void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2342 mp_parse_node_t pn = pns->nodes[0];
2343 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002344 // empty dict
Damien Georgeb9791222014-01-23 00:34:21 +00002345 EMIT_ARG(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002346 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2347 pns = (mp_parse_node_struct_t*)pn;
2348 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002349 // dict with one element
Damien Georgeb9791222014-01-23 00:34:21 +00002350 EMIT_ARG(build_map, 1);
Damien429d7192013-10-04 19:53:11 +01002351 compile_node(comp, pn);
2352 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002353 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2354 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2355 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2356 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002357 // dict/set with multiple elements
2358
2359 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002360 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002361 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2362
2363 // first element sets whether it's a dict or set
2364 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002365 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002366 // a dictionary
Damien Georgeb9791222014-01-23 00:34:21 +00002367 EMIT_ARG(build_map, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002368 compile_node(comp, pns->nodes[0]);
2369 EMIT(store_map);
2370 is_dict = true;
2371 } else {
2372 // a set
2373 compile_node(comp, pns->nodes[0]); // 1st value of set
2374 is_dict = false;
2375 }
2376
2377 // process rest of elements
2378 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002379 mp_parse_node_t pn = nodes[i];
2380 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002381 compile_node(comp, pn);
2382 if (is_dict) {
2383 if (!is_key_value) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002384 compile_syntax_error(comp, "?expecting key:value for dictiona");
Damien429d7192013-10-04 19:53:11 +01002385 return;
2386 }
2387 EMIT(store_map);
2388 } else {
2389 if (is_key_value) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002390 compile_syntax_error(comp, "?expecting just a value for s");
Damien429d7192013-10-04 19:53:11 +01002391 return;
2392 }
2393 }
2394 }
2395
2396 // if it's a set, build it
2397 if (!is_dict) {
Damien Georgeb9791222014-01-23 00:34:21 +00002398 EMIT_ARG(build_set, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002399 }
Damiend99b0522013-12-21 18:17:45 +00002400 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002401 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002402 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002403 // a dictionary comprehension
2404 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2405 } else {
2406 // a set comprehension
2407 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2408 }
2409 } else {
2410 // shouldn't happen
2411 assert(0);
2412 }
2413 } else {
2414 // set with one element
2415 goto set_with_one_element;
2416 }
2417 } else {
2418 // set with one element
2419 set_with_one_element:
2420 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002421 EMIT_ARG(build_set, 1);
Damien429d7192013-10-04 19:53:11 +01002422 }
2423}
2424
Damiend99b0522013-12-21 18:17:45 +00002425void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgebbcd49a2014-02-06 20:30:16 +00002426 compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
Damien429d7192013-10-04 19:53:11 +01002427}
2428
Damiend99b0522013-12-21 18:17:45 +00002429void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002430 // object who's index we want is on top of stack
2431 compile_node(comp, pns->nodes[0]); // the index
Damien Georgeb9791222014-01-23 00:34:21 +00002432 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +01002433}
2434
Damiend99b0522013-12-21 18:17:45 +00002435void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002436 // object who's attribute we want is on top of stack
Damien Georgeb9791222014-01-23 00:34:21 +00002437 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002438}
2439
Damiend99b0522013-12-21 18:17:45 +00002440void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2441 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2442 mp_parse_node_t pn = pns->nodes[0];
2443 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002444 // [?:]
Damien Georgeb9791222014-01-23 00:34:21 +00002445 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
2446 EMIT_ARG(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002447 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2448 pns = (mp_parse_node_struct_t*)pn;
2449 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
Damien Georgeb9791222014-01-23 00:34:21 +00002450 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002451 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002452 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002453 // [?::]
Damien Georgeb9791222014-01-23 00:34:21 +00002454 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002455 } else {
2456 // [?::x]
2457 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002458 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002459 }
Damiend99b0522013-12-21 18:17:45 +00002460 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002461 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002462 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2463 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2464 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2465 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002466 // [?:x:]
Damien Georgeb9791222014-01-23 00:34:21 +00002467 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002468 } else {
2469 // [?:x:x]
2470 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002471 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002472 }
2473 } else {
2474 // [?:x]
2475 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002476 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002477 }
2478 } else {
2479 // [?:x]
2480 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002481 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002482 }
2483}
2484
Damiend99b0522013-12-21 18:17:45 +00002485void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002486 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002487 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2488 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002489}
2490
Damiend99b0522013-12-21 18:17:45 +00002491void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgeb9791222014-01-23 00:34:21 +00002492 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002493 compile_subscript_3_helper(comp, pns);
2494}
2495
Damiend99b0522013-12-21 18:17:45 +00002496void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002497 // if this is called then we are compiling a dict key:value pair
2498 compile_node(comp, pns->nodes[1]); // value
2499 compile_node(comp, pns->nodes[0]); // key
2500}
2501
Damiend99b0522013-12-21 18:17:45 +00002502void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002503 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002504 // store class object into class name
Damien Georgeb9791222014-01-23 00:34:21 +00002505 EMIT_ARG(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002506}
2507
Damiend99b0522013-12-21 18:17:45 +00002508void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002509 if (comp->have_star_arg) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002510 compile_syntax_error(comp, "?can't have multiple *x");
Damien429d7192013-10-04 19:53:11 +01002511 return;
2512 }
2513 comp->have_star_arg = true;
2514 compile_node(comp, pns->nodes[0]);
2515}
2516
Damiend99b0522013-12-21 18:17:45 +00002517void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002518 if (comp->have_dbl_star_arg) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002519 compile_syntax_error(comp, "?can't have multiple **x");
Damien429d7192013-10-04 19:53:11 +01002520 return;
2521 }
2522 comp->have_dbl_star_arg = true;
2523 compile_node(comp, pns->nodes[0]);
2524}
2525
Damiend99b0522013-12-21 18:17:45 +00002526void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2527 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2528 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2529 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2530 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002531 compile_syntax_error(comp, "?lhs of keyword argument must be an id");
Damien429d7192013-10-04 19:53:11 +01002532 return;
2533 }
Damien Georgeb9791222014-01-23 00:34:21 +00002534 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002535 compile_node(comp, pns2->nodes[0]);
2536 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002537 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002538 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2539 } else {
2540 // shouldn't happen
2541 assert(0);
2542 }
2543}
2544
Damiend99b0522013-12-21 18:17:45 +00002545void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002546 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002547 compile_syntax_error(comp, "'yield' outside function");
Damien429d7192013-10-04 19:53:11 +01002548 return;
2549 }
Damiend99b0522013-12-21 18:17:45 +00002550 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00002551 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002552 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002553 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2554 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002555 compile_node(comp, pns->nodes[0]);
2556 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002557 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002558 EMIT(yield_from);
2559 } else {
2560 compile_node(comp, pns->nodes[0]);
2561 EMIT(yield_value);
2562 }
2563}
2564
Damiend99b0522013-12-21 18:17:45 +00002565typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002566STATIC compile_function_t compile_function[] = {
Damien429d7192013-10-04 19:53:11 +01002567 NULL,
2568#define nc NULL
2569#define c(f) compile_##f
Damien George1dc76af2014-02-26 16:57:08 +00002570#define DEF_RULE(rule, comp, kind, ...) comp,
Damien429d7192013-10-04 19:53:11 +01002571#include "grammar.h"
2572#undef nc
2573#undef c
2574#undef DEF_RULE
2575};
2576
Damiend99b0522013-12-21 18:17:45 +00002577void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2578 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002579 // pass
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02002580 } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
2581 machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
2582 EMIT_ARG(load_const_small_int, arg);
Damiend99b0522013-12-21 18:17:45 +00002583 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02002584 machine_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +00002585 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002586 case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
Damien Georgeb9791222014-01-23 00:34:21 +00002587 case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
2588 case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
2589 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
2590 case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
Damiend99b0522013-12-21 18:17:45 +00002591 case MP_PARSE_NODE_TOKEN:
2592 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002593 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002594 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002595 // do nothing
2596 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002597 EMIT_ARG(load_const_tok, arg);
Damien91d387d2013-10-09 15:09:52 +01002598 }
2599 break;
Damien429d7192013-10-04 19:53:11 +01002600 default: assert(0);
2601 }
2602 } else {
Damiend99b0522013-12-21 18:17:45 +00002603 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien Georgeb9791222014-01-23 00:34:21 +00002604 EMIT_ARG(set_line_number, pns->source_line);
Damiend99b0522013-12-21 18:17:45 +00002605 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002606 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002607 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien Georgecbd2f742014-01-19 11:48:48 +00002608#if MICROPY_DEBUG_PRINTERS
2609 mp_parse_node_print(pn, 0);
2610#endif
Damien429d7192013-10-04 19:53:11 +01002611 assert(0);
2612 } else {
2613 f(comp, pns);
2614 }
2615 }
2616}
2617
Damiend99b0522013-12-21 18:17:45 +00002618void 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 +01002619 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002620 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002621 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2622 if (MP_PARSE_NODE_IS_ID(pn)) {
2623 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002624 if (comp->have_bare_star) {
2625 // comes after a bare star, so doesn't count as a parameter
2626 } else {
2627 comp->scope_cur->num_params += 1;
2628 }
Damienb14de212013-10-06 00:28:28 +01002629 } else {
Damiend99b0522013-12-21 18:17:45 +00002630 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2631 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2632 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2633 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002634 //int node_index = 1; unused
2635 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002636 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002637 // this parameter has an annotation
2638 pn_annotation = pns->nodes[1];
2639 }
2640 //node_index = 2; unused
2641 }
2642 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002643 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002644 // this parameter has a default value
2645 if (comp->have_bare_star) {
2646 comp->scope_cur->num_dict_params += 1;
2647 } else {
2648 comp->scope_cur->num_default_params += 1;
2649 }
2650 }
2651 */
2652 if (comp->have_bare_star) {
2653 // comes after a bare star, so doesn't count as a parameter
2654 } else {
2655 comp->scope_cur->num_params += 1;
2656 }
Damiend99b0522013-12-21 18:17:45 +00002657 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2658 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002659 // bare star
2660 // TODO see http://www.python.org/dev/peps/pep-3102/
2661 comp->have_bare_star = true;
2662 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002663 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002664 // named star
Damien George8725f8f2014-02-15 19:33:11 +00002665 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002666 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2667 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002668 // named star with annotation
Damien George8725f8f2014-02-15 19:33:11 +00002669 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002670 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2671 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002672 pn_annotation = pns->nodes[1];
2673 } else {
2674 // shouldn't happen
2675 assert(0);
2676 }
Damiend99b0522013-12-21 18:17:45 +00002677 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2678 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2679 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002680 // this parameter has an annotation
2681 pn_annotation = pns->nodes[1];
2682 }
Damien George8725f8f2014-02-15 19:33:11 +00002683 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002684 } else {
Damienb14de212013-10-06 00:28:28 +01002685 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002686 assert(0);
2687 }
Damien429d7192013-10-04 19:53:11 +01002688 }
2689
2690 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002691 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002692 // TODO this parameter has an annotation
2693 }
2694 bool added;
2695 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2696 if (!added) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002697 compile_syntax_error(comp, "?same name used for parameter");
Damien429d7192013-10-04 19:53:11 +01002698 return;
2699 }
2700 id_info->param = true;
2701 id_info->kind = ID_INFO_KIND_LOCAL;
2702 }
2703}
2704
Damiend99b0522013-12-21 18:17:45 +00002705void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002706 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2707}
2708
Damiend99b0522013-12-21 18:17:45 +00002709void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002710 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2711}
2712
Damiend99b0522013-12-21 18:17:45 +00002713void 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 +01002714 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002715 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002716 // no more nested if/for; compile inner expression
2717 compile_node(comp, pn_inner_expr);
2718 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002719 EMIT_ARG(list_append, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002720 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002721 EMIT_ARG(map_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002722 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002723 EMIT_ARG(set_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002724 } else {
2725 EMIT(yield_value);
2726 EMIT(pop_top);
2727 }
Damiend99b0522013-12-21 18:17:45 +00002728 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002729 // if condition
Damiend99b0522013-12-21 18:17:45 +00002730 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002731 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2732 pn_iter = pns_comp_if->nodes[1];
2733 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002734 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002735 // for loop
Damiend99b0522013-12-21 18:17:45 +00002736 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002737 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002738 int l_end2 = comp_next_label(comp);
2739 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002740 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002741 EMIT_ARG(label_assign, l_top2);
2742 EMIT_ARG(for_iter, l_end2);
Damien429d7192013-10-04 19:53:11 +01002743 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2744 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 +00002745 EMIT_ARG(jump, l_top2);
2746 EMIT_ARG(label_assign, l_end2);
Damien429d7192013-10-04 19:53:11 +01002747 EMIT(for_iter_end);
2748 } else {
2749 // shouldn't happen
2750 assert(0);
2751 }
2752}
2753
Damiend99b0522013-12-21 18:17:45 +00002754void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002755 // see http://www.python.org/dev/peps/pep-0257/
2756
2757 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002758 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002759 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002760 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002761 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002762 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2763 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002764 for (int i = 0; i < num_nodes; i++) {
2765 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002766 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 +00002767 // not a newline, so this is the first statement; finish search
2768 break;
2769 }
2770 }
2771 // 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 +00002772 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002773 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002774 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002775 } else {
2776 return;
2777 }
2778
2779 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002780 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2781 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2782 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2783 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2784 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002785 compile_node(comp, pns->nodes[0]); // a doc string
2786 // store doc string
Damien Georgeb9791222014-01-23 00:34:21 +00002787 EMIT_ARG(store_id, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002788 }
2789 }
2790 }
2791}
2792
2793void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2794 comp->pass = pass;
2795 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002796 comp->next_label = 1;
Damien Georgeb9791222014-01-23 00:34:21 +00002797 EMIT_ARG(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002798
2799 if (comp->pass == PASS_1) {
2800 scope->stack_size = 0;
2801 }
2802
Damien5ac1b2e2013-10-18 19:58:12 +01002803#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002804 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002805 scope_print_info(scope);
2806 }
Damien5ac1b2e2013-10-18 19:58:12 +01002807#endif
Damien429d7192013-10-04 19:53:11 +01002808
2809 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002810 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2811 assert(scope->kind == SCOPE_MODULE);
2812 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2813 compile_node(comp, pns->nodes[0]); // compile the expression
2814 EMIT(return_value);
2815 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002816 if (!comp->is_repl) {
2817 check_for_doc_string(comp, scope->pn);
2818 }
Damien429d7192013-10-04 19:53:11 +01002819 compile_node(comp, scope->pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002820 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002821 EMIT(return_value);
2822 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002823 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2824 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2825 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002826
2827 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002828 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002829 if (comp->pass == PASS_1) {
2830 comp->have_bare_star = false;
2831 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2832 }
2833
Paul Sokolovsky2f0b0262014-02-10 02:04:26 +02002834 // pns->nodes[2] is return/whole function annotation
Damien429d7192013-10-04 19:53:11 +01002835
2836 compile_node(comp, pns->nodes[3]); // 3 is function body
2837 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002838 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002839 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002840 EMIT(return_value);
2841 }
2842 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002843 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2844 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2845 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002846
2847 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002848 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002849 if (comp->pass == PASS_1) {
2850 comp->have_bare_star = false;
2851 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2852 }
2853
2854 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2855 EMIT(return_value);
2856 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2857 // a bit of a hack at the moment
2858
Damiend99b0522013-12-21 18:17:45 +00002859 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2860 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2861 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2862 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2863 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002864
Damien George55baff42014-01-21 21:40:13 +00002865 qstr qstr_arg = QSTR_FROM_STR_STATIC(".0");
Damien429d7192013-10-04 19:53:11 +01002866 if (comp->pass == PASS_1) {
2867 bool added;
2868 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2869 assert(added);
2870 id_info->kind = ID_INFO_KIND_LOCAL;
2871 scope->num_params = 1;
2872 }
2873
2874 if (scope->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002875 EMIT_ARG(build_list, 0);
Damien429d7192013-10-04 19:53:11 +01002876 } else if (scope->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002877 EMIT_ARG(build_map, 0);
Damien429d7192013-10-04 19:53:11 +01002878 } else if (scope->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002879 EMIT_ARG(build_set, 0);
Damien429d7192013-10-04 19:53:11 +01002880 }
2881
Damienb05d7072013-10-05 13:37:10 +01002882 int l_end = comp_next_label(comp);
2883 int l_top = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002884 EMIT_ARG(load_id, qstr_arg);
2885 EMIT_ARG(label_assign, l_top);
2886 EMIT_ARG(for_iter, l_end);
Damien429d7192013-10-04 19:53:11 +01002887 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2888 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
Damien Georgeb9791222014-01-23 00:34:21 +00002889 EMIT_ARG(jump, l_top);
2890 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002891 EMIT(for_iter_end);
2892
2893 if (scope->kind == SCOPE_GEN_EXPR) {
Damien Georgeb9791222014-01-23 00:34:21 +00002894 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002895 }
2896 EMIT(return_value);
2897 } else {
2898 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00002899 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2900 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2901 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01002902
2903 if (comp->pass == PASS_1) {
2904 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002905 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01002906 assert(added);
2907 id_info->kind = ID_INFO_KIND_LOCAL;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002908 id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
Damien429d7192013-10-04 19:53:11 +01002909 assert(added);
2910 id_info->kind = ID_INFO_KIND_LOCAL;
2911 id_info->param = true;
2912 scope->num_params = 1; // __locals__ is the parameter
2913 }
2914
Damien Georgeb9791222014-01-23 00:34:21 +00002915 EMIT_ARG(load_id, MP_QSTR___locals__);
Damien429d7192013-10-04 19:53:11 +01002916 EMIT(store_locals);
Damien Georgeb9791222014-01-23 00:34:21 +00002917 EMIT_ARG(load_id, MP_QSTR___name__);
2918 EMIT_ARG(store_id, MP_QSTR___module__);
2919 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
2920 EMIT_ARG(store_id, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01002921
2922 check_for_doc_string(comp, pns->nodes[2]);
2923 compile_node(comp, pns->nodes[2]); // 2 is class body
2924
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002925 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01002926 assert(id != NULL);
2927 if (id->kind == ID_INFO_KIND_LOCAL) {
Damien Georgeb9791222014-01-23 00:34:21 +00002928 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002929 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002930#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00002931 EMIT_ARG(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002932#else
Damien George35e2a4e2014-02-05 00:51:47 +00002933 EMIT_ARG(load_fast, MP_QSTR___class__, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +00002934#endif
Damien429d7192013-10-04 19:53:11 +01002935 }
2936 EMIT(return_value);
2937 }
2938
Damien415eb6f2013-10-05 12:19:06 +01002939 EMIT(end_pass);
Damien826005c2013-10-05 23:17:28 +01002940}
2941
2942void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2943 comp->pass = pass;
2944 comp->scope_cur = scope;
2945 comp->next_label = 1;
2946
2947 if (scope->kind != SCOPE_FUNCTION) {
2948 printf("Error: inline assembler must be a function\n");
2949 return;
2950 }
2951
Damiena2f2f7d2013-10-06 00:14:13 +01002952 if (comp->pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002953 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur);
Damiena2f2f7d2013-10-06 00:14:13 +01002954 }
2955
Damien826005c2013-10-05 23:17:28 +01002956 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002957 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2958 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2959 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002960
Damiend99b0522013-12-21 18:17:45 +00002961 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002962
Damiena2f2f7d2013-10-06 00:14:13 +01002963 // parameters are in pns->nodes[1]
2964 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002965 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002966 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
Damien Georgeb9791222014-01-23 00:34:21 +00002967 scope->num_params = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
Damiena2f2f7d2013-10-06 00:14:13 +01002968 }
2969
Damiend99b0522013-12-21 18:17:45 +00002970 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002971
Damiend99b0522013-12-21 18:17:45 +00002972 mp_parse_node_t pn_body = pns->nodes[3]; // body
2973 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002974 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2975
Damien Georgecbd2f742014-01-19 11:48:48 +00002976 /*
Damien826005c2013-10-05 23:17:28 +01002977 if (comp->pass == PASS_3) {
2978 //printf("----\n");
2979 scope_print_info(scope);
2980 }
Damien Georgecbd2f742014-01-19 11:48:48 +00002981 */
Damien826005c2013-10-05 23:17:28 +01002982
2983 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002984 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2985 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2986 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2987 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2988 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2989 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2990 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2991 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2992 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2993 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2994 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2995 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2996 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002997 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2998
2999 // emit instructions
3000 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00003001 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien Georgef41fdd02014-03-03 23:19:11 +00003002 compile_syntax_error(comp, "inline assembler 'label' requires 1 argument");
Damien826005c2013-10-05 23:17:28 +01003003 return;
3004 }
3005 int lab = comp_next_label(comp);
3006 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00003007 EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01003008 }
3009 } else {
3010 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00003011 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
Damien826005c2013-10-05 23:17:28 +01003012 }
3013 }
3014 }
3015
3016 if (comp->pass > PASS_1) {
3017 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01003018 }
Damien429d7192013-10-04 19:53:11 +01003019}
3020
3021void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
3022 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00003023 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01003024 scope->num_locals = 0;
3025 for (int i = 0; i < scope->id_info_len; i++) {
3026 id_info_t *id = &scope->id_info[i];
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003027 if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01003028 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
3029 continue;
3030 }
3031 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
3032 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
3033 }
Damien9ecbcff2013-12-11 00:41:43 +00003034 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01003035 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
3036 id->local_num = scope->num_locals;
3037 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00003038 }
3039 }
3040
3041 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00003042#if MICROPY_EMIT_CPYTHON
3043 int num_cell = 0;
3044#endif
Damien9ecbcff2013-12-11 00:41:43 +00003045 for (int i = 0; i < scope->id_info_len; i++) {
3046 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00003047#if MICROPY_EMIT_CPYTHON
3048 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00003049 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00003050 id->local_num = num_cell;
3051 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00003052 }
Damien George6baf76e2013-12-30 22:32:17 +00003053#else
3054 // in Micro Python the cells come right after the fast locals
3055 // parameters are not counted here, since they remain at the start
3056 // of the locals, even if they are cell vars
3057 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
3058 id->local_num = scope->num_locals;
3059 scope->num_locals += 1;
3060 }
3061#endif
Damien9ecbcff2013-12-11 00:41:43 +00003062 }
Damien9ecbcff2013-12-11 00:41:43 +00003063
3064 // compute the index of free vars (freevars[idx] in CPython)
3065 // make sure they are in the order of the parent scope
3066 if (scope->parent != NULL) {
3067 int num_free = 0;
3068 for (int i = 0; i < scope->parent->id_info_len; i++) {
3069 id_info_t *id = &scope->parent->id_info[i];
3070 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3071 for (int j = 0; j < scope->id_info_len; j++) {
3072 id_info_t *id2 = &scope->id_info[j];
3073 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00003074 assert(!id2->param); // free vars should not be params
3075#if MICROPY_EMIT_CPYTHON
3076 // in CPython the frees are numbered after the cells
3077 id2->local_num = num_cell + num_free;
3078#else
3079 // in Micro Python the frees come first, before the params
3080 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00003081#endif
3082 num_free += 1;
3083 }
3084 }
3085 }
Damien429d7192013-10-04 19:53:11 +01003086 }
Damien George6baf76e2013-12-30 22:32:17 +00003087#if !MICROPY_EMIT_CPYTHON
3088 // in Micro Python shift all other locals after the free locals
3089 if (num_free > 0) {
3090 for (int i = 0; i < scope->id_info_len; i++) {
3091 id_info_t *id = &scope->id_info[i];
3092 if (id->param || id->kind != ID_INFO_KIND_FREE) {
3093 id->local_num += num_free;
3094 }
3095 }
3096 scope->num_params += num_free; // free vars are counted as params for passing them into the function
3097 scope->num_locals += num_free;
3098 }
3099#endif
Damien429d7192013-10-04 19:53:11 +01003100 }
3101
Damien George8725f8f2014-02-15 19:33:11 +00003102 // compute scope_flags
3103 //scope->scope_flags = 0; since we set some things in parameters
Damien429d7192013-10-04 19:53:11 +01003104 if (scope->kind != SCOPE_MODULE) {
Damien George8725f8f2014-02-15 19:33:11 +00003105 scope->scope_flags |= MP_SCOPE_FLAG_NEWLOCALS;
Damien429d7192013-10-04 19:53:11 +01003106 }
3107 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) {
3108 assert(scope->parent != NULL);
Damien George8725f8f2014-02-15 19:33:11 +00003109 scope->scope_flags |= MP_SCOPE_FLAG_OPTIMISED;
Damien429d7192013-10-04 19:53:11 +01003110
3111 // TODO possibly other ways it can be nested
Damien George08d07552014-01-29 18:58:52 +00003112 // Note that we don't actually use this information at the moment (for CPython compat only)
3113 if ((SCOPE_FUNCTION <= scope->parent->kind && scope->parent->kind <= SCOPE_SET_COMP) || (scope->parent->kind == SCOPE_CLASS && scope->parent->parent->kind == SCOPE_FUNCTION)) {
Damien George8725f8f2014-02-15 19:33:11 +00003114 scope->scope_flags |= MP_SCOPE_FLAG_NESTED;
Damien429d7192013-10-04 19:53:11 +01003115 }
3116 }
3117 int num_free = 0;
3118 for (int i = 0; i < scope->id_info_len; i++) {
3119 id_info_t *id = &scope->id_info[i];
3120 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3121 num_free += 1;
3122 }
3123 }
3124 if (num_free == 0) {
Damien George8725f8f2014-02-15 19:33:11 +00003125 scope->scope_flags |= MP_SCOPE_FLAG_NOFREE;
Damien429d7192013-10-04 19:53:11 +01003126 }
3127}
3128
Damien George08335002014-01-18 23:24:36 +00003129mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003130 compiler_t *comp = m_new(compiler_t, 1);
3131
Damien Georgecbd2f742014-01-19 11:48:48 +00003132 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003133 comp->is_repl = is_repl;
3134 comp->had_error = false;
3135
Damien429d7192013-10-04 19:53:11 +01003136 comp->break_label = 0;
3137 comp->continue_label = 0;
Damien Georgecbddb272014-02-01 20:08:18 +00003138 comp->break_continue_except_level = 0;
3139 comp->cur_except_level = 0;
3140
Damien George35e2a4e2014-02-05 00:51:47 +00003141 comp->func_arg_is_super = false;
3142
Damien429d7192013-10-04 19:53:11 +01003143 comp->scope_head = NULL;
3144 comp->scope_cur = NULL;
3145
Damien826005c2013-10-05 23:17:28 +01003146 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003147 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003148
3149 // set the outer scope
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003150 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003151
Damien826005c2013-10-05 23:17:28 +01003152 // compile pass 1
Damien George35e2a4e2014-02-05 00:51:47 +00003153 comp->emit = emit_pass1_new();
Damien826005c2013-10-05 23:17:28 +01003154 comp->emit_method_table = &emit_pass1_method_table;
3155 comp->emit_inline_asm = NULL;
3156 comp->emit_inline_asm_method_table = NULL;
3157 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003158 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003159 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003160#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003161 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003162 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003163#endif
Damien826005c2013-10-05 23:17:28 +01003164 } else {
3165 compile_scope(comp, s, PASS_1);
3166 }
3167
3168 // update maximim number of labels needed
3169 if (comp->next_label > max_num_labels) {
3170 max_num_labels = comp->next_label;
3171 }
Damien429d7192013-10-04 19:53:11 +01003172 }
3173
Damien826005c2013-10-05 23:17:28 +01003174 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003175 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003176 compile_scope_compute_things(comp, s);
3177 }
3178
Damien826005c2013-10-05 23:17:28 +01003179 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003180 emit_pass1_free(comp->emit);
3181
Damien826005c2013-10-05 23:17:28 +01003182 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003183#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003184 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003185#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003186 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003187#endif
Damien3ef4abb2013-10-12 16:53:13 +01003188#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003189 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003190#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003191#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003192 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003193 if (false) {
3194 // dummy
3195
Damien3ef4abb2013-10-12 16:53:13 +01003196#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003197 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3198 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003199 if (emit_inline_thumb == NULL) {
3200 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3201 }
3202 comp->emit = NULL;
3203 comp->emit_method_table = NULL;
3204 comp->emit_inline_asm = emit_inline_thumb;
3205 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3206 compile_scope_inline_asm(comp, s, PASS_2);
3207 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003208#endif
3209
Damien826005c2013-10-05 23:17:28 +01003210 } else {
Damienc025ebb2013-10-12 14:30:21 +01003211
3212 // choose the emit type
3213
Damien3ef4abb2013-10-12 16:53:13 +01003214#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003215 comp->emit = emit_cpython_new(max_num_labels);
3216 comp->emit_method_table = &emit_cpython_method_table;
3217#else
Damien826005c2013-10-05 23:17:28 +01003218 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003219
3220#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003221 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003222 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003223#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003224 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003225 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003226 }
Damien13ed3a62013-10-08 09:05:10 +01003227 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003228#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003229 if (emit_native == NULL) {
3230 emit_native = emit_native_thumb_new(max_num_labels);
3231 }
3232 comp->emit_method_table = &emit_native_thumb_method_table;
3233#endif
3234 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003235 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003236 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003237#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003238
Damien826005c2013-10-05 23:17:28 +01003239 default:
3240 if (emit_bc == NULL) {
Damien Georgecbd2f742014-01-19 11:48:48 +00003241 emit_bc = emit_bc_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003242 }
3243 comp->emit = emit_bc;
3244 comp->emit_method_table = &emit_bc_method_table;
3245 break;
3246 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003247#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003248
3249 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003250 compile_scope(comp, s, PASS_2);
3251 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003252 }
Damien429d7192013-10-04 19:53:11 +01003253 }
3254
Damien George41d02b62014-01-24 22:42:28 +00003255 // free the emitters
3256#if !MICROPY_EMIT_CPYTHON
3257 if (emit_bc != NULL) {
3258 emit_bc_free(emit_bc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +02003259 }
Damien George41d02b62014-01-24 22:42:28 +00003260#if MICROPY_EMIT_NATIVE
3261 if (emit_native != NULL) {
3262#if MICROPY_EMIT_X64
3263 emit_native_x64_free(emit_native);
3264#elif MICROPY_EMIT_THUMB
3265 emit_native_thumb_free(emit_native);
3266#endif
3267 }
3268#endif
3269#if MICROPY_EMIT_INLINE_THUMB
3270 if (emit_inline_thumb != NULL) {
3271 emit_inline_thumb_free(emit_inline_thumb);
3272 }
3273#endif
3274#endif // !MICROPY_EMIT_CPYTHON
3275
3276 // free the scopes
Paul Sokolovskyfd313582014-01-23 23:05:47 +02003277 uint unique_code_id = module_scope->unique_code_id;
3278 for (scope_t *s = module_scope; s;) {
3279 scope_t *next = s->next;
3280 scope_free(s);
3281 s = next;
3282 }
Damien5ac1b2e2013-10-18 19:58:12 +01003283
Damien George41d02b62014-01-24 22:42:28 +00003284 // free the compiler
3285 bool had_error = comp->had_error;
3286 m_del_obj(compiler_t, comp);
3287
Damien George1fb03172014-01-03 14:22:03 +00003288 if (had_error) {
3289 // TODO return a proper error message
3290 return mp_const_none;
3291 } else {
3292#if MICROPY_EMIT_CPYTHON
3293 // can't create code, so just return true
Damien George41d02b62014-01-24 22:42:28 +00003294 (void)unique_code_id; // to suppress warning that unique_code_id is unused
Damien George1fb03172014-01-03 14:22:03 +00003295 return mp_const_true;
3296#else
3297 // return function that executes the outer module
Paul Sokolovsky90750022014-02-01 15:05:04 +02003298 return rt_make_function_from_id(unique_code_id, MP_OBJ_NULL);
Damien George1fb03172014-01-03 14:22:03 +00003299#endif
3300 }
Damien429d7192013-10-04 19:53:11 +01003301}