blob: 8a8de23a093a31e5a4a78de9cbb871fa4a3be1c7 [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <unistd.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <string.h>
6#include <assert.h>
7
8#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +000010#include "qstr.h"
Damien429d7192013-10-04 19:53:11 +010011#include "lexer.h"
Damien429d7192013-10-04 19:53:11 +010012#include "parse.h"
13#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000014#include "runtime0.h"
Damien429d7192013-10-04 19:53:11 +010015#include "emit.h"
Damien George1fb03172014-01-03 14:22:03 +000016#include "obj.h"
17#include "compile.h"
18#include "runtime.h"
Damien429d7192013-10-04 19:53:11 +010019
20// TODO need to mangle __attr names
21
Damience89a212013-10-15 22:25:17 +010022#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)
23
Damien429d7192013-10-04 19:53:11 +010024typedef enum {
25 PN_none = 0,
Damien George00208ce2014-01-23 00:00:53 +000026#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
Damien429d7192013-10-04 19:53:11 +010027#include "grammar.h"
28#undef DEF_RULE
29 PN_maximum_number_of,
30} pn_kind_t;
31
Damien Georgeb9791222014-01-23 00:34:21 +000032#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
33#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
34#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
35#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
Damien429d7192013-10-04 19:53:11 +010036
Damien6cdd3af2013-10-05 18:08:26 +010037#define EMIT_OPT_NONE (0)
38#define EMIT_OPT_BYTE_CODE (1)
39#define EMIT_OPT_NATIVE_PYTHON (2)
Damien7af3d192013-10-07 00:02:49 +010040#define EMIT_OPT_VIPER (3)
41#define EMIT_OPT_ASM_THUMB (4)
Damien6cdd3af2013-10-05 18:08:26 +010042
Damien429d7192013-10-04 19:53:11 +010043typedef struct _compiler_t {
Damien Georgecbd2f742014-01-19 11:48:48 +000044 qstr source_file;
Damien5ac1b2e2013-10-18 19:58:12 +010045 bool is_repl;
Damien429d7192013-10-04 19:53:11 +010046 pass_kind_t pass;
Damien5ac1b2e2013-10-18 19:58:12 +010047 bool had_error; // try to keep compiler clean from nlr
Damien429d7192013-10-04 19:53:11 +010048
Damienb05d7072013-10-05 13:37:10 +010049 int next_label;
Damienb05d7072013-10-05 13:37:10 +010050
Damien429d7192013-10-04 19:53:11 +010051 int break_label;
52 int continue_label;
Damien Georgecbddb272014-02-01 20:08:18 +000053 int break_continue_except_level;
54 int cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
Damien429d7192013-10-04 19:53:11 +010055
56 int n_arg_keyword;
57 bool have_star_arg;
58 bool have_dbl_star_arg;
59 bool have_bare_star;
60 int param_pass;
61 int param_pass_num_dict_params;
62 int param_pass_num_default_params;
63
Damien George35e2a4e2014-02-05 00:51:47 +000064 bool func_arg_is_super; // used to compile special case of super() function call
65
Damien429d7192013-10-04 19:53:11 +010066 scope_t *scope_head;
67 scope_t *scope_cur;
68
Damien6cdd3af2013-10-05 18:08:26 +010069 emit_t *emit; // current emitter
70 const emit_method_table_t *emit_method_table; // current emit method table
Damien826005c2013-10-05 23:17:28 +010071
72 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
73 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 +010074} compiler_t;
75
Damiend99b0522013-12-21 18:17:45 +000076mp_parse_node_t fold_constants(mp_parse_node_t pn) {
77 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
78 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
79 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +010080
81 // fold arguments first
82 for (int i = 0; i < n; i++) {
83 pns->nodes[i] = fold_constants(pns->nodes[i]);
84 }
85
Damiend99b0522013-12-21 18:17:45 +000086 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +010087 case PN_shift_expr:
Damiend99b0522013-12-21 18:17:45 +000088 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
89 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
90 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
91 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
Damien3ef4abb2013-10-12 16:53:13 +010092#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +010093 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +000094 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
Damien0efb3a12013-10-12 16:16:56 +010095#endif
Damiend99b0522013-12-21 18:17:45 +000096 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
97 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien429d7192013-10-04 19:53:11 +010098 } else {
99 // shouldn't happen
100 assert(0);
101 }
102 }
103 break;
104
105 case PN_arith_expr:
Damien0efb3a12013-10-12 16:16:56 +0100106 // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
Damiend99b0522013-12-21 18:17:45 +0000107 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
108 machine_int_t arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
109 machine_int_t arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
Damien0efb3a12013-10-12 16:16:56 +0100110 machine_int_t res;
Damiend99b0522013-12-21 18:17:45 +0000111 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100112 res = arg0 + arg1;
Damiend99b0522013-12-21 18:17:45 +0000113 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100114 res = arg0 - arg1;
Damien429d7192013-10-04 19:53:11 +0100115 } else {
116 // shouldn't happen
117 assert(0);
Damien0efb3a12013-10-12 16:16:56 +0100118 res = 0;
119 }
Damiend99b0522013-12-21 18:17:45 +0000120 if (MP_FIT_SMALL_INT(res)) {
121 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
Damien429d7192013-10-04 19:53:11 +0100122 }
123 }
124 break;
125
126 case PN_term:
Damiend99b0522013-12-21 18:17:45 +0000127 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
128 int arg0 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
129 int arg1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[2]);
130 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien3ef4abb2013-10-12 16:53:13 +0100131#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100132 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000133 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
Damien0efb3a12013-10-12 16:16:56 +0100134#endif
Damiend99b0522013-12-21 18:17:45 +0000135 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +0100136 ; // pass
Damiend99b0522013-12-21 18:17:45 +0000137 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
Damien0efb3a12013-10-12 16:16:56 +0100138 // XXX implement this properly as Python's % operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000139 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1);
140 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
Damien0efb3a12013-10-12 16:16:56 +0100141 // XXX implement this properly as Python's // operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000142 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1);
Damien429d7192013-10-04 19:53:11 +0100143 } else {
144 // shouldn't happen
145 assert(0);
146 }
147 }
148 break;
149
150 case PN_factor_2:
Damiend99b0522013-12-21 18:17:45 +0000151 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
152 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
153 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
154 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
155 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
156 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
157 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
158 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien429d7192013-10-04 19:53:11 +0100159 } else {
160 // shouldn't happen
161 assert(0);
162 }
163 }
164 break;
165
Damien3ef4abb2013-10-12 16:53:13 +0100166#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +0100167 case PN_power:
Damien0efb3a12013-10-12 16:16:56 +0100168 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000169 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])) {
170 mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
171 if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
172 int power = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100173 if (power >= 0) {
174 int ans = 1;
Damiend99b0522013-12-21 18:17:45 +0000175 int base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100176 for (; power > 0; power--) {
177 ans *= base;
178 }
Damiend99b0522013-12-21 18:17:45 +0000179 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien429d7192013-10-04 19:53:11 +0100180 }
181 }
182 }
183 break;
Damien0efb3a12013-10-12 16:16:56 +0100184#endif
Damien429d7192013-10-04 19:53:11 +0100185 }
186 }
187
188 return pn;
189}
190
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200191STATIC 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 +0000192void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100193
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200194STATIC int comp_next_label(compiler_t *comp) {
Damienb05d7072013-10-05 13:37:10 +0100195 return comp->next_label++;
196}
197
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200198STATIC 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 +0000199 scope_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
Damien429d7192013-10-04 19:53:11 +0100200 scope->parent = comp->scope_cur;
201 scope->next = NULL;
202 if (comp->scope_head == NULL) {
203 comp->scope_head = scope;
204 } else {
205 scope_t *s = comp->scope_head;
206 while (s->next != NULL) {
207 s = s->next;
208 }
209 s->next = scope;
210 }
211 return scope;
212}
213
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200214STATIC int list_len(mp_parse_node_t pn, int pn_kind) {
Damiend99b0522013-12-21 18:17:45 +0000215 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100216 return 0;
Damiend99b0522013-12-21 18:17:45 +0000217 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100218 return 1;
219 } else {
Damiend99b0522013-12-21 18:17:45 +0000220 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
221 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100222 return 1;
223 } else {
Damiend99b0522013-12-21 18:17:45 +0000224 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100225 }
226 }
227}
228
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200229STATIC 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 +0000230 if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
231 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
232 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100233 for (int i = 0; i < num_nodes; i++) {
234 f(comp, pns->nodes[i]);
235 }
Damiend99b0522013-12-21 18:17:45 +0000236 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100237 f(comp, pn);
238 }
239}
240
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200241STATIC int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
Damiend99b0522013-12-21 18:17:45 +0000242 if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100243 *nodes = NULL;
244 return 0;
Damiend99b0522013-12-21 18:17:45 +0000245 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100246 *nodes = pn;
247 return 1;
248 } else {
Damiend99b0522013-12-21 18:17:45 +0000249 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
250 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100251 *nodes = pn;
252 return 1;
253 } else {
254 *nodes = pns->nodes;
Damiend99b0522013-12-21 18:17:45 +0000255 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100256 }
257 }
258}
259
Damiend99b0522013-12-21 18:17:45 +0000260void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100261}
262
Damiend99b0522013-12-21 18:17:45 +0000263void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
264 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100265 for (int i = 0; i < num_nodes; i++) {
266 compile_node(comp, pns->nodes[i]);
267 }
268}
269
Damien3ef4abb2013-10-12 16:53:13 +0100270#if MICROPY_EMIT_CPYTHON
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200271STATIC bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000272 if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100273 return false;
274 }
Damiend99b0522013-12-21 18:17:45 +0000275 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +0100276 return false;
277 }
278 return true;
279}
280
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200281STATIC void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
Damien George55baff42014-01-21 21:40:13 +0000282 uint len;
283 const byte *str = qstr_data(qstr, &len);
Damien02f89412013-12-12 15:13:36 +0000284 bool has_single_quote = false;
285 bool has_double_quote = false;
286 for (int i = 0; i < len; i++) {
287 if (str[i] == '\'') {
288 has_single_quote = true;
289 } else if (str[i] == '"') {
290 has_double_quote = true;
291 }
292 }
293 if (bytes) {
294 vstr_printf(vstr, "b");
295 }
296 bool quote_single = false;
297 if (has_single_quote && !has_double_quote) {
298 vstr_printf(vstr, "\"");
299 } else {
300 quote_single = true;
301 vstr_printf(vstr, "'");
302 }
303 for (int i = 0; i < len; i++) {
304 if (str[i] == '\n') {
305 vstr_printf(vstr, "\\n");
306 } else if (str[i] == '\\') {
307 vstr_printf(vstr, "\\\\");
308 } else if (str[i] == '\'' && quote_single) {
309 vstr_printf(vstr, "\\'");
310 } else {
311 vstr_printf(vstr, "%c", str[i]);
312 }
313 }
314 if (has_single_quote && !has_double_quote) {
315 vstr_printf(vstr, "\"");
316 } else {
317 vstr_printf(vstr, "'");
318 }
319}
320
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200321STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
Damiend99b0522013-12-21 18:17:45 +0000322 assert(MP_PARSE_NODE_IS_LEAF(pn));
323 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
324 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
325 case MP_PARSE_NODE_ID: assert(0);
326 case MP_PARSE_NODE_SMALL_INT: vstr_printf(vstr, "%d", arg); break;
327 case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
328 case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
329 case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
330 case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
331 case MP_PARSE_NODE_TOKEN:
Damien429d7192013-10-04 19:53:11 +0100332 switch (arg) {
Damiend99b0522013-12-21 18:17:45 +0000333 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
334 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
335 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
Damien429d7192013-10-04 19:53:11 +0100336 default: assert(0);
337 }
338 break;
339 default: assert(0);
340 }
341}
342
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200343STATIC 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 +0100344 int n = 0;
345 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000346 n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien429d7192013-10-04 19:53:11 +0100347 }
348 int total = n;
349 bool is_const = true;
Damiend99b0522013-12-21 18:17:45 +0000350 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100351 total += 1;
Damien3a205172013-10-12 15:01:56 +0100352 if (!cpython_c_tuple_is_const(pn)) {
Damien429d7192013-10-04 19:53:11 +0100353 is_const = false;
354 }
355 }
356 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100357 if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien429d7192013-10-04 19:53:11 +0100358 is_const = false;
359 break;
360 }
361 }
362 if (total > 0 && is_const) {
363 bool need_comma = false;
Damien02f89412013-12-12 15:13:36 +0000364 vstr_t *vstr = vstr_new();
365 vstr_printf(vstr, "(");
Damiend99b0522013-12-21 18:17:45 +0000366 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien02f89412013-12-12 15:13:36 +0000367 cpython_c_tuple_emit_const(comp, pn, vstr);
Damien429d7192013-10-04 19:53:11 +0100368 need_comma = true;
369 }
370 for (int i = 0; i < n; i++) {
371 if (need_comma) {
Damien02f89412013-12-12 15:13:36 +0000372 vstr_printf(vstr, ", ");
Damien429d7192013-10-04 19:53:11 +0100373 }
Damien02f89412013-12-12 15:13:36 +0000374 cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien429d7192013-10-04 19:53:11 +0100375 need_comma = true;
376 }
377 if (total == 1) {
Damien02f89412013-12-12 15:13:36 +0000378 vstr_printf(vstr, ",)");
Damien429d7192013-10-04 19:53:11 +0100379 } else {
Damien02f89412013-12-12 15:13:36 +0000380 vstr_printf(vstr, ")");
Damien429d7192013-10-04 19:53:11 +0100381 }
Damien Georgeb9791222014-01-23 00:34:21 +0000382 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +0000383 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +0100384 } else {
Damiend99b0522013-12-21 18:17:45 +0000385 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100386 compile_node(comp, pn);
387 }
388 for (int i = 0; i < n; i++) {
389 compile_node(comp, pns_list->nodes[i]);
390 }
Damien Georgeb9791222014-01-23 00:34:21 +0000391 EMIT_ARG(build_tuple, total);
Damien429d7192013-10-04 19:53:11 +0100392 }
393}
Damien3a205172013-10-12 15:01:56 +0100394#endif
395
396// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
Damiend99b0522013-12-21 18:17:45 +0000397void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3ef4abb2013-10-12 16:53:13 +0100398#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100399 cpython_c_tuple(comp, pn, pns_list);
400#else
401 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000402 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100403 compile_node(comp, pn);
404 total += 1;
405 }
406 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000407 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100408 for (int i = 0; i < n; i++) {
409 compile_node(comp, pns_list->nodes[i]);
410 }
411 total += n;
412 }
Damien Georgeb9791222014-01-23 00:34:21 +0000413 EMIT_ARG(build_tuple, total);
Damien3a205172013-10-12 15:01:56 +0100414#endif
415}
Damien429d7192013-10-04 19:53:11 +0100416
Damiend99b0522013-12-21 18:17:45 +0000417void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100418 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000419 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100420}
421
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200422STATIC bool node_is_const_false(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000423 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
424 // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100425}
426
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200427STATIC bool node_is_const_true(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000428 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_ARG(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100429}
430
Damien3ef4abb2013-10-12 16:53:13 +0100431#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100432// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200433STATIC 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 +0100434 if (node_is_const_false(pn)) {
435 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000436 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100437 }
438 return;
439 } else if (node_is_const_true(pn)) {
440 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000441 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100442 }
443 return;
Damiend99b0522013-12-21 18:17:45 +0000444 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
445 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
446 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
447 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien429d7192013-10-04 19:53:11 +0100448 if (jump_if == false) {
Damienb05d7072013-10-05 13:37:10 +0100449 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100450 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100451 cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien429d7192013-10-04 19:53:11 +0100452 }
Damien3a205172013-10-12 15:01:56 +0100453 cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000454 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100455 } else {
456 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100457 cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100458 }
459 }
460 return;
Damiend99b0522013-12-21 18:17:45 +0000461 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien429d7192013-10-04 19:53:11 +0100462 if (jump_if == false) {
463 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100464 cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100465 }
466 } else {
Damienb05d7072013-10-05 13:37:10 +0100467 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100468 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100469 cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien429d7192013-10-04 19:53:11 +0100470 }
Damien3a205172013-10-12 15:01:56 +0100471 cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000472 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100473 }
474 return;
Damiend99b0522013-12-21 18:17:45 +0000475 } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100476 cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien429d7192013-10-04 19:53:11 +0100477 return;
478 }
479 }
480
481 // nothing special, fall back to default compiling for node and jump
482 compile_node(comp, pn);
483 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000484 EMIT_ARG(pop_jump_if_false, label);
Damien429d7192013-10-04 19:53:11 +0100485 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000486 EMIT_ARG(pop_jump_if_true, label);
Damien429d7192013-10-04 19:53:11 +0100487 }
488}
Damien3a205172013-10-12 15:01:56 +0100489#endif
Damien429d7192013-10-04 19:53:11 +0100490
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200491STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien3ef4abb2013-10-12 16:53:13 +0100492#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100493 cpython_c_if_cond(comp, pn, jump_if, label, false);
494#else
495 if (node_is_const_false(pn)) {
496 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000497 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100498 }
499 return;
500 } else if (node_is_const_true(pn)) {
501 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000502 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100503 }
504 return;
Damiend99b0522013-12-21 18:17:45 +0000505 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
506 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
507 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
508 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100509 if (jump_if == false) {
510 int label2 = comp_next_label(comp);
511 for (int i = 0; i < n - 1; i++) {
512 c_if_cond(comp, pns->nodes[i], true, label2);
513 }
514 c_if_cond(comp, pns->nodes[n - 1], false, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000515 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100516 } else {
517 for (int i = 0; i < n; i++) {
518 c_if_cond(comp, pns->nodes[i], true, label);
519 }
520 }
521 return;
Damiend99b0522013-12-21 18:17:45 +0000522 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100523 if (jump_if == false) {
524 for (int i = 0; i < n; i++) {
525 c_if_cond(comp, pns->nodes[i], false, label);
526 }
527 } else {
528 int label2 = comp_next_label(comp);
529 for (int i = 0; i < n - 1; i++) {
530 c_if_cond(comp, pns->nodes[i], false, label2);
531 }
532 c_if_cond(comp, pns->nodes[n - 1], true, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000533 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100534 }
535 return;
Damiend99b0522013-12-21 18:17:45 +0000536 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100537 c_if_cond(comp, pns->nodes[0], !jump_if, label);
538 return;
539 }
540 }
541
542 // nothing special, fall back to default compiling for node and jump
543 compile_node(comp, pn);
544 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000545 EMIT_ARG(pop_jump_if_false, label);
Damien3a205172013-10-12 15:01:56 +0100546 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000547 EMIT_ARG(pop_jump_if_true, label);
Damien3a205172013-10-12 15:01:56 +0100548 }
549#endif
Damien429d7192013-10-04 19:53:11 +0100550}
551
552typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damiend99b0522013-12-21 18:17:45 +0000553void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100554
Damiend99b0522013-12-21 18:17:45 +0000555void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100556 if (assign_kind != ASSIGN_AUG_STORE) {
557 compile_node(comp, pns->nodes[0]);
558 }
559
Damiend99b0522013-12-21 18:17:45 +0000560 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
561 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
562 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
563 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100564 if (assign_kind != ASSIGN_AUG_STORE) {
565 for (int i = 0; i < n - 1; i++) {
566 compile_node(comp, pns1->nodes[i]);
567 }
568 }
Damiend99b0522013-12-21 18:17:45 +0000569 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
570 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100571 }
Damiend99b0522013-12-21 18:17:45 +0000572 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +0100573 printf("SyntaxError: can't assign to function call\n");
574 return;
Damiend99b0522013-12-21 18:17:45 +0000575 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100576 if (assign_kind == ASSIGN_AUG_STORE) {
577 EMIT(rot_three);
578 EMIT(store_subscr);
579 } else {
580 compile_node(comp, pns1->nodes[0]);
581 if (assign_kind == ASSIGN_AUG_LOAD) {
582 EMIT(dup_top_two);
Damien Georgeb9791222014-01-23 00:34:21 +0000583 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +0100584 } else {
585 EMIT(store_subscr);
586 }
587 }
Damiend99b0522013-12-21 18:17:45 +0000588 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
589 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100590 if (assign_kind == ASSIGN_AUG_LOAD) {
591 EMIT(dup_top);
Damien Georgeb9791222014-01-23 00:34:21 +0000592 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100593 } else {
594 if (assign_kind == ASSIGN_AUG_STORE) {
595 EMIT(rot_two);
596 }
Damien Georgeb9791222014-01-23 00:34:21 +0000597 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100598 }
599 } else {
600 // shouldn't happen
601 assert(0);
602 }
603 } else {
604 // shouldn't happen
605 assert(0);
606 }
607
Damiend99b0522013-12-21 18:17:45 +0000608 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100609 // SyntaxError, cannot assign
610 assert(0);
611 }
612}
613
Damiend99b0522013-12-21 18:17:45 +0000614void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
Damien429d7192013-10-04 19:53:11 +0100615 assert(n >= 0);
616 int have_star_index = -1;
617 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000618 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) {
Damien429d7192013-10-04 19:53:11 +0100619 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000620 EMIT_ARG(unpack_ex, i, n - i - 1);
Damien429d7192013-10-04 19:53:11 +0100621 have_star_index = i;
622 } else {
623 printf("SyntaxError: two starred expressions in assignment\n");
624 return;
625 }
626 }
627 }
628 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000629 EMIT_ARG(unpack_sequence, n);
Damien429d7192013-10-04 19:53:11 +0100630 }
631 for (int i = 0; i < n; i++) {
632 if (i == have_star_index) {
Damiend99b0522013-12-21 18:17:45 +0000633 c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100634 } else {
635 c_assign(comp, nodes[i], ASSIGN_STORE);
636 }
637 }
638}
639
640// assigns top of stack to pn
Damiend99b0522013-12-21 18:17:45 +0000641void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100642 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +0000643 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100644 assert(0);
Damiend99b0522013-12-21 18:17:45 +0000645 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
646 if (MP_PARSE_NODE_IS_ID(pn)) {
647 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100648 switch (assign_kind) {
649 case ASSIGN_STORE:
650 case ASSIGN_AUG_STORE:
Damien Georgeb9791222014-01-23 00:34:21 +0000651 EMIT_ARG(store_id, arg);
Damien429d7192013-10-04 19:53:11 +0100652 break;
653 case ASSIGN_AUG_LOAD:
Damien Georgeb9791222014-01-23 00:34:21 +0000654 EMIT_ARG(load_id, arg);
Damien429d7192013-10-04 19:53:11 +0100655 break;
656 }
657 } else {
658 printf("SyntaxError: can't assign to literal\n");
659 return;
660 }
661 } else {
Damiend99b0522013-12-21 18:17:45 +0000662 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
663 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +0100664 case PN_power:
665 // lhs is an index or attribute
666 c_assign_power(comp, pns, assign_kind);
667 break;
668
669 case PN_testlist_star_expr:
670 case PN_exprlist:
671 // lhs is a tuple
672 if (assign_kind != ASSIGN_STORE) {
673 goto bad_aug;
674 }
Damiend99b0522013-12-21 18:17:45 +0000675 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100676 break;
677
678 case PN_atom_paren:
679 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000680 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100681 // empty tuple
682 printf("SyntaxError: can't assign to ()\n");
683 return;
Damiend99b0522013-12-21 18:17:45 +0000684 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
685 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100686 goto testlist_comp;
687 } else {
688 // parenthesis around 1 item, is just that item
689 pn = pns->nodes[0];
690 goto tail_recursion;
691 }
692 break;
693
694 case PN_atom_bracket:
695 // lhs is something in brackets
696 if (assign_kind != ASSIGN_STORE) {
697 goto bad_aug;
698 }
Damiend99b0522013-12-21 18:17:45 +0000699 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100700 // empty list, assignment allowed
701 c_assign_tuple(comp, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000702 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
703 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100704 goto testlist_comp;
705 } else {
706 // brackets around 1 item
707 c_assign_tuple(comp, 1, &pns->nodes[0]);
708 }
709 break;
710
711 default:
Damiend99b0522013-12-21 18:17:45 +0000712 printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien429d7192013-10-04 19:53:11 +0100713 assert(0);
714 }
715 return;
716
717 testlist_comp:
718 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000719 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
720 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
721 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100722 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000723 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100724 c_assign_tuple(comp, 1, &pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000725 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100726 // sequence of many items
727 // TODO call c_assign_tuple instead
Damiend99b0522013-12-21 18:17:45 +0000728 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
Damien Georgeb9791222014-01-23 00:34:21 +0000729 EMIT_ARG(unpack_sequence, 1 + n);
Damien429d7192013-10-04 19:53:11 +0100730 c_assign(comp, pns->nodes[0], ASSIGN_STORE);
731 for (int i = 0; i < n; i++) {
732 c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
733 }
Damiend99b0522013-12-21 18:17:45 +0000734 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +0100735 // TODO not implemented
736 assert(0);
737 } else {
738 // sequence with 2 items
739 goto sequence_with_2_items;
740 }
741 } else {
742 // sequence with 2 items
743 sequence_with_2_items:
744 c_assign_tuple(comp, 2, pns->nodes);
745 }
746 return;
747 }
748 return;
749
750 bad_aug:
751 printf("SyntaxError: illegal expression for augmented assignment\n");
752}
753
754// stuff for lambda and comprehensions and generators
755void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
756 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000757 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100758 int nfree = 0;
759 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000760 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
761 id_info_t *id = &comp->scope_cur->id_info[i];
762 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
763 for (int j = 0; j < this_scope->id_info_len; j++) {
764 id_info_t *id2 = &this_scope->id_info[j];
765 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +0000766#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +0000767 EMIT_ARG(load_closure, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000768#else
769 // in Micro Python we load closures using LOAD_FAST
Damien Georgeb9791222014-01-23 00:34:21 +0000770 EMIT_ARG(load_fast, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000771#endif
Damien318aec62013-12-10 18:28:17 +0000772 nfree += 1;
773 }
774 }
Damien429d7192013-10-04 19:53:11 +0100775 }
776 }
777 }
778 if (nfree > 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000779 EMIT_ARG(build_tuple, nfree);
Damien429d7192013-10-04 19:53:11 +0100780 }
781
782 // make the function/closure
783 if (nfree == 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000784 EMIT_ARG(make_function, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100785 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000786 EMIT_ARG(make_closure, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100787 }
788}
789
Damiend99b0522013-12-21 18:17:45 +0000790void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
791 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
792 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
793 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100794 // this parameter has a default value
795 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
796 if (comp->have_bare_star) {
797 comp->param_pass_num_dict_params += 1;
798 if (comp->param_pass == 1) {
Damien Georgeb9791222014-01-23 00:34:21 +0000799 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100800 compile_node(comp, pns->nodes[2]);
801 }
802 } else {
803 comp->param_pass_num_default_params += 1;
804 if (comp->param_pass == 2) {
805 compile_node(comp, pns->nodes[2]);
806 }
807 }
808 }
Damiend99b0522013-12-21 18:17:45 +0000809 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
810 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
811 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100812 // bare star
813 comp->have_bare_star = true;
814 }
815 }
816}
817
818// leaves function object on stack
819// returns function name
Damiend99b0522013-12-21 18:17:45 +0000820qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100821 if (comp->pass == PASS_1) {
822 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000823 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100824 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000825 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100826 }
827
828 // save variables (probably don't need to do this, since we can't have nested definitions..?)
829 bool old_have_bare_star = comp->have_bare_star;
830 int old_param_pass = comp->param_pass;
831 int old_param_pass_num_dict_params = comp->param_pass_num_dict_params;
832 int old_param_pass_num_default_params = comp->param_pass_num_default_params;
833
834 // compile default parameters
835 comp->have_bare_star = false;
836 comp->param_pass = 1; // pass 1 does any default parameters after bare star
837 comp->param_pass_num_dict_params = 0;
838 comp->param_pass_num_default_params = 0;
839 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
840 comp->have_bare_star = false;
841 comp->param_pass = 2; // pass 2 does any default parameters before bare star
842 comp->param_pass_num_dict_params = 0;
843 comp->param_pass_num_default_params = 0;
844 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
845
846 // get the scope for this function
847 scope_t *fscope = (scope_t*)pns->nodes[4];
848
849 // make the function
850 close_over_variables_etc(comp, fscope, comp->param_pass_num_dict_params, comp->param_pass_num_default_params);
851
852 // restore variables
853 comp->have_bare_star = old_have_bare_star;
854 comp->param_pass = old_param_pass;
855 comp->param_pass_num_dict_params = old_param_pass_num_dict_params;
856 comp->param_pass_num_default_params = old_param_pass_num_default_params;
857
858 // return its name (the 'f' in "def f(...):")
859 return fscope->simple_name;
860}
861
862// leaves class object on stack
863// returns class name
Damiend99b0522013-12-21 18:17:45 +0000864qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100865 if (comp->pass == PASS_1) {
866 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000867 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100868 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000869 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100870 }
871
872 EMIT(load_build_class);
873
874 // scope for this class
875 scope_t *cscope = (scope_t*)pns->nodes[3];
876
877 // compile the class
878 close_over_variables_etc(comp, cscope, 0, 0);
879
880 // get its name
Damien Georgeb9791222014-01-23 00:34:21 +0000881 EMIT_ARG(load_const_id, cscope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100882
883 // nodes[1] has parent classes, if any
Damien Georgebbcd49a2014-02-06 20:30:16 +0000884 comp->func_arg_is_super = false;
885 compile_trailer_paren_helper(comp, pns->nodes[1], false, 2);
Damien429d7192013-10-04 19:53:11 +0100886
887 // return its name (the 'C' in class C(...):")
888 return cscope->simple_name;
889}
890
Damien6cdd3af2013-10-05 18:08:26 +0100891// returns true if it was a built-in decorator (even if the built-in had an error)
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200892STATIC 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 +0000893 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100894 return false;
895 }
896
897 if (name_len != 2) {
898 printf("SyntaxError: invalid micropython decorator\n");
899 return true;
900 }
901
Damiend99b0522013-12-21 18:17:45 +0000902 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000903 if (attr == MP_QSTR_byte_code) {
Damien5ac1b2e2013-10-18 19:58:12 +0100904 *emit_options = EMIT_OPT_BYTE_CODE;
Damience89a212013-10-15 22:25:17 +0100905#if MICROPY_EMIT_NATIVE
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000906 } else if (attr == MP_QSTR_native) {
Damien6cdd3af2013-10-05 18:08:26 +0100907 *emit_options = EMIT_OPT_NATIVE_PYTHON;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000908 } else if (attr == MP_QSTR_viper) {
Damien7af3d192013-10-07 00:02:49 +0100909 *emit_options = EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100910#endif
Damien3ef4abb2013-10-12 16:53:13 +0100911#if MICROPY_EMIT_INLINE_THUMB
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000912 } else if (attr == MP_QSTR_asm_thumb) {
Damien5bfb7592013-10-05 18:41:24 +0100913 *emit_options = EMIT_OPT_ASM_THUMB;
Damienc025ebb2013-10-12 14:30:21 +0100914#endif
Damien6cdd3af2013-10-05 18:08:26 +0100915 } else {
Damience89a212013-10-15 22:25:17 +0100916 printf("SyntaxError: invalid micropython decorator '%s'\n", qstr_str(attr));
Damien6cdd3af2013-10-05 18:08:26 +0100917 }
918
919 return true;
920}
921
Damiend99b0522013-12-21 18:17:45 +0000922void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100923 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000924 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +0100925 int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
926
Damien6cdd3af2013-10-05 18:08:26 +0100927 // inherit emit options for this function/class definition
928 uint emit_options = comp->scope_cur->emit_options;
929
930 // compile each decorator
931 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100932 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000933 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
934 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100935
936 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +0000937 mp_parse_node_t *name_nodes;
Damien6cdd3af2013-10-05 18:08:26 +0100938 int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
939
940 // check for built-in decorators
941 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
942 // this was a built-in
943 num_built_in_decorators += 1;
944
945 } else {
946 // not a built-in, compile normally
947
948 // compile the decorator function
949 compile_node(comp, name_nodes[0]);
950 for (int i = 1; i < name_len; i++) {
Damiend99b0522013-12-21 18:17:45 +0000951 assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be
Damien Georgeb9791222014-01-23 00:34:21 +0000952 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i]));
Damien6cdd3af2013-10-05 18:08:26 +0100953 }
954
955 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +0000956 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +0100957 // call the decorator function with the arguments in nodes[1]
Damien George35e2a4e2014-02-05 00:51:47 +0000958 comp->func_arg_is_super = false;
Damien6cdd3af2013-10-05 18:08:26 +0100959 compile_node(comp, pns_decorator->nodes[1]);
960 }
Damien429d7192013-10-04 19:53:11 +0100961 }
962 }
963
964 // compile the body (funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +0000965 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +0100966 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +0000967 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100968 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Damiend99b0522013-12-21 18:17:45 +0000969 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100970 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +0100971 } else {
972 // shouldn't happen
973 assert(0);
974 }
975
976 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +0100977 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +0000978 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +0100979 }
980
981 // store func/class object into name
Damien Georgeb9791222014-01-23 00:34:21 +0000982 EMIT_ARG(store_id, body_name);
Damien429d7192013-10-04 19:53:11 +0100983}
984
Damiend99b0522013-12-21 18:17:45 +0000985void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +0100986 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +0100987 // store function object into function name
Damien Georgeb9791222014-01-23 00:34:21 +0000988 EMIT_ARG(store_id, fname);
Damien429d7192013-10-04 19:53:11 +0100989}
990
Damiend99b0522013-12-21 18:17:45 +0000991void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
992 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +0000993 EMIT_ARG(delete_id, MP_PARSE_NODE_LEAF_ARG(pn));
Damiend99b0522013-12-21 18:17:45 +0000994 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
995 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +0100996
997 compile_node(comp, pns->nodes[0]); // base of the power node
998
Damiend99b0522013-12-21 18:17:45 +0000999 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1000 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1001 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
1002 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001003 for (int i = 0; i < n - 1; i++) {
1004 compile_node(comp, pns1->nodes[i]);
1005 }
Damiend99b0522013-12-21 18:17:45 +00001006 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
1007 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +01001008 }
Damiend99b0522013-12-21 18:17:45 +00001009 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +01001010 // SyntaxError: can't delete a function call
1011 assert(0);
Damiend99b0522013-12-21 18:17:45 +00001012 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +01001013 compile_node(comp, pns1->nodes[0]);
1014 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +00001015 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
1016 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien Georgeb9791222014-01-23 00:34:21 +00001017 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001018 } else {
1019 // shouldn't happen
1020 assert(0);
1021 }
1022 } else {
1023 // shouldn't happen
1024 assert(0);
1025 }
1026
Damiend99b0522013-12-21 18:17:45 +00001027 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001028 // SyntaxError, cannot delete
1029 assert(0);
1030 }
Damiend99b0522013-12-21 18:17:45 +00001031 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
1032 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
1033 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) {
1034 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001035 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
1036
Damiend99b0522013-12-21 18:17:45 +00001037 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1038 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1039 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01001040 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00001041 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001042 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00001043 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01001044 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +00001045 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001046 c_del_stmt(comp, pns->nodes[0]);
1047 for (int i = 0; i < n; i++) {
1048 c_del_stmt(comp, pns1->nodes[i]);
1049 }
Damiend99b0522013-12-21 18:17:45 +00001050 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01001051 // TODO not implemented; can't del comprehension?
1052 assert(0);
1053 } else {
1054 // sequence with 2 items
1055 goto sequence_with_2_items;
1056 }
1057 } else {
1058 // sequence with 2 items
1059 sequence_with_2_items:
1060 c_del_stmt(comp, pns->nodes[0]);
1061 c_del_stmt(comp, pns->nodes[1]);
1062 }
1063 } else {
1064 // tuple with 1 element
1065 c_del_stmt(comp, pn);
1066 }
1067 } else {
1068 // not implemented
1069 assert(0);
1070 }
1071}
1072
Damiend99b0522013-12-21 18:17:45 +00001073void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001074 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
1075}
1076
Damiend99b0522013-12-21 18:17:45 +00001077void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001078 if (comp->break_label == 0) {
1079 printf("ERROR: cannot break from here\n");
1080 }
Damien Georgecbddb272014-02-01 20:08:18 +00001081 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001082}
1083
Damiend99b0522013-12-21 18:17:45 +00001084void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001085 if (comp->continue_label == 0) {
1086 printf("ERROR: cannot continue from here\n");
1087 }
Damien Georgecbddb272014-02-01 20:08:18 +00001088 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001089}
1090
Damiend99b0522013-12-21 18:17:45 +00001091void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +01001092 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
1093 printf("SyntaxError: 'return' outside function\n");
1094 comp->had_error = true;
1095 return;
1096 }
Damiend99b0522013-12-21 18:17:45 +00001097 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001098 // no argument to 'return', so return None
Damien Georgeb9791222014-01-23 00:34:21 +00001099 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damiend99b0522013-12-21 18:17:45 +00001100 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +01001101 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +00001102 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
1103 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 +01001104
Damienb05d7072013-10-05 13:37:10 +01001105 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001106 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1107 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
1108 EMIT(return_value);
Damien Georgeb9791222014-01-23 00:34:21 +00001109 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001110 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1111 } else {
1112 compile_node(comp, pns->nodes[0]);
1113 }
1114 EMIT(return_value);
1115}
1116
Damiend99b0522013-12-21 18:17:45 +00001117void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001118 compile_node(comp, pns->nodes[0]);
1119 EMIT(pop_top);
1120}
1121
Damiend99b0522013-12-21 18:17:45 +00001122void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1123 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001124 // raise
Damien Georgeb9791222014-01-23 00:34:21 +00001125 EMIT_ARG(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001126 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001127 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001128 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001129 compile_node(comp, pns->nodes[0]);
1130 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001131 EMIT_ARG(raise_varargs, 2);
Damien429d7192013-10-04 19:53:11 +01001132 } else {
1133 // raise x
1134 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001135 EMIT_ARG(raise_varargs, 1);
Damien429d7192013-10-04 19:53:11 +01001136 }
1137}
1138
1139// q1 holds the base, q2 the full name
1140// eg a -> q1=q2=a
1141// a.b.c -> q1=a, q2=a.b.c
Damiend99b0522013-12-21 18:17:45 +00001142void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
Damien429d7192013-10-04 19:53:11 +01001143 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001144 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1145 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001146 // a name of the form x as y; unwrap it
Damiend99b0522013-12-21 18:17:45 +00001147 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001148 pn = pns->nodes[0];
1149 is_as = true;
1150 }
Damiend99b0522013-12-21 18:17:45 +00001151 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001152 // just a simple name
Damiend99b0522013-12-21 18:17:45 +00001153 *q2 = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001154 if (!is_as) {
1155 *q1 = *q2;
1156 }
Damien Georgeb9791222014-01-23 00:34:21 +00001157 EMIT_ARG(import_name, *q2);
Damiend99b0522013-12-21 18:17:45 +00001158 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
1159 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
1160 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) {
Damien429d7192013-10-04 19:53:11 +01001161 // a name of the form a.b.c
1162 if (!is_as) {
Damiend99b0522013-12-21 18:17:45 +00001163 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001164 }
Damiend99b0522013-12-21 18:17:45 +00001165 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001166 int len = n - 1;
1167 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00001168 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001169 }
Damien George55baff42014-01-21 21:40:13 +00001170 byte *q_ptr;
1171 byte *str_dest = qstr_build_start(len, &q_ptr);
Damien429d7192013-10-04 19:53:11 +01001172 for (int i = 0; i < n; i++) {
1173 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001174 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001175 }
Damien George55baff42014-01-21 21:40:13 +00001176 uint str_src_len;
1177 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00001178 memcpy(str_dest, str_src, str_src_len);
1179 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001180 }
Damien George55baff42014-01-21 21:40:13 +00001181 *q2 = qstr_build_end(q_ptr);
Damien Georgeb9791222014-01-23 00:34:21 +00001182 EMIT_ARG(import_name, *q2);
Damien429d7192013-10-04 19:53:11 +01001183 if (is_as) {
1184 for (int i = 1; i < n; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001185 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001186 }
1187 }
1188 } else {
1189 // TODO not implemented
1190 assert(0);
1191 }
1192 } else {
1193 // TODO not implemented
1194 assert(0);
1195 }
1196}
1197
Damiend99b0522013-12-21 18:17:45 +00001198void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgeb9791222014-01-23 00:34:21 +00001199 EMIT_ARG(load_const_small_int, 0); // ??
1200 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001201 qstr q1, q2;
1202 do_import_name(comp, pn, &q1, &q2);
Damien Georgeb9791222014-01-23 00:34:21 +00001203 EMIT_ARG(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001204}
1205
Damiend99b0522013-12-21 18:17:45 +00001206void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001207 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1208}
1209
Damiend99b0522013-12-21 18:17:45 +00001210void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1211 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001212 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001213
1214 // build the "fromlist" tuple
1215#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001216 EMIT_ARG(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001217#else
Damien Georgeb9791222014-01-23 00:34:21 +00001218 EMIT_ARG(load_const_str, QSTR_FROM_STR_STATIC("*"), false);
1219 EMIT_ARG(build_tuple, 1);
Damiendb4c3612013-12-10 17:27:24 +00001220#endif
1221
1222 // do the import
Damien429d7192013-10-04 19:53:11 +01001223 qstr dummy_q, id1;
1224 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1225 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001226
Damien429d7192013-10-04 19:53:11 +01001227 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001228 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001229
1230 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001231 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001232 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001233#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001234 {
1235 vstr_t *vstr = vstr_new();
1236 vstr_printf(vstr, "(");
1237 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001238 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1239 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1240 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001241 if (i > 0) {
1242 vstr_printf(vstr, ", ");
1243 }
1244 vstr_printf(vstr, "'");
Damien George55baff42014-01-21 21:40:13 +00001245 uint len;
1246 const byte *str = qstr_data(id2, &len);
1247 vstr_add_strn(vstr, (const char*)str, len);
Damien02f89412013-12-12 15:13:36 +00001248 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001249 }
Damien02f89412013-12-12 15:13:36 +00001250 if (n == 1) {
1251 vstr_printf(vstr, ",");
1252 }
1253 vstr_printf(vstr, ")");
Damien Georgeb9791222014-01-23 00:34:21 +00001254 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001255 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001256 }
Damiendb4c3612013-12-10 17:27:24 +00001257#else
1258 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001259 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1260 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1261 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001262 EMIT_ARG(load_const_str, id2, false);
Damiendb4c3612013-12-10 17:27:24 +00001263 }
Damien Georgeb9791222014-01-23 00:34:21 +00001264 EMIT_ARG(build_tuple, n);
Damiendb4c3612013-12-10 17:27:24 +00001265#endif
1266
1267 // do the import
Damien429d7192013-10-04 19:53:11 +01001268 qstr dummy_q, id1;
1269 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1270 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001271 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1272 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1273 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001274 EMIT_ARG(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001275 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001276 EMIT_ARG(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001277 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001278 EMIT_ARG(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001279 }
1280 }
1281 EMIT(pop_top);
1282 }
1283}
1284
Damiend99b0522013-12-21 18:17:45 +00001285void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001286 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001287 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1288 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001289 } else {
Damiend99b0522013-12-21 18:17:45 +00001290 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1291 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001292 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001293 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001294 }
Damien429d7192013-10-04 19:53:11 +01001295 }
1296 }
1297}
1298
Damiend99b0522013-12-21 18:17:45 +00001299void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001300 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001301 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1302 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001303 } else {
Damiend99b0522013-12-21 18:17:45 +00001304 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1305 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001306 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001307 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001308 }
Damien429d7192013-10-04 19:53:11 +01001309 }
1310 }
1311}
1312
Damiend99b0522013-12-21 18:17:45 +00001313void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001314 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001315 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien Georgeb9791222014-01-23 00:34:21 +00001316 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 +00001317 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001318 // assertion message
1319 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001320 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001321 }
Damien Georgeb9791222014-01-23 00:34:21 +00001322 EMIT_ARG(raise_varargs, 1);
1323 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001324}
1325
Damiend99b0522013-12-21 18:17:45 +00001326void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001327 // TODO proper and/or short circuiting
1328
Damienb05d7072013-10-05 13:37:10 +01001329 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001330
Damienb05d7072013-10-05 13:37:10 +01001331 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001332 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1333
1334 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001335 //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 +01001336 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001337 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001338 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001339 }
1340 //}
Damien Georgeb9791222014-01-23 00:34:21 +00001341 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001342
Damiend99b0522013-12-21 18:17:45 +00001343 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001344 // compile elif blocks
1345
Damiend99b0522013-12-21 18:17:45 +00001346 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001347
Damiend99b0522013-12-21 18:17:45 +00001348 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001349 // multiple elif blocks
1350
Damiend99b0522013-12-21 18:17:45 +00001351 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001352 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001353 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
Damienb05d7072013-10-05 13:37:10 +01001354 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001355 c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition
1356
1357 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001358 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001359 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001360 }
Damien Georgeb9791222014-01-23 00:34:21 +00001361 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001362 }
1363
1364 } else {
1365 // a single elif block
1366
Damienb05d7072013-10-05 13:37:10 +01001367 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001368 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1369
1370 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001371 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001372 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001373 }
Damien Georgeb9791222014-01-23 00:34:21 +00001374 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001375 }
1376 }
1377
1378 // compile else block
1379 compile_node(comp, pns->nodes[3]); // can be null
1380
Damien Georgeb9791222014-01-23 00:34:21 +00001381 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001382}
1383
Damien Georgecbddb272014-02-01 20:08:18 +00001384#define START_BREAK_CONTINUE_BLOCK \
1385 int old_break_label = comp->break_label; \
1386 int old_continue_label = comp->continue_label; \
1387 int break_label = comp_next_label(comp); \
1388 int continue_label = comp_next_label(comp); \
1389 comp->break_label = break_label; \
1390 comp->continue_label = continue_label; \
1391 comp->break_continue_except_level = comp->cur_except_level;
1392
1393#define END_BREAK_CONTINUE_BLOCK \
1394 comp->break_label = old_break_label; \
1395 comp->continue_label = old_continue_label; \
1396 comp->break_continue_except_level = comp->cur_except_level;
1397
Damiend99b0522013-12-21 18:17:45 +00001398void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgecbddb272014-02-01 20:08:18 +00001399 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001400
Damience89a212013-10-15 22:25:17 +01001401 // compared to CPython, we have an optimised version of while loops
1402#if MICROPY_EMIT_CPYTHON
1403 int done_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001404 EMIT_ARG(setup_loop, break_label);
1405 EMIT_ARG(label_assign, continue_label);
Damien429d7192013-10-04 19:53:11 +01001406 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1407 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001408 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001409 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001410 }
Damien Georgeb9791222014-01-23 00:34:21 +00001411 EMIT_ARG(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001412 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1413 // this is a small hack to agree with CPython
1414 if (!node_is_const_true(pns->nodes[0])) {
1415 EMIT(pop_block);
1416 }
Damience89a212013-10-15 22:25:17 +01001417#else
1418 int top_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001419 EMIT_ARG(jump, continue_label);
1420 EMIT_ARG(label_assign, top_label);
Damience89a212013-10-15 22:25:17 +01001421 compile_node(comp, pns->nodes[1]); // body
Damien Georgeb9791222014-01-23 00:34:21 +00001422 EMIT_ARG(label_assign, continue_label);
Damience89a212013-10-15 22:25:17 +01001423 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1424#endif
1425
1426 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001427 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001428
1429 compile_node(comp, pns->nodes[2]); // else
1430
Damien Georgeb9791222014-01-23 00:34:21 +00001431 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001432}
1433
Damienf72fd0e2013-11-06 20:20:49 +00001434// TODO preload end and step onto stack if they are not constants
1435// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001436void 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 +00001437 START_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001438
1439 int top_label = comp_next_label(comp);
Damien George600ae732014-01-21 23:48:04 +00001440 int entry_label = comp_next_label(comp);
Damienf72fd0e2013-11-06 20:20:49 +00001441
1442 // compile: var = start
1443 compile_node(comp, pn_start);
1444 c_assign(comp, pn_var, ASSIGN_STORE);
1445
Damien Georgeb9791222014-01-23 00:34:21 +00001446 EMIT_ARG(jump, entry_label);
1447 EMIT_ARG(label_assign, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001448
Damienf3822fc2013-11-09 20:12:03 +00001449 // compile body
1450 compile_node(comp, pn_body);
1451
Damien Georgeb9791222014-01-23 00:34:21 +00001452 EMIT_ARG(label_assign, continue_label);
Damien George600ae732014-01-21 23:48:04 +00001453
Damienf72fd0e2013-11-06 20:20:49 +00001454 // compile: var += step
1455 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1456 compile_node(comp, pn_step);
Damien Georgeb9791222014-01-23 00:34:21 +00001457 EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_ADD);
Damienf72fd0e2013-11-06 20:20:49 +00001458 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1459
Damien Georgeb9791222014-01-23 00:34:21 +00001460 EMIT_ARG(label_assign, entry_label);
Damienf72fd0e2013-11-06 20:20:49 +00001461
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001462 // compile: if var <cond> end: goto top
Damienf72fd0e2013-11-06 20:20:49 +00001463 compile_node(comp, pn_var);
1464 compile_node(comp, pn_end);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001465 if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) {
Damien George9aa2a522014-02-01 23:04:09 +00001466 EMIT_ARG(binary_op, RT_BINARY_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001467 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001468 EMIT_ARG(binary_op, RT_BINARY_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001469 }
Damien Georgeb9791222014-01-23 00:34:21 +00001470 EMIT_ARG(pop_jump_if_true, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001471
1472 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001473 END_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001474
1475 compile_node(comp, pn_else);
1476
Damien Georgeb9791222014-01-23 00:34:21 +00001477 EMIT_ARG(label_assign, break_label);
Damienf72fd0e2013-11-06 20:20:49 +00001478}
1479
Damiend99b0522013-12-21 18:17:45 +00001480void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001481#if !MICROPY_EMIT_CPYTHON
1482 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1483 // this is actually slower, but uses no heap memory
1484 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001485 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)) {
1486 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001487 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1488 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1489 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
1490 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
Damiend99b0522013-12-21 18:17:45 +00001491 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1492 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001493 int n_args = list_get(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001494 mp_parse_node_t pn_range_start;
1495 mp_parse_node_t pn_range_end;
1496 mp_parse_node_t pn_range_step;
1497 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001498 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001499 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001500 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001501 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001502 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001503 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001504 } else if (n_args == 2) {
1505 pn_range_start = args[0];
1506 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001507 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001508 } else {
1509 pn_range_start = args[0];
1510 pn_range_end = args[1];
1511 pn_range_step = args[2];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001512 // We need to know sign of step. This is possible only if it's constant
1513 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
1514 optimize = false;
1515 }
Damienf72fd0e2013-11-06 20:20:49 +00001516 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001517 }
1518 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001519 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1520 return;
1521 }
1522 }
1523 }
1524#endif
1525
Damien Georgecbddb272014-02-01 20:08:18 +00001526 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001527
Damienb05d7072013-10-05 13:37:10 +01001528 int pop_label = comp_next_label(comp);
1529 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001530
Damience89a212013-10-15 22:25:17 +01001531 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1532#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001533 EMIT_ARG(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001534#endif
1535
Damien429d7192013-10-04 19:53:11 +01001536 compile_node(comp, pns->nodes[1]); // iterator
1537 EMIT(get_iter);
Damien Georgecbddb272014-02-01 20:08:18 +00001538 EMIT_ARG(label_assign, continue_label);
Damien Georgeb9791222014-01-23 00:34:21 +00001539 EMIT_ARG(for_iter, pop_label);
Damien429d7192013-10-04 19:53:11 +01001540 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1541 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001542 if (!EMIT(last_emit_was_return_value)) {
Damien Georgecbddb272014-02-01 20:08:18 +00001543 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001544 }
Damien Georgeb9791222014-01-23 00:34:21 +00001545 EMIT_ARG(label_assign, pop_label);
Damien429d7192013-10-04 19:53:11 +01001546 EMIT(for_iter_end);
1547
1548 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001549 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001550
Damience89a212013-10-15 22:25:17 +01001551#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001552 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001553#endif
Damien429d7192013-10-04 19:53:11 +01001554
1555 compile_node(comp, pns->nodes[3]); // else (not tested)
1556
Damien Georgeb9791222014-01-23 00:34:21 +00001557 EMIT_ARG(label_assign, break_label);
1558 EMIT_ARG(label_assign, end_label);
Damien429d7192013-10-04 19:53:11 +01001559}
1560
Damiend99b0522013-12-21 18:17:45 +00001561void 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 +01001562 // this function is a bit of a hack at the moment
1563 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1564
1565 // setup code
1566 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001567 int l1 = comp_next_label(comp);
1568 int success_label = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001569
Damien Georgeb9791222014-01-23 00:34:21 +00001570 EMIT_ARG(setup_except, l1);
Damien Georgecbddb272014-02-01 20:08:18 +00001571 comp->cur_except_level += 1;
1572
Damien429d7192013-10-04 19:53:11 +01001573 compile_node(comp, pn_body); // body
1574 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001575 EMIT_ARG(jump, success_label);
1576 EMIT_ARG(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001577 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001578
1579 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001580 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1581 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001582
1583 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001584 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001585
Damiend99b0522013-12-21 18:17:45 +00001586 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001587 // this is a catch all exception handler
1588 if (i + 1 != n_except) {
1589 printf("SyntaxError: default 'except:' must be last\n");
1590 return;
1591 }
1592 } else {
1593 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001594 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1595 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1596 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1597 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001598 // handler binds the exception to a local
1599 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001600 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001601 }
1602 }
1603 EMIT(dup_top);
1604 compile_node(comp, pns_exception_expr);
Damien George9aa2a522014-02-01 23:04:09 +00001605 EMIT_ARG(binary_op, RT_BINARY_OP_EXCEPTION_MATCH);
Damien Georgeb9791222014-01-23 00:34:21 +00001606 EMIT_ARG(pop_jump_if_false, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001607 }
1608
1609 EMIT(pop_top);
1610
1611 if (qstr_exception_local == 0) {
1612 EMIT(pop_top);
1613 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001614 EMIT_ARG(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001615 }
1616
1617 EMIT(pop_top);
1618
Damiene2880aa2013-12-20 14:22:59 +00001619 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001620 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001621 l3 = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001622 EMIT_ARG(setup_finally, l3);
Damien Georgecbddb272014-02-01 20:08:18 +00001623 comp->cur_except_level += 1;
Damien429d7192013-10-04 19:53:11 +01001624 }
1625 compile_node(comp, pns_except->nodes[1]);
1626 if (qstr_exception_local != 0) {
1627 EMIT(pop_block);
1628 }
1629 EMIT(pop_except);
1630 if (qstr_exception_local != 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001631 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1632 EMIT_ARG(label_assign, l3);
1633 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1634 EMIT_ARG(store_id, qstr_exception_local);
1635 EMIT_ARG(delete_id, qstr_exception_local);
Damien Georgecbddb272014-02-01 20:08:18 +00001636
1637 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001638 EMIT(end_finally);
1639 }
Damien Georgeb9791222014-01-23 00:34:21 +00001640 EMIT_ARG(jump, l2);
1641 EMIT_ARG(label_assign, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001642 }
1643
Damien Georgecbddb272014-02-01 20:08:18 +00001644 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001645 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001646
Damien Georgeb9791222014-01-23 00:34:21 +00001647 EMIT_ARG(label_assign, success_label);
Damien429d7192013-10-04 19:53:11 +01001648 compile_node(comp, pn_else); // else block, can be null
Damien Georgeb9791222014-01-23 00:34:21 +00001649 EMIT_ARG(label_assign, l2);
1650 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001651}
1652
Damiend99b0522013-12-21 18:17:45 +00001653void 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 +01001654 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1655 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001656 int l_finally_block = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001657
Damien Georgeb9791222014-01-23 00:34:21 +00001658 EMIT_ARG(setup_finally, l_finally_block);
Damien Georgecbddb272014-02-01 20:08:18 +00001659 comp->cur_except_level += 1;
1660
Damien429d7192013-10-04 19:53:11 +01001661 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001662 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001663 compile_node(comp, pn_body);
1664 } else {
1665 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1666 }
1667 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001668 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1669 EMIT_ARG(label_assign, l_finally_block);
Damien429d7192013-10-04 19:53:11 +01001670 compile_node(comp, pn_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001671
1672 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001673 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001674
Damien Georgeb9791222014-01-23 00:34:21 +00001675 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001676}
1677
Damiend99b0522013-12-21 18:17:45 +00001678void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1679 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1680 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1681 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001682 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001683 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1684 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001685 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001686 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001687 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001688 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001689 // no finally
1690 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1691 } else {
1692 // have finally
Damiend99b0522013-12-21 18:17:45 +00001693 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 +01001694 }
1695 } else {
1696 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001697 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001698 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001699 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001700 }
1701 } else {
1702 // shouldn't happen
1703 assert(0);
1704 }
1705}
1706
Damiend99b0522013-12-21 18:17:45 +00001707void 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 +01001708 if (n == 0) {
1709 // no more pre-bits, compile the body of the with
1710 compile_node(comp, body);
1711 } else {
Damienb05d7072013-10-05 13:37:10 +01001712 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001713 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001714 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001715 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001716 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001717 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001718 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1719 } else {
1720 // this pre-bit is just an expression
1721 compile_node(comp, nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001722 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001723 EMIT(pop_top);
1724 }
1725 // compile additional pre-bits and the body
1726 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1727 // finish this with block
1728 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001729 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1730 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001731 EMIT(with_cleanup);
1732 EMIT(end_finally);
1733 }
1734}
1735
Damiend99b0522013-12-21 18:17:45 +00001736void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001737 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001738 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001739 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1740 assert(n > 0);
1741
1742 // compile in a nested fashion
1743 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1744}
1745
Damiend99b0522013-12-21 18:17:45 +00001746void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1747 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001748 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1749 // for REPL, evaluate then print the expression
Damien Georgeb9791222014-01-23 00:34:21 +00001750 EMIT_ARG(load_id, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001751 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001752 EMIT_ARG(call_function, 1, 0, false, false);
Damien5ac1b2e2013-10-18 19:58:12 +01001753 EMIT(pop_top);
1754
Damien429d7192013-10-04 19:53:11 +01001755 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001756 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001757 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001758 // do nothing with a lonely constant
1759 } else {
1760 compile_node(comp, pns->nodes[0]); // just an expression
1761 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1762 }
Damien429d7192013-10-04 19:53:11 +01001763 }
1764 } else {
Damiend99b0522013-12-21 18:17:45 +00001765 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1766 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001767 if (kind == PN_expr_stmt_augassign) {
1768 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1769 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001770 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien George7e5fb242014-02-01 22:18:47 +00001771 rt_binary_op_t op;
Damiend99b0522013-12-21 18:17:45 +00001772 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
Damien George7e5fb242014-02-01 22:18:47 +00001773 case MP_TOKEN_DEL_PIPE_EQUAL: op = RT_BINARY_OP_INPLACE_OR; break;
1774 case MP_TOKEN_DEL_CARET_EQUAL: op = RT_BINARY_OP_INPLACE_XOR; break;
1775 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = RT_BINARY_OP_INPLACE_AND; break;
1776 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = RT_BINARY_OP_INPLACE_LSHIFT; break;
1777 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = RT_BINARY_OP_INPLACE_RSHIFT; break;
1778 case MP_TOKEN_DEL_PLUS_EQUAL: op = RT_BINARY_OP_INPLACE_ADD; break;
1779 case MP_TOKEN_DEL_MINUS_EQUAL: op = RT_BINARY_OP_INPLACE_SUBTRACT; break;
1780 case MP_TOKEN_DEL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_MULTIPLY; break;
1781 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
1782 case MP_TOKEN_DEL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
1783 case MP_TOKEN_DEL_PERCENT_EQUAL: op = RT_BINARY_OP_INPLACE_MODULO; break;
1784 case MP_TOKEN_DEL_DBL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_POWER; break;
1785 default: assert(0); op = RT_BINARY_OP_INPLACE_OR; // shouldn't happen
Damien429d7192013-10-04 19:53:11 +01001786 }
Damien George7e5fb242014-02-01 22:18:47 +00001787 EMIT_ARG(binary_op, op);
Damien429d7192013-10-04 19:53:11 +01001788 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1789 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001790 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1791 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001792 // following CPython, we store left-most first
1793 if (rhs > 0) {
1794 EMIT(dup_top);
1795 }
1796 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1797 for (int i = 0; i < rhs; i++) {
1798 if (i + 1 < rhs) {
1799 EMIT(dup_top);
1800 }
Damiend99b0522013-12-21 18:17:45 +00001801 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001802 }
1803 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001804 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1805 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1806 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1807 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001808 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001809 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1810 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001811 compile_node(comp, pns10->nodes[0]); // rhs
1812 compile_node(comp, pns10->nodes[1]); // rhs
1813 EMIT(rot_two);
1814 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1815 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001816 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1817 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1818 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1819 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001820 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001821 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1822 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001823 compile_node(comp, pns10->nodes[0]); // rhs
1824 compile_node(comp, pns10->nodes[1]); // rhs
1825 compile_node(comp, pns10->nodes[2]); // rhs
1826 EMIT(rot_three);
1827 EMIT(rot_two);
1828 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1829 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1830 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1831 } else {
1832 compile_node(comp, pns1->nodes[0]); // rhs
1833 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1834 }
1835 } else {
1836 // shouldn't happen
1837 assert(0);
1838 }
1839 }
1840}
1841
Damiend99b0522013-12-21 18:17:45 +00001842void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1843 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001844 compile_node(comp, pns->nodes[0]);
1845 for (int i = 1; i < num_nodes; i += 1) {
1846 compile_node(comp, pns->nodes[i]);
Damien Georgeb9791222014-01-23 00:34:21 +00001847 EMIT_ARG(binary_op, binary_op);
Damien429d7192013-10-04 19:53:11 +01001848 }
1849}
1850
Damiend99b0522013-12-21 18:17:45 +00001851void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1852 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1853 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001854
1855 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001856 int l_fail = comp_next_label(comp);
1857 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001858 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1859 compile_node(comp, pns->nodes[0]); // success value
Damien Georgeb9791222014-01-23 00:34:21 +00001860 EMIT_ARG(jump, l_end);
1861 EMIT_ARG(label_assign, l_fail);
1862 EMIT_ARG(set_stack_size, stack_size); // force stack size reset
Damien429d7192013-10-04 19:53:11 +01001863 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
Damien Georgeb9791222014-01-23 00:34:21 +00001864 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001865}
1866
Damiend99b0522013-12-21 18:17:45 +00001867void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001868 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001869 //mp_parse_node_t pn_params = pns->nodes[0];
1870 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001871
1872 if (comp->pass == PASS_1) {
1873 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001874 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 +01001875 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001876 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001877 }
1878
1879 // get the scope for this lambda
1880 scope_t *this_scope = (scope_t*)pns->nodes[2];
1881
1882 // make the lambda
1883 close_over_variables_etc(comp, this_scope, 0, 0);
1884}
1885
Damiend99b0522013-12-21 18:17:45 +00001886void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001887 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001888 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001889 for (int i = 0; i < n; i += 1) {
1890 compile_node(comp, pns->nodes[i]);
1891 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001892 EMIT_ARG(jump_if_true_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001893 }
1894 }
Damien Georgeb9791222014-01-23 00:34:21 +00001895 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001896}
1897
Damiend99b0522013-12-21 18:17:45 +00001898void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001899 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001900 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001901 for (int i = 0; i < n; i += 1) {
1902 compile_node(comp, pns->nodes[i]);
1903 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001904 EMIT_ARG(jump_if_false_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001905 }
1906 }
Damien Georgeb9791222014-01-23 00:34:21 +00001907 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001908}
1909
Damiend99b0522013-12-21 18:17:45 +00001910void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001911 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001912 EMIT_ARG(unary_op, RT_UNARY_OP_NOT);
Damien429d7192013-10-04 19:53:11 +01001913}
1914
Damiend99b0522013-12-21 18:17:45 +00001915void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001916 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001917 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001918 compile_node(comp, pns->nodes[0]);
1919 bool multi = (num_nodes > 3);
1920 int l_fail = 0;
1921 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001922 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001923 }
1924 for (int i = 1; i + 1 < num_nodes; i += 2) {
1925 compile_node(comp, pns->nodes[i + 1]);
1926 if (i + 2 < num_nodes) {
1927 EMIT(dup_top);
1928 EMIT(rot_three);
1929 }
Damien George7e5fb242014-02-01 22:18:47 +00001930 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
1931 rt_binary_op_t op;
1932 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
Damien George9aa2a522014-02-01 23:04:09 +00001933 case MP_TOKEN_OP_LESS: op = RT_BINARY_OP_LESS; break;
1934 case MP_TOKEN_OP_MORE: op = RT_BINARY_OP_MORE; break;
1935 case MP_TOKEN_OP_DBL_EQUAL: op = RT_BINARY_OP_EQUAL; break;
1936 case MP_TOKEN_OP_LESS_EQUAL: op = RT_BINARY_OP_LESS_EQUAL; break;
1937 case MP_TOKEN_OP_MORE_EQUAL: op = RT_BINARY_OP_MORE_EQUAL; break;
1938 case MP_TOKEN_OP_NOT_EQUAL: op = RT_BINARY_OP_NOT_EQUAL; break;
1939 case MP_TOKEN_KW_IN: op = RT_BINARY_OP_IN; break;
1940 default: assert(0); op = RT_BINARY_OP_LESS; // shouldn't happen
Damien George7e5fb242014-02-01 22:18:47 +00001941 }
1942 EMIT_ARG(binary_op, op);
Damiend99b0522013-12-21 18:17:45 +00001943 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
1944 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
1945 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01001946 if (kind == PN_comp_op_not_in) {
Damien George9aa2a522014-02-01 23:04:09 +00001947 EMIT_ARG(binary_op, RT_BINARY_OP_NOT_IN);
Damien429d7192013-10-04 19:53:11 +01001948 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00001949 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien George9aa2a522014-02-01 23:04:09 +00001950 EMIT_ARG(binary_op, RT_BINARY_OP_IS);
Damien429d7192013-10-04 19:53:11 +01001951 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001952 EMIT_ARG(binary_op, RT_BINARY_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01001953 }
1954 } else {
1955 // shouldn't happen
1956 assert(0);
1957 }
1958 } else {
1959 // shouldn't happen
1960 assert(0);
1961 }
1962 if (i + 2 < num_nodes) {
Damien Georgeb9791222014-01-23 00:34:21 +00001963 EMIT_ARG(jump_if_false_or_pop, l_fail);
Damien429d7192013-10-04 19:53:11 +01001964 }
1965 }
1966 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001967 int l_end = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001968 EMIT_ARG(jump, l_end);
1969 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001970 EMIT(rot_two);
1971 EMIT(pop_top);
Damien Georgeb9791222014-01-23 00:34:21 +00001972 EMIT_ARG(label_assign, l_end);
1973 EMIT_ARG(set_stack_size, stack_size + 1); // force stack size
Damien429d7192013-10-04 19:53:11 +01001974 }
1975}
1976
Damiend99b0522013-12-21 18:17:45 +00001977void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001978 // TODO
1979 assert(0);
1980 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001981 //EMIT_ARG(unary_op, "UNARY_STAR");
Damien429d7192013-10-04 19:53:11 +01001982}
1983
Damiend99b0522013-12-21 18:17:45 +00001984void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001985 c_binary_op(comp, pns, RT_BINARY_OP_OR);
1986}
1987
Damiend99b0522013-12-21 18:17:45 +00001988void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001989 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
1990}
1991
Damiend99b0522013-12-21 18:17:45 +00001992void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001993 c_binary_op(comp, pns, RT_BINARY_OP_AND);
1994}
1995
Damiend99b0522013-12-21 18:17:45 +00001996void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1997 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001998 compile_node(comp, pns->nodes[0]);
1999 for (int i = 1; i + 1 < num_nodes; i += 2) {
2000 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002001 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002002 EMIT_ARG(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00002003 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002004 EMIT_ARG(binary_op, RT_BINARY_OP_RSHIFT);
Damien429d7192013-10-04 19:53:11 +01002005 } else {
2006 // shouldn't happen
2007 assert(0);
2008 }
2009 }
2010}
2011
Damiend99b0522013-12-21 18:17:45 +00002012void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2013 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002014 compile_node(comp, pns->nodes[0]);
2015 for (int i = 1; i + 1 < num_nodes; i += 2) {
2016 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002017 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002018 EMIT_ARG(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002019 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002020 EMIT_ARG(binary_op, RT_BINARY_OP_SUBTRACT);
Damien429d7192013-10-04 19:53:11 +01002021 } else {
2022 // shouldn't happen
2023 assert(0);
2024 }
2025 }
2026}
2027
Damiend99b0522013-12-21 18:17:45 +00002028void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2029 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002030 compile_node(comp, pns->nodes[0]);
2031 for (int i = 1; i + 1 < num_nodes; i += 2) {
2032 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002033 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002034 EMIT_ARG(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002035 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002036 EMIT_ARG(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002037 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002038 EMIT_ARG(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002039 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002040 EMIT_ARG(binary_op, RT_BINARY_OP_MODULO);
Damien429d7192013-10-04 19:53:11 +01002041 } else {
2042 // shouldn't happen
2043 assert(0);
2044 }
2045 }
2046}
2047
Damiend99b0522013-12-21 18:17:45 +00002048void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002049 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002050 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002051 EMIT_ARG(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002052 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002053 EMIT_ARG(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002054 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002055 EMIT_ARG(unary_op, RT_UNARY_OP_INVERT);
Damien429d7192013-10-04 19:53:11 +01002056 } else {
2057 // shouldn't happen
2058 assert(0);
2059 }
2060}
2061
Damien George35e2a4e2014-02-05 00:51:47 +00002062void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
2063 // this is to handle special super() call
2064 comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
2065
2066 compile_generic_all_nodes(comp, pns);
2067}
2068
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002069STATIC 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 +01002070 // function to call is on top of stack
2071
Damien George35e2a4e2014-02-05 00:51:47 +00002072#if !MICROPY_EMIT_CPYTHON
2073 // this is to handle special super() call
Damien Georgebbcd49a2014-02-06 20:30:16 +00002074 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 +00002075 EMIT_ARG(load_id, MP_QSTR___class__);
2076 // get first argument to function
2077 bool found = false;
2078 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
2079 if (comp->scope_cur->id_info[i].param) {
2080 EMIT_ARG(load_fast, MP_QSTR_, comp->scope_cur->id_info[i].local_num);
2081 found = true;
2082 break;
2083 }
2084 }
2085 if (!found) {
2086 printf("TypeError: super() call cannot find self\n");
2087 return;
2088 }
2089 EMIT_ARG(call_function, 2, 0, false, false);
2090 return;
2091 }
2092#endif
2093
Damien429d7192013-10-04 19:53:11 +01002094 int old_n_arg_keyword = comp->n_arg_keyword;
2095 bool old_have_star_arg = comp->have_star_arg;
2096 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2097 comp->n_arg_keyword = 0;
2098 comp->have_star_arg = false;
2099 comp->have_dbl_star_arg = false;
2100
Damien Georgebbcd49a2014-02-06 20:30:16 +00002101 compile_node(comp, pn_arglist); // arguments to function call; can be null
Damien429d7192013-10-04 19:53:11 +01002102
2103 // compute number of positional arguments
Damien Georgebbcd49a2014-02-06 20:30:16 +00002104 int n_positional = n_positional_extra + list_len(pn_arglist, PN_arglist) - comp->n_arg_keyword;
Damien429d7192013-10-04 19:53:11 +01002105 if (comp->have_star_arg) {
2106 n_positional -= 1;
2107 }
2108 if (comp->have_dbl_star_arg) {
2109 n_positional -= 1;
2110 }
2111
2112 if (is_method_call) {
Damien Georgeb9791222014-01-23 00:34:21 +00002113 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 +01002114 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002115 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 +01002116 }
2117
2118 comp->n_arg_keyword = old_n_arg_keyword;
2119 comp->have_star_arg = old_have_star_arg;
2120 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2121}
2122
Damiend99b0522013-12-21 18:17:45 +00002123void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2124 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002125 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002126 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 +01002127 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002128 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2129 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
Damien Georgeb9791222014-01-23 00:34:21 +00002130 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien Georgebbcd49a2014-02-06 20:30:16 +00002131 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
Damien429d7192013-10-04 19:53:11 +01002132 i += 1;
2133 } else {
2134 compile_node(comp, pns->nodes[i]);
2135 }
Damien George35e2a4e2014-02-05 00:51:47 +00002136 comp->func_arg_is_super = false;
Damien429d7192013-10-04 19:53:11 +01002137 }
2138}
2139
Damiend99b0522013-12-21 18:17:45 +00002140void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002141 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002142 EMIT_ARG(binary_op, RT_BINARY_OP_POWER);
Damien429d7192013-10-04 19:53:11 +01002143}
2144
Damiend99b0522013-12-21 18:17:45 +00002145void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002146 // a list of strings
Damien63321742013-12-10 17:41:49 +00002147
2148 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002149 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002150 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002151 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002152 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002153 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2154 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2155 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002156 if (i == 0) {
2157 string_kind = pn_kind;
2158 } else if (pn_kind != string_kind) {
2159 printf("SyntaxError: cannot mix bytes and nonbytes literals\n");
2160 return;
2161 }
Damien George55baff42014-01-21 21:40:13 +00002162 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01002163 }
Damien63321742013-12-10 17:41:49 +00002164
Damien63321742013-12-10 17:41:49 +00002165 // concatenate string/bytes
Damien George55baff42014-01-21 21:40:13 +00002166 byte *q_ptr;
2167 byte *s_dest = qstr_build_start(n_bytes, &q_ptr);
Damien63321742013-12-10 17:41:49 +00002168 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00002169 uint s_len;
2170 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00002171 memcpy(s_dest, s, s_len);
2172 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002173 }
Damien George55baff42014-01-21 21:40:13 +00002174 qstr q = qstr_build_end(q_ptr);
Damien63321742013-12-10 17:41:49 +00002175
Damien Georgeb9791222014-01-23 00:34:21 +00002176 EMIT_ARG(load_const_str, q, string_kind == MP_PARSE_NODE_BYTES);
Damien429d7192013-10-04 19:53:11 +01002177}
2178
2179// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002180void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2181 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2182 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2183 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002184
2185 if (comp->pass == PASS_1) {
2186 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002187 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 +01002188 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002189 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002190 }
2191
2192 // get the scope for this comprehension
2193 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2194
2195 // compile the comprehension
2196 close_over_variables_etc(comp, this_scope, 0, 0);
2197
2198 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2199 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002200 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01002201}
2202
Damiend99b0522013-12-21 18:17:45 +00002203void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2204 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002205 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002206 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2207 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2208 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2209 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2210 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2211 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2212 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002213 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002214 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002215 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002216 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002217 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002218 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002219 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002220 // generator expression
2221 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2222 } else {
2223 // tuple with 2 items
2224 goto tuple_with_2_items;
2225 }
2226 } else {
2227 // tuple with 2 items
2228 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002229 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002230 }
2231 } else {
2232 // parenthesis around a single item, is just that item
2233 compile_node(comp, pns->nodes[0]);
2234 }
2235}
2236
Damiend99b0522013-12-21 18:17:45 +00002237void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2238 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002239 // empty list
Damien Georgeb9791222014-01-23 00:34:21 +00002240 EMIT_ARG(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002241 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2242 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2243 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2244 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2245 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002246 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002247 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002248 compile_node(comp, pns2->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002249 EMIT_ARG(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002250 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002251 // list of many items
2252 compile_node(comp, pns2->nodes[0]);
2253 compile_generic_all_nodes(comp, pns3);
Damien Georgeb9791222014-01-23 00:34:21 +00002254 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
Damiend99b0522013-12-21 18:17:45 +00002255 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002256 // list comprehension
2257 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2258 } else {
2259 // list with 2 items
2260 goto list_with_2_items;
2261 }
2262 } else {
2263 // list with 2 items
2264 list_with_2_items:
2265 compile_node(comp, pns2->nodes[0]);
2266 compile_node(comp, pns2->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00002267 EMIT_ARG(build_list, 2);
Damien429d7192013-10-04 19:53:11 +01002268 }
2269 } else {
2270 // list with 1 item
2271 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002272 EMIT_ARG(build_list, 1);
Damien429d7192013-10-04 19:53:11 +01002273 }
2274}
2275
Damiend99b0522013-12-21 18:17:45 +00002276void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2277 mp_parse_node_t pn = pns->nodes[0];
2278 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002279 // empty dict
Damien Georgeb9791222014-01-23 00:34:21 +00002280 EMIT_ARG(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002281 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2282 pns = (mp_parse_node_struct_t*)pn;
2283 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002284 // dict with one element
Damien Georgeb9791222014-01-23 00:34:21 +00002285 EMIT_ARG(build_map, 1);
Damien429d7192013-10-04 19:53:11 +01002286 compile_node(comp, pn);
2287 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002288 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2289 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2290 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2291 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002292 // dict/set with multiple elements
2293
2294 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002295 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002296 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2297
2298 // first element sets whether it's a dict or set
2299 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002300 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002301 // a dictionary
Damien Georgeb9791222014-01-23 00:34:21 +00002302 EMIT_ARG(build_map, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002303 compile_node(comp, pns->nodes[0]);
2304 EMIT(store_map);
2305 is_dict = true;
2306 } else {
2307 // a set
2308 compile_node(comp, pns->nodes[0]); // 1st value of set
2309 is_dict = false;
2310 }
2311
2312 // process rest of elements
2313 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002314 mp_parse_node_t pn = nodes[i];
2315 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002316 compile_node(comp, pn);
2317 if (is_dict) {
2318 if (!is_key_value) {
2319 printf("SyntaxError?: expecting key:value for dictionary");
2320 return;
2321 }
2322 EMIT(store_map);
2323 } else {
2324 if (is_key_value) {
2325 printf("SyntaxError?: expecting just a value for set");
2326 return;
2327 }
2328 }
2329 }
2330
2331 // if it's a set, build it
2332 if (!is_dict) {
Damien Georgeb9791222014-01-23 00:34:21 +00002333 EMIT_ARG(build_set, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002334 }
Damiend99b0522013-12-21 18:17:45 +00002335 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002336 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002337 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002338 // a dictionary comprehension
2339 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2340 } else {
2341 // a set comprehension
2342 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2343 }
2344 } else {
2345 // shouldn't happen
2346 assert(0);
2347 }
2348 } else {
2349 // set with one element
2350 goto set_with_one_element;
2351 }
2352 } else {
2353 // set with one element
2354 set_with_one_element:
2355 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002356 EMIT_ARG(build_set, 1);
Damien429d7192013-10-04 19:53:11 +01002357 }
2358}
2359
Damiend99b0522013-12-21 18:17:45 +00002360void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgebbcd49a2014-02-06 20:30:16 +00002361 compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
Damien429d7192013-10-04 19:53:11 +01002362}
2363
Damiend99b0522013-12-21 18:17:45 +00002364void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002365 // object who's index we want is on top of stack
2366 compile_node(comp, pns->nodes[0]); // the index
Damien Georgeb9791222014-01-23 00:34:21 +00002367 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +01002368}
2369
Damiend99b0522013-12-21 18:17:45 +00002370void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002371 // object who's attribute we want is on top of stack
Damien Georgeb9791222014-01-23 00:34:21 +00002372 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002373}
2374
Damiend99b0522013-12-21 18:17:45 +00002375void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2376 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2377 mp_parse_node_t pn = pns->nodes[0];
2378 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002379 // [?:]
Damien Georgeb9791222014-01-23 00:34:21 +00002380 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
2381 EMIT_ARG(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002382 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2383 pns = (mp_parse_node_struct_t*)pn;
2384 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
Damien Georgeb9791222014-01-23 00:34:21 +00002385 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002386 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002387 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002388 // [?::]
Damien Georgeb9791222014-01-23 00:34:21 +00002389 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002390 } else {
2391 // [?::x]
2392 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002393 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002394 }
Damiend99b0522013-12-21 18:17:45 +00002395 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002396 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002397 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2398 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2399 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2400 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002401 // [?:x:]
Damien Georgeb9791222014-01-23 00:34:21 +00002402 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002403 } else {
2404 // [?:x:x]
2405 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002406 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002407 }
2408 } else {
2409 // [?:x]
2410 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002411 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002412 }
2413 } else {
2414 // [?:x]
2415 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002416 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002417 }
2418}
2419
Damiend99b0522013-12-21 18:17:45 +00002420void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002421 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002422 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2423 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002424}
2425
Damiend99b0522013-12-21 18:17:45 +00002426void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgeb9791222014-01-23 00:34:21 +00002427 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002428 compile_subscript_3_helper(comp, pns);
2429}
2430
Damiend99b0522013-12-21 18:17:45 +00002431void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002432 // if this is called then we are compiling a dict key:value pair
2433 compile_node(comp, pns->nodes[1]); // value
2434 compile_node(comp, pns->nodes[0]); // key
2435}
2436
Damiend99b0522013-12-21 18:17:45 +00002437void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002438 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002439 // store class object into class name
Damien Georgeb9791222014-01-23 00:34:21 +00002440 EMIT_ARG(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002441}
2442
Damiend99b0522013-12-21 18:17:45 +00002443void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002444 if (comp->have_star_arg) {
2445 printf("SyntaxError?: can't have multiple *x\n");
2446 return;
2447 }
2448 comp->have_star_arg = true;
2449 compile_node(comp, pns->nodes[0]);
2450}
2451
Damiend99b0522013-12-21 18:17:45 +00002452void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002453 if (comp->have_dbl_star_arg) {
2454 printf("SyntaxError?: can't have multiple **x\n");
2455 return;
2456 }
2457 comp->have_dbl_star_arg = true;
2458 compile_node(comp, pns->nodes[0]);
2459}
2460
Damiend99b0522013-12-21 18:17:45 +00002461void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2462 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2463 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2464 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2465 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002466 printf("SyntaxError?: lhs of keyword argument must be an id\n");
2467 return;
2468 }
Damien Georgeb9791222014-01-23 00:34:21 +00002469 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002470 compile_node(comp, pns2->nodes[0]);
2471 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002472 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002473 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2474 } else {
2475 // shouldn't happen
2476 assert(0);
2477 }
2478}
2479
Damiend99b0522013-12-21 18:17:45 +00002480void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002481 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
2482 printf("SyntaxError: 'yield' outside function\n");
2483 return;
2484 }
Damiend99b0522013-12-21 18:17:45 +00002485 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00002486 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002487 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002488 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2489 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002490 compile_node(comp, pns->nodes[0]);
2491 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002492 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002493 EMIT(yield_from);
2494 } else {
2495 compile_node(comp, pns->nodes[0]);
2496 EMIT(yield_value);
2497 }
2498}
2499
Damiend99b0522013-12-21 18:17:45 +00002500typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002501STATIC compile_function_t compile_function[] = {
Damien429d7192013-10-04 19:53:11 +01002502 NULL,
2503#define nc NULL
2504#define c(f) compile_##f
2505#define DEF_RULE(rule, comp, kind, arg...) comp,
2506#include "grammar.h"
2507#undef nc
2508#undef c
2509#undef DEF_RULE
2510};
2511
Damiend99b0522013-12-21 18:17:45 +00002512void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2513 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002514 // pass
Damiend99b0522013-12-21 18:17:45 +00002515 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien George08d07552014-01-29 18:58:52 +00002516 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +00002517 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002518 case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
2519 case MP_PARSE_NODE_SMALL_INT: EMIT_ARG(load_const_small_int, arg); break;
2520 case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
2521 case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
2522 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
2523 case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
Damiend99b0522013-12-21 18:17:45 +00002524 case MP_PARSE_NODE_TOKEN:
2525 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002526 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002527 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002528 // do nothing
2529 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002530 EMIT_ARG(load_const_tok, arg);
Damien91d387d2013-10-09 15:09:52 +01002531 }
2532 break;
Damien429d7192013-10-04 19:53:11 +01002533 default: assert(0);
2534 }
2535 } else {
Damiend99b0522013-12-21 18:17:45 +00002536 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien Georgeb9791222014-01-23 00:34:21 +00002537 EMIT_ARG(set_line_number, pns->source_line);
Damiend99b0522013-12-21 18:17:45 +00002538 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002539 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002540 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien Georgecbd2f742014-01-19 11:48:48 +00002541#if MICROPY_DEBUG_PRINTERS
2542 mp_parse_node_print(pn, 0);
2543#endif
Damien429d7192013-10-04 19:53:11 +01002544 assert(0);
2545 } else {
2546 f(comp, pns);
2547 }
2548 }
2549}
2550
Damiend99b0522013-12-21 18:17:45 +00002551void 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 +01002552 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002553 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002554 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2555 if (MP_PARSE_NODE_IS_ID(pn)) {
2556 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002557 if (comp->have_bare_star) {
2558 // comes after a bare star, so doesn't count as a parameter
2559 } else {
2560 comp->scope_cur->num_params += 1;
2561 }
Damienb14de212013-10-06 00:28:28 +01002562 } else {
Damiend99b0522013-12-21 18:17:45 +00002563 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2564 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2565 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2566 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002567 //int node_index = 1; unused
2568 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002569 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002570 // this parameter has an annotation
2571 pn_annotation = pns->nodes[1];
2572 }
2573 //node_index = 2; unused
2574 }
2575 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002576 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002577 // this parameter has a default value
2578 if (comp->have_bare_star) {
2579 comp->scope_cur->num_dict_params += 1;
2580 } else {
2581 comp->scope_cur->num_default_params += 1;
2582 }
2583 }
2584 */
2585 if (comp->have_bare_star) {
2586 // comes after a bare star, so doesn't count as a parameter
2587 } else {
2588 comp->scope_cur->num_params += 1;
2589 }
Damiend99b0522013-12-21 18:17:45 +00002590 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2591 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002592 // bare star
2593 // TODO see http://www.python.org/dev/peps/pep-3102/
2594 comp->have_bare_star = true;
2595 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002596 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002597 // named star
2598 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002599 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2600 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002601 // named star with annotation
2602 comp->scope_cur->flags |= SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002603 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2604 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002605 pn_annotation = pns->nodes[1];
2606 } else {
2607 // shouldn't happen
2608 assert(0);
2609 }
Damiend99b0522013-12-21 18:17:45 +00002610 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2611 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2612 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002613 // this parameter has an annotation
2614 pn_annotation = pns->nodes[1];
2615 }
2616 comp->scope_cur->flags |= SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002617 } else {
Damienb14de212013-10-06 00:28:28 +01002618 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002619 assert(0);
2620 }
Damien429d7192013-10-04 19:53:11 +01002621 }
2622
2623 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002624 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002625 // TODO this parameter has an annotation
2626 }
2627 bool added;
2628 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2629 if (!added) {
2630 printf("SyntaxError?: same name used for parameter; %s\n", qstr_str(param_name));
2631 return;
2632 }
2633 id_info->param = true;
2634 id_info->kind = ID_INFO_KIND_LOCAL;
2635 }
2636}
2637
Damiend99b0522013-12-21 18:17:45 +00002638void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002639 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2640}
2641
Damiend99b0522013-12-21 18:17:45 +00002642void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002643 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2644}
2645
Damiend99b0522013-12-21 18:17:45 +00002646void 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 +01002647 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002648 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002649 // no more nested if/for; compile inner expression
2650 compile_node(comp, pn_inner_expr);
2651 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002652 EMIT_ARG(list_append, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002653 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002654 EMIT_ARG(map_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002655 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002656 EMIT_ARG(set_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002657 } else {
2658 EMIT(yield_value);
2659 EMIT(pop_top);
2660 }
Damiend99b0522013-12-21 18:17:45 +00002661 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002662 // if condition
Damiend99b0522013-12-21 18:17:45 +00002663 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002664 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2665 pn_iter = pns_comp_if->nodes[1];
2666 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002667 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002668 // for loop
Damiend99b0522013-12-21 18:17:45 +00002669 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002670 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002671 int l_end2 = comp_next_label(comp);
2672 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002673 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002674 EMIT_ARG(label_assign, l_top2);
2675 EMIT_ARG(for_iter, l_end2);
Damien429d7192013-10-04 19:53:11 +01002676 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2677 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 +00002678 EMIT_ARG(jump, l_top2);
2679 EMIT_ARG(label_assign, l_end2);
Damien429d7192013-10-04 19:53:11 +01002680 EMIT(for_iter_end);
2681 } else {
2682 // shouldn't happen
2683 assert(0);
2684 }
2685}
2686
Damiend99b0522013-12-21 18:17:45 +00002687void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002688 // see http://www.python.org/dev/peps/pep-0257/
2689
2690 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002691 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002692 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002693 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002694 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002695 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2696 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002697 for (int i = 0; i < num_nodes; i++) {
2698 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002699 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 +00002700 // not a newline, so this is the first statement; finish search
2701 break;
2702 }
2703 }
2704 // 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 +00002705 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002706 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002707 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002708 } else {
2709 return;
2710 }
2711
2712 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002713 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2714 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2715 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2716 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2717 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002718 compile_node(comp, pns->nodes[0]); // a doc string
2719 // store doc string
Damien Georgeb9791222014-01-23 00:34:21 +00002720 EMIT_ARG(store_id, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002721 }
2722 }
2723 }
2724}
2725
2726void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2727 comp->pass = pass;
2728 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002729 comp->next_label = 1;
Damien Georgeb9791222014-01-23 00:34:21 +00002730 EMIT_ARG(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002731
2732 if (comp->pass == PASS_1) {
2733 scope->stack_size = 0;
2734 }
2735
Damien5ac1b2e2013-10-18 19:58:12 +01002736#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002737 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002738 scope_print_info(scope);
2739 }
Damien5ac1b2e2013-10-18 19:58:12 +01002740#endif
Damien429d7192013-10-04 19:53:11 +01002741
2742 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002743 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2744 assert(scope->kind == SCOPE_MODULE);
2745 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2746 compile_node(comp, pns->nodes[0]); // compile the expression
2747 EMIT(return_value);
2748 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002749 if (!comp->is_repl) {
2750 check_for_doc_string(comp, scope->pn);
2751 }
Damien429d7192013-10-04 19:53:11 +01002752 compile_node(comp, scope->pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002753 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002754 EMIT(return_value);
2755 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002756 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2757 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2758 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002759
2760 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002761 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002762 if (comp->pass == PASS_1) {
2763 comp->have_bare_star = false;
2764 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2765 }
2766
Paul Sokolovsky2f0b0262014-02-10 02:04:26 +02002767 // pns->nodes[2] is return/whole function annotation
Damien429d7192013-10-04 19:53:11 +01002768
2769 compile_node(comp, pns->nodes[3]); // 3 is function body
2770 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002771 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002772 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002773 EMIT(return_value);
2774 }
2775 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002776 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2777 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2778 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002779
2780 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002781 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002782 if (comp->pass == PASS_1) {
2783 comp->have_bare_star = false;
2784 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2785 }
2786
2787 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2788 EMIT(return_value);
2789 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2790 // a bit of a hack at the moment
2791
Damiend99b0522013-12-21 18:17:45 +00002792 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2793 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2794 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2795 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2796 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002797
Damien George55baff42014-01-21 21:40:13 +00002798 qstr qstr_arg = QSTR_FROM_STR_STATIC(".0");
Damien429d7192013-10-04 19:53:11 +01002799 if (comp->pass == PASS_1) {
2800 bool added;
2801 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2802 assert(added);
2803 id_info->kind = ID_INFO_KIND_LOCAL;
2804 scope->num_params = 1;
2805 }
2806
2807 if (scope->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002808 EMIT_ARG(build_list, 0);
Damien429d7192013-10-04 19:53:11 +01002809 } else if (scope->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002810 EMIT_ARG(build_map, 0);
Damien429d7192013-10-04 19:53:11 +01002811 } else if (scope->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002812 EMIT_ARG(build_set, 0);
Damien429d7192013-10-04 19:53:11 +01002813 }
2814
Damienb05d7072013-10-05 13:37:10 +01002815 int l_end = comp_next_label(comp);
2816 int l_top = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002817 EMIT_ARG(load_id, qstr_arg);
2818 EMIT_ARG(label_assign, l_top);
2819 EMIT_ARG(for_iter, l_end);
Damien429d7192013-10-04 19:53:11 +01002820 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2821 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
Damien Georgeb9791222014-01-23 00:34:21 +00002822 EMIT_ARG(jump, l_top);
2823 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002824 EMIT(for_iter_end);
2825
2826 if (scope->kind == SCOPE_GEN_EXPR) {
Damien Georgeb9791222014-01-23 00:34:21 +00002827 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002828 }
2829 EMIT(return_value);
2830 } else {
2831 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00002832 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2833 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2834 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01002835
2836 if (comp->pass == PASS_1) {
2837 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002838 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01002839 assert(added);
2840 id_info->kind = ID_INFO_KIND_LOCAL;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002841 id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
Damien429d7192013-10-04 19:53:11 +01002842 assert(added);
2843 id_info->kind = ID_INFO_KIND_LOCAL;
2844 id_info->param = true;
2845 scope->num_params = 1; // __locals__ is the parameter
2846 }
2847
Damien Georgeb9791222014-01-23 00:34:21 +00002848 EMIT_ARG(load_id, MP_QSTR___locals__);
Damien429d7192013-10-04 19:53:11 +01002849 EMIT(store_locals);
Damien Georgeb9791222014-01-23 00:34:21 +00002850 EMIT_ARG(load_id, MP_QSTR___name__);
2851 EMIT_ARG(store_id, MP_QSTR___module__);
2852 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
2853 EMIT_ARG(store_id, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01002854
2855 check_for_doc_string(comp, pns->nodes[2]);
2856 compile_node(comp, pns->nodes[2]); // 2 is class body
2857
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002858 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01002859 assert(id != NULL);
2860 if (id->kind == ID_INFO_KIND_LOCAL) {
Damien Georgeb9791222014-01-23 00:34:21 +00002861 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002862 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002863#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00002864 EMIT_ARG(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002865#else
Damien George35e2a4e2014-02-05 00:51:47 +00002866 EMIT_ARG(load_fast, MP_QSTR___class__, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +00002867#endif
Damien429d7192013-10-04 19:53:11 +01002868 }
2869 EMIT(return_value);
2870 }
2871
Damien415eb6f2013-10-05 12:19:06 +01002872 EMIT(end_pass);
Damien826005c2013-10-05 23:17:28 +01002873}
2874
2875void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2876 comp->pass = pass;
2877 comp->scope_cur = scope;
2878 comp->next_label = 1;
2879
2880 if (scope->kind != SCOPE_FUNCTION) {
2881 printf("Error: inline assembler must be a function\n");
2882 return;
2883 }
2884
Damiena2f2f7d2013-10-06 00:14:13 +01002885 if (comp->pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002886 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur);
Damiena2f2f7d2013-10-06 00:14:13 +01002887 }
2888
Damien826005c2013-10-05 23:17:28 +01002889 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002890 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2891 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2892 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002893
Damiend99b0522013-12-21 18:17:45 +00002894 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002895
Damiena2f2f7d2013-10-06 00:14:13 +01002896 // parameters are in pns->nodes[1]
2897 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002898 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002899 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
Damien Georgeb9791222014-01-23 00:34:21 +00002900 scope->num_params = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
Damiena2f2f7d2013-10-06 00:14:13 +01002901 }
2902
Damiend99b0522013-12-21 18:17:45 +00002903 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002904
Damiend99b0522013-12-21 18:17:45 +00002905 mp_parse_node_t pn_body = pns->nodes[3]; // body
2906 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002907 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2908
Damien Georgecbd2f742014-01-19 11:48:48 +00002909 /*
Damien826005c2013-10-05 23:17:28 +01002910 if (comp->pass == PASS_3) {
2911 //printf("----\n");
2912 scope_print_info(scope);
2913 }
Damien Georgecbd2f742014-01-19 11:48:48 +00002914 */
Damien826005c2013-10-05 23:17:28 +01002915
2916 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002917 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2918 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2919 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2920 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2921 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2922 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2923 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2924 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2925 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2926 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2927 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2928 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2929 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002930 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2931
2932 // emit instructions
2933 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00002934 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien826005c2013-10-05 23:17:28 +01002935 printf("SyntaxError: inline assembler 'label' requires 1 argument\n");
2936 return;
2937 }
2938 int lab = comp_next_label(comp);
2939 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002940 EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01002941 }
2942 } else {
2943 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002944 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
Damien826005c2013-10-05 23:17:28 +01002945 }
2946 }
2947 }
2948
2949 if (comp->pass > PASS_1) {
2950 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01002951 }
Damien429d7192013-10-04 19:53:11 +01002952}
2953
2954void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
2955 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00002956 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01002957 scope->num_locals = 0;
2958 for (int i = 0; i < scope->id_info_len; i++) {
2959 id_info_t *id = &scope->id_info[i];
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002960 if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01002961 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
2962 continue;
2963 }
2964 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
2965 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
2966 }
Damien9ecbcff2013-12-11 00:41:43 +00002967 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01002968 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
2969 id->local_num = scope->num_locals;
2970 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002971 }
2972 }
2973
2974 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00002975#if MICROPY_EMIT_CPYTHON
2976 int num_cell = 0;
2977#endif
Damien9ecbcff2013-12-11 00:41:43 +00002978 for (int i = 0; i < scope->id_info_len; i++) {
2979 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00002980#if MICROPY_EMIT_CPYTHON
2981 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00002982 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00002983 id->local_num = num_cell;
2984 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002985 }
Damien George6baf76e2013-12-30 22:32:17 +00002986#else
2987 // in Micro Python the cells come right after the fast locals
2988 // parameters are not counted here, since they remain at the start
2989 // of the locals, even if they are cell vars
2990 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
2991 id->local_num = scope->num_locals;
2992 scope->num_locals += 1;
2993 }
2994#endif
Damien9ecbcff2013-12-11 00:41:43 +00002995 }
Damien9ecbcff2013-12-11 00:41:43 +00002996
2997 // compute the index of free vars (freevars[idx] in CPython)
2998 // make sure they are in the order of the parent scope
2999 if (scope->parent != NULL) {
3000 int num_free = 0;
3001 for (int i = 0; i < scope->parent->id_info_len; i++) {
3002 id_info_t *id = &scope->parent->id_info[i];
3003 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3004 for (int j = 0; j < scope->id_info_len; j++) {
3005 id_info_t *id2 = &scope->id_info[j];
3006 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00003007 assert(!id2->param); // free vars should not be params
3008#if MICROPY_EMIT_CPYTHON
3009 // in CPython the frees are numbered after the cells
3010 id2->local_num = num_cell + num_free;
3011#else
3012 // in Micro Python the frees come first, before the params
3013 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00003014#endif
3015 num_free += 1;
3016 }
3017 }
3018 }
Damien429d7192013-10-04 19:53:11 +01003019 }
Damien George6baf76e2013-12-30 22:32:17 +00003020#if !MICROPY_EMIT_CPYTHON
3021 // in Micro Python shift all other locals after the free locals
3022 if (num_free > 0) {
3023 for (int i = 0; i < scope->id_info_len; i++) {
3024 id_info_t *id = &scope->id_info[i];
3025 if (id->param || id->kind != ID_INFO_KIND_FREE) {
3026 id->local_num += num_free;
3027 }
3028 }
3029 scope->num_params += num_free; // free vars are counted as params for passing them into the function
3030 scope->num_locals += num_free;
3031 }
3032#endif
Damien429d7192013-10-04 19:53:11 +01003033 }
3034
3035 // compute flags
3036 //scope->flags = 0; since we set some things in parameters
3037 if (scope->kind != SCOPE_MODULE) {
3038 scope->flags |= SCOPE_FLAG_NEWLOCALS;
3039 }
3040 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) {
3041 assert(scope->parent != NULL);
3042 scope->flags |= SCOPE_FLAG_OPTIMISED;
3043
3044 // TODO possibly other ways it can be nested
Damien George08d07552014-01-29 18:58:52 +00003045 // Note that we don't actually use this information at the moment (for CPython compat only)
3046 if ((SCOPE_FUNCTION <= scope->parent->kind && scope->parent->kind <= SCOPE_SET_COMP) || (scope->parent->kind == SCOPE_CLASS && scope->parent->parent->kind == SCOPE_FUNCTION)) {
Damien429d7192013-10-04 19:53:11 +01003047 scope->flags |= SCOPE_FLAG_NESTED;
3048 }
3049 }
3050 int num_free = 0;
3051 for (int i = 0; i < scope->id_info_len; i++) {
3052 id_info_t *id = &scope->id_info[i];
3053 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3054 num_free += 1;
3055 }
3056 }
3057 if (num_free == 0) {
3058 scope->flags |= SCOPE_FLAG_NOFREE;
3059 }
3060}
3061
Damien George08335002014-01-18 23:24:36 +00003062mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003063 compiler_t *comp = m_new(compiler_t, 1);
3064
Damien Georgecbd2f742014-01-19 11:48:48 +00003065 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003066 comp->is_repl = is_repl;
3067 comp->had_error = false;
3068
Damien429d7192013-10-04 19:53:11 +01003069 comp->break_label = 0;
3070 comp->continue_label = 0;
Damien Georgecbddb272014-02-01 20:08:18 +00003071 comp->break_continue_except_level = 0;
3072 comp->cur_except_level = 0;
3073
Damien George35e2a4e2014-02-05 00:51:47 +00003074 comp->func_arg_is_super = false;
3075
Damien429d7192013-10-04 19:53:11 +01003076 comp->scope_head = NULL;
3077 comp->scope_cur = NULL;
3078
Damien826005c2013-10-05 23:17:28 +01003079 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003080 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003081
3082 // set the outer scope
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003083 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003084
Damien826005c2013-10-05 23:17:28 +01003085 // compile pass 1
Damien George35e2a4e2014-02-05 00:51:47 +00003086 comp->emit = emit_pass1_new();
Damien826005c2013-10-05 23:17:28 +01003087 comp->emit_method_table = &emit_pass1_method_table;
3088 comp->emit_inline_asm = NULL;
3089 comp->emit_inline_asm_method_table = NULL;
3090 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003091 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003092 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003093#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003094 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003095 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003096#endif
Damien826005c2013-10-05 23:17:28 +01003097 } else {
3098 compile_scope(comp, s, PASS_1);
3099 }
3100
3101 // update maximim number of labels needed
3102 if (comp->next_label > max_num_labels) {
3103 max_num_labels = comp->next_label;
3104 }
Damien429d7192013-10-04 19:53:11 +01003105 }
3106
Damien826005c2013-10-05 23:17:28 +01003107 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003108 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003109 compile_scope_compute_things(comp, s);
3110 }
3111
Damien826005c2013-10-05 23:17:28 +01003112 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003113 emit_pass1_free(comp->emit);
3114
Damien826005c2013-10-05 23:17:28 +01003115 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003116#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003117 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003118#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003119 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003120#endif
Damien3ef4abb2013-10-12 16:53:13 +01003121#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003122 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003123#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003124#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003125 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003126 if (false) {
3127 // dummy
3128
Damien3ef4abb2013-10-12 16:53:13 +01003129#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003130 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3131 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003132 if (emit_inline_thumb == NULL) {
3133 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3134 }
3135 comp->emit = NULL;
3136 comp->emit_method_table = NULL;
3137 comp->emit_inline_asm = emit_inline_thumb;
3138 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3139 compile_scope_inline_asm(comp, s, PASS_2);
3140 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003141#endif
3142
Damien826005c2013-10-05 23:17:28 +01003143 } else {
Damienc025ebb2013-10-12 14:30:21 +01003144
3145 // choose the emit type
3146
Damien3ef4abb2013-10-12 16:53:13 +01003147#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003148 comp->emit = emit_cpython_new(max_num_labels);
3149 comp->emit_method_table = &emit_cpython_method_table;
3150#else
Damien826005c2013-10-05 23:17:28 +01003151 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003152
3153#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003154 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003155 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003156#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003157 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003158 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003159 }
Damien13ed3a62013-10-08 09:05:10 +01003160 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003161#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003162 if (emit_native == NULL) {
3163 emit_native = emit_native_thumb_new(max_num_labels);
3164 }
3165 comp->emit_method_table = &emit_native_thumb_method_table;
3166#endif
3167 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003168 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003169 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003170#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003171
Damien826005c2013-10-05 23:17:28 +01003172 default:
3173 if (emit_bc == NULL) {
Damien Georgecbd2f742014-01-19 11:48:48 +00003174 emit_bc = emit_bc_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003175 }
3176 comp->emit = emit_bc;
3177 comp->emit_method_table = &emit_bc_method_table;
3178 break;
3179 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003180#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003181
3182 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003183 compile_scope(comp, s, PASS_2);
3184 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003185 }
Damien429d7192013-10-04 19:53:11 +01003186 }
3187
Damien George41d02b62014-01-24 22:42:28 +00003188 // free the emitters
3189#if !MICROPY_EMIT_CPYTHON
3190 if (emit_bc != NULL) {
3191 emit_bc_free(emit_bc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +02003192 }
Damien George41d02b62014-01-24 22:42:28 +00003193#if MICROPY_EMIT_NATIVE
3194 if (emit_native != NULL) {
3195#if MICROPY_EMIT_X64
3196 emit_native_x64_free(emit_native);
3197#elif MICROPY_EMIT_THUMB
3198 emit_native_thumb_free(emit_native);
3199#endif
3200 }
3201#endif
3202#if MICROPY_EMIT_INLINE_THUMB
3203 if (emit_inline_thumb != NULL) {
3204 emit_inline_thumb_free(emit_inline_thumb);
3205 }
3206#endif
3207#endif // !MICROPY_EMIT_CPYTHON
3208
3209 // free the scopes
Paul Sokolovskyfd313582014-01-23 23:05:47 +02003210 uint unique_code_id = module_scope->unique_code_id;
3211 for (scope_t *s = module_scope; s;) {
3212 scope_t *next = s->next;
3213 scope_free(s);
3214 s = next;
3215 }
Damien5ac1b2e2013-10-18 19:58:12 +01003216
Damien George41d02b62014-01-24 22:42:28 +00003217 // free the compiler
3218 bool had_error = comp->had_error;
3219 m_del_obj(compiler_t, comp);
3220
Damien George1fb03172014-01-03 14:22:03 +00003221 if (had_error) {
3222 // TODO return a proper error message
3223 return mp_const_none;
3224 } else {
3225#if MICROPY_EMIT_CPYTHON
3226 // can't create code, so just return true
Damien George41d02b62014-01-24 22:42:28 +00003227 (void)unique_code_id; // to suppress warning that unique_code_id is unused
Damien George1fb03172014-01-03 14:22:03 +00003228 return mp_const_true;
3229#else
3230 // return function that executes the outer module
Paul Sokolovsky90750022014-02-01 15:05:04 +02003231 return rt_make_function_from_id(unique_code_id, MP_OBJ_NULL);
Damien George1fb03172014-01-03 14:22:03 +00003232#endif
3233 }
Damien429d7192013-10-04 19:53:11 +01003234}