blob: c895b26fa914756413ee651cf741aae724da53c5 [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
Paul Sokolovskya1aba362014-02-20 13:21:31 +02001190 // This covers relative imports starting with dot(s) like "from .foo import"
Damien429d7192013-10-04 19:53:11 +01001191 assert(0);
1192 }
1193 } else {
1194 // TODO not implemented
Paul Sokolovskya1aba362014-02-20 13:21:31 +02001195 // This covers relative imports with dots only like "from .. import"
Damien429d7192013-10-04 19:53:11 +01001196 assert(0);
1197 }
1198}
1199
Damiend99b0522013-12-21 18:17:45 +00001200void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgeb9791222014-01-23 00:34:21 +00001201 EMIT_ARG(load_const_small_int, 0); // ??
1202 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001203 qstr q1, q2;
1204 do_import_name(comp, pn, &q1, &q2);
Damien Georgeb9791222014-01-23 00:34:21 +00001205 EMIT_ARG(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001206}
1207
Damiend99b0522013-12-21 18:17:45 +00001208void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001209 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1210}
1211
Damiend99b0522013-12-21 18:17:45 +00001212void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1213 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001214 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001215
1216 // build the "fromlist" tuple
1217#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001218 EMIT_ARG(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001219#else
Damien Georgeb9791222014-01-23 00:34:21 +00001220 EMIT_ARG(load_const_str, QSTR_FROM_STR_STATIC("*"), false);
1221 EMIT_ARG(build_tuple, 1);
Damiendb4c3612013-12-10 17:27:24 +00001222#endif
1223
1224 // do the import
Damien429d7192013-10-04 19:53:11 +01001225 qstr dummy_q, id1;
1226 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1227 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001228
Damien429d7192013-10-04 19:53:11 +01001229 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001230 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001231
1232 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001233 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001234 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001235#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001236 {
1237 vstr_t *vstr = vstr_new();
1238 vstr_printf(vstr, "(");
1239 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001240 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1241 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1242 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001243 if (i > 0) {
1244 vstr_printf(vstr, ", ");
1245 }
1246 vstr_printf(vstr, "'");
Damien George55baff42014-01-21 21:40:13 +00001247 uint len;
1248 const byte *str = qstr_data(id2, &len);
1249 vstr_add_strn(vstr, (const char*)str, len);
Damien02f89412013-12-12 15:13:36 +00001250 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001251 }
Damien02f89412013-12-12 15:13:36 +00001252 if (n == 1) {
1253 vstr_printf(vstr, ",");
1254 }
1255 vstr_printf(vstr, ")");
Damien Georgeb9791222014-01-23 00:34:21 +00001256 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001257 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001258 }
Damiendb4c3612013-12-10 17:27:24 +00001259#else
1260 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001261 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1262 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1263 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001264 EMIT_ARG(load_const_str, id2, false);
Damiendb4c3612013-12-10 17:27:24 +00001265 }
Damien Georgeb9791222014-01-23 00:34:21 +00001266 EMIT_ARG(build_tuple, n);
Damiendb4c3612013-12-10 17:27:24 +00001267#endif
1268
1269 // do the import
Damien429d7192013-10-04 19:53:11 +01001270 qstr dummy_q, id1;
1271 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1272 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001273 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1274 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1275 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001276 EMIT_ARG(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001277 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001278 EMIT_ARG(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001279 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001280 EMIT_ARG(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001281 }
1282 }
1283 EMIT(pop_top);
1284 }
1285}
1286
Damiend99b0522013-12-21 18:17:45 +00001287void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001288 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001289 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1290 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001291 } else {
Damiend99b0522013-12-21 18:17:45 +00001292 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1293 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001294 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001295 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001296 }
Damien429d7192013-10-04 19:53:11 +01001297 }
1298 }
1299}
1300
Damiend99b0522013-12-21 18:17:45 +00001301void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001302 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001303 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1304 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001305 } else {
Damiend99b0522013-12-21 18:17:45 +00001306 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1307 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001308 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001309 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001310 }
Damien429d7192013-10-04 19:53:11 +01001311 }
1312 }
1313}
1314
Damiend99b0522013-12-21 18:17:45 +00001315void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001316 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001317 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien Georgeb9791222014-01-23 00:34:21 +00001318 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 +00001319 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001320 // assertion message
1321 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001322 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001323 }
Damien Georgeb9791222014-01-23 00:34:21 +00001324 EMIT_ARG(raise_varargs, 1);
1325 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001326}
1327
Damiend99b0522013-12-21 18:17:45 +00001328void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001329 // TODO proper and/or short circuiting
1330
Damienb05d7072013-10-05 13:37:10 +01001331 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001332
Damienb05d7072013-10-05 13:37:10 +01001333 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001334 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1335
1336 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001337 //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 +01001338 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001339 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001340 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001341 }
1342 //}
Damien Georgeb9791222014-01-23 00:34:21 +00001343 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001344
Damiend99b0522013-12-21 18:17:45 +00001345 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001346 // compile elif blocks
1347
Damiend99b0522013-12-21 18:17:45 +00001348 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001349
Damiend99b0522013-12-21 18:17:45 +00001350 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001351 // multiple elif blocks
1352
Damiend99b0522013-12-21 18:17:45 +00001353 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001354 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001355 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
Damienb05d7072013-10-05 13:37:10 +01001356 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001357 c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition
1358
1359 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001360 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001361 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001362 }
Damien Georgeb9791222014-01-23 00:34:21 +00001363 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001364 }
1365
1366 } else {
1367 // a single elif block
1368
Damienb05d7072013-10-05 13:37:10 +01001369 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001370 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1371
1372 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001373 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001374 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001375 }
Damien Georgeb9791222014-01-23 00:34:21 +00001376 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001377 }
1378 }
1379
1380 // compile else block
1381 compile_node(comp, pns->nodes[3]); // can be null
1382
Damien Georgeb9791222014-01-23 00:34:21 +00001383 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001384}
1385
Damien Georgecbddb272014-02-01 20:08:18 +00001386#define START_BREAK_CONTINUE_BLOCK \
1387 int old_break_label = comp->break_label; \
1388 int old_continue_label = comp->continue_label; \
1389 int break_label = comp_next_label(comp); \
1390 int continue_label = comp_next_label(comp); \
1391 comp->break_label = break_label; \
1392 comp->continue_label = continue_label; \
1393 comp->break_continue_except_level = comp->cur_except_level;
1394
1395#define END_BREAK_CONTINUE_BLOCK \
1396 comp->break_label = old_break_label; \
1397 comp->continue_label = old_continue_label; \
1398 comp->break_continue_except_level = comp->cur_except_level;
1399
Damiend99b0522013-12-21 18:17:45 +00001400void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgecbddb272014-02-01 20:08:18 +00001401 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001402
Damience89a212013-10-15 22:25:17 +01001403 // compared to CPython, we have an optimised version of while loops
1404#if MICROPY_EMIT_CPYTHON
1405 int done_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001406 EMIT_ARG(setup_loop, break_label);
1407 EMIT_ARG(label_assign, continue_label);
Damien429d7192013-10-04 19:53:11 +01001408 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1409 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001410 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001411 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001412 }
Damien Georgeb9791222014-01-23 00:34:21 +00001413 EMIT_ARG(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001414 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1415 // this is a small hack to agree with CPython
1416 if (!node_is_const_true(pns->nodes[0])) {
1417 EMIT(pop_block);
1418 }
Damience89a212013-10-15 22:25:17 +01001419#else
1420 int top_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001421 EMIT_ARG(jump, continue_label);
1422 EMIT_ARG(label_assign, top_label);
Damience89a212013-10-15 22:25:17 +01001423 compile_node(comp, pns->nodes[1]); // body
Damien Georgeb9791222014-01-23 00:34:21 +00001424 EMIT_ARG(label_assign, continue_label);
Damience89a212013-10-15 22:25:17 +01001425 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1426#endif
1427
1428 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001429 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001430
1431 compile_node(comp, pns->nodes[2]); // else
1432
Damien Georgeb9791222014-01-23 00:34:21 +00001433 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001434}
1435
Damienf72fd0e2013-11-06 20:20:49 +00001436// TODO preload end and step onto stack if they are not constants
1437// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001438void 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 +00001439 START_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001440
1441 int top_label = comp_next_label(comp);
Damien George600ae732014-01-21 23:48:04 +00001442 int entry_label = comp_next_label(comp);
Damienf72fd0e2013-11-06 20:20:49 +00001443
1444 // compile: var = start
1445 compile_node(comp, pn_start);
1446 c_assign(comp, pn_var, ASSIGN_STORE);
1447
Damien Georgeb9791222014-01-23 00:34:21 +00001448 EMIT_ARG(jump, entry_label);
1449 EMIT_ARG(label_assign, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001450
Damienf3822fc2013-11-09 20:12:03 +00001451 // compile body
1452 compile_node(comp, pn_body);
1453
Damien Georgeb9791222014-01-23 00:34:21 +00001454 EMIT_ARG(label_assign, continue_label);
Damien George600ae732014-01-21 23:48:04 +00001455
Damienf72fd0e2013-11-06 20:20:49 +00001456 // compile: var += step
1457 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1458 compile_node(comp, pn_step);
Damien Georgeb9791222014-01-23 00:34:21 +00001459 EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_ADD);
Damienf72fd0e2013-11-06 20:20:49 +00001460 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1461
Damien Georgeb9791222014-01-23 00:34:21 +00001462 EMIT_ARG(label_assign, entry_label);
Damienf72fd0e2013-11-06 20:20:49 +00001463
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001464 // compile: if var <cond> end: goto top
Damienf72fd0e2013-11-06 20:20:49 +00001465 compile_node(comp, pn_var);
1466 compile_node(comp, pn_end);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001467 if (MP_PARSE_NODE_LEAF_ARG(pn_step) >= 0) {
Damien George9aa2a522014-02-01 23:04:09 +00001468 EMIT_ARG(binary_op, RT_BINARY_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001469 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001470 EMIT_ARG(binary_op, RT_BINARY_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001471 }
Damien Georgeb9791222014-01-23 00:34:21 +00001472 EMIT_ARG(pop_jump_if_true, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001473
1474 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001475 END_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001476
1477 compile_node(comp, pn_else);
1478
Damien Georgeb9791222014-01-23 00:34:21 +00001479 EMIT_ARG(label_assign, break_label);
Damienf72fd0e2013-11-06 20:20:49 +00001480}
1481
Damiend99b0522013-12-21 18:17:45 +00001482void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001483#if !MICROPY_EMIT_CPYTHON
1484 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1485 // this is actually slower, but uses no heap memory
1486 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001487 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)) {
1488 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001489 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1490 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1491 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
1492 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
Damiend99b0522013-12-21 18:17:45 +00001493 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1494 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001495 int n_args = list_get(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001496 mp_parse_node_t pn_range_start;
1497 mp_parse_node_t pn_range_end;
1498 mp_parse_node_t pn_range_step;
1499 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001500 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001501 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001502 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001503 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001504 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001505 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001506 } else if (n_args == 2) {
1507 pn_range_start = args[0];
1508 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001509 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001510 } else {
1511 pn_range_start = args[0];
1512 pn_range_end = args[1];
1513 pn_range_step = args[2];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001514 // We need to know sign of step. This is possible only if it's constant
1515 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
1516 optimize = false;
1517 }
Damienf72fd0e2013-11-06 20:20:49 +00001518 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001519 }
1520 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001521 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1522 return;
1523 }
1524 }
1525 }
1526#endif
1527
Damien Georgecbddb272014-02-01 20:08:18 +00001528 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001529
Damienb05d7072013-10-05 13:37:10 +01001530 int pop_label = comp_next_label(comp);
1531 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001532
Damience89a212013-10-15 22:25:17 +01001533 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1534#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001535 EMIT_ARG(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001536#endif
1537
Damien429d7192013-10-04 19:53:11 +01001538 compile_node(comp, pns->nodes[1]); // iterator
1539 EMIT(get_iter);
Damien Georgecbddb272014-02-01 20:08:18 +00001540 EMIT_ARG(label_assign, continue_label);
Damien Georgeb9791222014-01-23 00:34:21 +00001541 EMIT_ARG(for_iter, pop_label);
Damien429d7192013-10-04 19:53:11 +01001542 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1543 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001544 if (!EMIT(last_emit_was_return_value)) {
Damien Georgecbddb272014-02-01 20:08:18 +00001545 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001546 }
Damien Georgeb9791222014-01-23 00:34:21 +00001547 EMIT_ARG(label_assign, pop_label);
Damien429d7192013-10-04 19:53:11 +01001548 EMIT(for_iter_end);
1549
1550 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001551 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001552
Damience89a212013-10-15 22:25:17 +01001553#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001554 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001555#endif
Damien429d7192013-10-04 19:53:11 +01001556
1557 compile_node(comp, pns->nodes[3]); // else (not tested)
1558
Damien Georgeb9791222014-01-23 00:34:21 +00001559 EMIT_ARG(label_assign, break_label);
1560 EMIT_ARG(label_assign, end_label);
Damien429d7192013-10-04 19:53:11 +01001561}
1562
Damiend99b0522013-12-21 18:17:45 +00001563void 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 +01001564 // this function is a bit of a hack at the moment
1565 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1566
1567 // setup code
1568 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001569 int l1 = comp_next_label(comp);
1570 int success_label = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001571
Damien Georgeb9791222014-01-23 00:34:21 +00001572 EMIT_ARG(setup_except, l1);
Damien Georgecbddb272014-02-01 20:08:18 +00001573 comp->cur_except_level += 1;
1574
Damien429d7192013-10-04 19:53:11 +01001575 compile_node(comp, pn_body); // body
1576 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001577 EMIT_ARG(jump, success_label);
1578 EMIT_ARG(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001579 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001580
1581 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001582 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1583 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001584
1585 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001586 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001587
Damiend99b0522013-12-21 18:17:45 +00001588 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001589 // this is a catch all exception handler
1590 if (i + 1 != n_except) {
1591 printf("SyntaxError: default 'except:' must be last\n");
1592 return;
1593 }
1594 } else {
1595 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001596 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1597 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1598 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1599 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001600 // handler binds the exception to a local
1601 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001602 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001603 }
1604 }
1605 EMIT(dup_top);
1606 compile_node(comp, pns_exception_expr);
Damien George9aa2a522014-02-01 23:04:09 +00001607 EMIT_ARG(binary_op, RT_BINARY_OP_EXCEPTION_MATCH);
Damien Georgeb9791222014-01-23 00:34:21 +00001608 EMIT_ARG(pop_jump_if_false, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001609 }
1610
1611 EMIT(pop_top);
1612
1613 if (qstr_exception_local == 0) {
1614 EMIT(pop_top);
1615 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001616 EMIT_ARG(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001617 }
1618
1619 EMIT(pop_top);
1620
Damiene2880aa2013-12-20 14:22:59 +00001621 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001622 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001623 l3 = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001624 EMIT_ARG(setup_finally, l3);
Damien Georgecbddb272014-02-01 20:08:18 +00001625 comp->cur_except_level += 1;
Damien429d7192013-10-04 19:53:11 +01001626 }
1627 compile_node(comp, pns_except->nodes[1]);
1628 if (qstr_exception_local != 0) {
1629 EMIT(pop_block);
1630 }
1631 EMIT(pop_except);
1632 if (qstr_exception_local != 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001633 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1634 EMIT_ARG(label_assign, l3);
1635 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1636 EMIT_ARG(store_id, qstr_exception_local);
1637 EMIT_ARG(delete_id, qstr_exception_local);
Damien Georgecbddb272014-02-01 20:08:18 +00001638
1639 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001640 EMIT(end_finally);
1641 }
Damien Georgeb9791222014-01-23 00:34:21 +00001642 EMIT_ARG(jump, l2);
1643 EMIT_ARG(label_assign, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001644 }
1645
Damien Georgecbddb272014-02-01 20:08:18 +00001646 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001647 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001648
Damien Georgeb9791222014-01-23 00:34:21 +00001649 EMIT_ARG(label_assign, success_label);
Damien429d7192013-10-04 19:53:11 +01001650 compile_node(comp, pn_else); // else block, can be null
Damien Georgeb9791222014-01-23 00:34:21 +00001651 EMIT_ARG(label_assign, l2);
1652 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001653}
1654
Damiend99b0522013-12-21 18:17:45 +00001655void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) {
Damien429d7192013-10-04 19:53:11 +01001656 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1657 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001658 int l_finally_block = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001659
Damien Georgeb9791222014-01-23 00:34:21 +00001660 EMIT_ARG(setup_finally, l_finally_block);
Damien Georgecbddb272014-02-01 20:08:18 +00001661 comp->cur_except_level += 1;
1662
Damien429d7192013-10-04 19:53:11 +01001663 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001664 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001665 compile_node(comp, pn_body);
1666 } else {
1667 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1668 }
1669 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001670 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1671 EMIT_ARG(label_assign, l_finally_block);
Damien429d7192013-10-04 19:53:11 +01001672 compile_node(comp, pn_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001673
1674 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001675 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001676
Damien Georgeb9791222014-01-23 00:34:21 +00001677 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001678}
1679
Damiend99b0522013-12-21 18:17:45 +00001680void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1681 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1682 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1683 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001684 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001685 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1686 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001687 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001688 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001689 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001690 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001691 // no finally
1692 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1693 } else {
1694 // have finally
Damiend99b0522013-12-21 18:17:45 +00001695 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 +01001696 }
1697 } else {
1698 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001699 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001700 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001701 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001702 }
1703 } else {
1704 // shouldn't happen
1705 assert(0);
1706 }
1707}
1708
Damiend99b0522013-12-21 18:17:45 +00001709void 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 +01001710 if (n == 0) {
1711 // no more pre-bits, compile the body of the with
1712 compile_node(comp, body);
1713 } else {
Damienb05d7072013-10-05 13:37:10 +01001714 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001715 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001716 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001717 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001718 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001719 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001720 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1721 } else {
1722 // this pre-bit is just an expression
1723 compile_node(comp, nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001724 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001725 EMIT(pop_top);
1726 }
1727 // compile additional pre-bits and the body
1728 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1729 // finish this with block
1730 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001731 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1732 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001733 EMIT(with_cleanup);
1734 EMIT(end_finally);
1735 }
1736}
1737
Damiend99b0522013-12-21 18:17:45 +00001738void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001739 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001740 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001741 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1742 assert(n > 0);
1743
1744 // compile in a nested fashion
1745 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1746}
1747
Damiend99b0522013-12-21 18:17:45 +00001748void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1749 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001750 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1751 // for REPL, evaluate then print the expression
Damien Georgeb9791222014-01-23 00:34:21 +00001752 EMIT_ARG(load_id, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001753 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001754 EMIT_ARG(call_function, 1, 0, false, false);
Damien5ac1b2e2013-10-18 19:58:12 +01001755 EMIT(pop_top);
1756
Damien429d7192013-10-04 19:53:11 +01001757 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001758 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001759 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001760 // do nothing with a lonely constant
1761 } else {
1762 compile_node(comp, pns->nodes[0]); // just an expression
1763 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1764 }
Damien429d7192013-10-04 19:53:11 +01001765 }
1766 } else {
Damiend99b0522013-12-21 18:17:45 +00001767 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1768 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001769 if (kind == PN_expr_stmt_augassign) {
1770 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1771 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001772 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien George7e5fb242014-02-01 22:18:47 +00001773 rt_binary_op_t op;
Damiend99b0522013-12-21 18:17:45 +00001774 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
Damien George7e5fb242014-02-01 22:18:47 +00001775 case MP_TOKEN_DEL_PIPE_EQUAL: op = RT_BINARY_OP_INPLACE_OR; break;
1776 case MP_TOKEN_DEL_CARET_EQUAL: op = RT_BINARY_OP_INPLACE_XOR; break;
1777 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = RT_BINARY_OP_INPLACE_AND; break;
1778 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = RT_BINARY_OP_INPLACE_LSHIFT; break;
1779 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = RT_BINARY_OP_INPLACE_RSHIFT; break;
1780 case MP_TOKEN_DEL_PLUS_EQUAL: op = RT_BINARY_OP_INPLACE_ADD; break;
1781 case MP_TOKEN_DEL_MINUS_EQUAL: op = RT_BINARY_OP_INPLACE_SUBTRACT; break;
1782 case MP_TOKEN_DEL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_MULTIPLY; break;
1783 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
1784 case MP_TOKEN_DEL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
1785 case MP_TOKEN_DEL_PERCENT_EQUAL: op = RT_BINARY_OP_INPLACE_MODULO; break;
1786 case MP_TOKEN_DEL_DBL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_POWER; break;
1787 default: assert(0); op = RT_BINARY_OP_INPLACE_OR; // shouldn't happen
Damien429d7192013-10-04 19:53:11 +01001788 }
Damien George7e5fb242014-02-01 22:18:47 +00001789 EMIT_ARG(binary_op, op);
Damien429d7192013-10-04 19:53:11 +01001790 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1791 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001792 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1793 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001794 // following CPython, we store left-most first
1795 if (rhs > 0) {
1796 EMIT(dup_top);
1797 }
1798 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1799 for (int i = 0; i < rhs; i++) {
1800 if (i + 1 < rhs) {
1801 EMIT(dup_top);
1802 }
Damiend99b0522013-12-21 18:17:45 +00001803 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001804 }
1805 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001806 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1807 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1808 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1809 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001810 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001811 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1812 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001813 compile_node(comp, pns10->nodes[0]); // rhs
1814 compile_node(comp, pns10->nodes[1]); // rhs
1815 EMIT(rot_two);
1816 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1817 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001818 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1819 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1820 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1821 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001822 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001823 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1824 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001825 compile_node(comp, pns10->nodes[0]); // rhs
1826 compile_node(comp, pns10->nodes[1]); // rhs
1827 compile_node(comp, pns10->nodes[2]); // rhs
1828 EMIT(rot_three);
1829 EMIT(rot_two);
1830 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1831 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1832 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1833 } else {
1834 compile_node(comp, pns1->nodes[0]); // rhs
1835 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1836 }
1837 } else {
1838 // shouldn't happen
1839 assert(0);
1840 }
1841 }
1842}
1843
Damiend99b0522013-12-21 18:17:45 +00001844void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1845 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001846 compile_node(comp, pns->nodes[0]);
1847 for (int i = 1; i < num_nodes; i += 1) {
1848 compile_node(comp, pns->nodes[i]);
Damien Georgeb9791222014-01-23 00:34:21 +00001849 EMIT_ARG(binary_op, binary_op);
Damien429d7192013-10-04 19:53:11 +01001850 }
1851}
1852
Damiend99b0522013-12-21 18:17:45 +00001853void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1854 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1855 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001856
1857 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001858 int l_fail = comp_next_label(comp);
1859 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001860 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1861 compile_node(comp, pns->nodes[0]); // success value
Damien Georgeb9791222014-01-23 00:34:21 +00001862 EMIT_ARG(jump, l_end);
1863 EMIT_ARG(label_assign, l_fail);
1864 EMIT_ARG(set_stack_size, stack_size); // force stack size reset
Damien429d7192013-10-04 19:53:11 +01001865 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
Damien Georgeb9791222014-01-23 00:34:21 +00001866 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001867}
1868
Damiend99b0522013-12-21 18:17:45 +00001869void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001870 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001871 //mp_parse_node_t pn_params = pns->nodes[0];
1872 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001873
1874 if (comp->pass == PASS_1) {
1875 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001876 scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01001877 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001878 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001879 }
1880
1881 // get the scope for this lambda
1882 scope_t *this_scope = (scope_t*)pns->nodes[2];
1883
1884 // make the lambda
1885 close_over_variables_etc(comp, this_scope, 0, 0);
1886}
1887
Damiend99b0522013-12-21 18:17:45 +00001888void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001889 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001890 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001891 for (int i = 0; i < n; i += 1) {
1892 compile_node(comp, pns->nodes[i]);
1893 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001894 EMIT_ARG(jump_if_true_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001895 }
1896 }
Damien Georgeb9791222014-01-23 00:34:21 +00001897 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001898}
1899
Damiend99b0522013-12-21 18:17:45 +00001900void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001901 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001902 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001903 for (int i = 0; i < n; i += 1) {
1904 compile_node(comp, pns->nodes[i]);
1905 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001906 EMIT_ARG(jump_if_false_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001907 }
1908 }
Damien Georgeb9791222014-01-23 00:34:21 +00001909 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001910}
1911
Damiend99b0522013-12-21 18:17:45 +00001912void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001913 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001914 EMIT_ARG(unary_op, RT_UNARY_OP_NOT);
Damien429d7192013-10-04 19:53:11 +01001915}
1916
Damiend99b0522013-12-21 18:17:45 +00001917void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001918 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001919 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001920 compile_node(comp, pns->nodes[0]);
1921 bool multi = (num_nodes > 3);
1922 int l_fail = 0;
1923 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001924 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001925 }
1926 for (int i = 1; i + 1 < num_nodes; i += 2) {
1927 compile_node(comp, pns->nodes[i + 1]);
1928 if (i + 2 < num_nodes) {
1929 EMIT(dup_top);
1930 EMIT(rot_three);
1931 }
Damien George7e5fb242014-02-01 22:18:47 +00001932 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
1933 rt_binary_op_t op;
1934 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
Damien George9aa2a522014-02-01 23:04:09 +00001935 case MP_TOKEN_OP_LESS: op = RT_BINARY_OP_LESS; break;
1936 case MP_TOKEN_OP_MORE: op = RT_BINARY_OP_MORE; break;
1937 case MP_TOKEN_OP_DBL_EQUAL: op = RT_BINARY_OP_EQUAL; break;
1938 case MP_TOKEN_OP_LESS_EQUAL: op = RT_BINARY_OP_LESS_EQUAL; break;
1939 case MP_TOKEN_OP_MORE_EQUAL: op = RT_BINARY_OP_MORE_EQUAL; break;
1940 case MP_TOKEN_OP_NOT_EQUAL: op = RT_BINARY_OP_NOT_EQUAL; break;
1941 case MP_TOKEN_KW_IN: op = RT_BINARY_OP_IN; break;
1942 default: assert(0); op = RT_BINARY_OP_LESS; // shouldn't happen
Damien George7e5fb242014-02-01 22:18:47 +00001943 }
1944 EMIT_ARG(binary_op, op);
Damiend99b0522013-12-21 18:17:45 +00001945 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
1946 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
1947 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01001948 if (kind == PN_comp_op_not_in) {
Damien George9aa2a522014-02-01 23:04:09 +00001949 EMIT_ARG(binary_op, RT_BINARY_OP_NOT_IN);
Damien429d7192013-10-04 19:53:11 +01001950 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00001951 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien George9aa2a522014-02-01 23:04:09 +00001952 EMIT_ARG(binary_op, RT_BINARY_OP_IS);
Damien429d7192013-10-04 19:53:11 +01001953 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001954 EMIT_ARG(binary_op, RT_BINARY_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01001955 }
1956 } else {
1957 // shouldn't happen
1958 assert(0);
1959 }
1960 } else {
1961 // shouldn't happen
1962 assert(0);
1963 }
1964 if (i + 2 < num_nodes) {
Damien Georgeb9791222014-01-23 00:34:21 +00001965 EMIT_ARG(jump_if_false_or_pop, l_fail);
Damien429d7192013-10-04 19:53:11 +01001966 }
1967 }
1968 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001969 int l_end = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001970 EMIT_ARG(jump, l_end);
1971 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001972 EMIT(rot_two);
1973 EMIT(pop_top);
Damien Georgeb9791222014-01-23 00:34:21 +00001974 EMIT_ARG(label_assign, l_end);
1975 EMIT_ARG(set_stack_size, stack_size + 1); // force stack size
Damien429d7192013-10-04 19:53:11 +01001976 }
1977}
1978
Damiend99b0522013-12-21 18:17:45 +00001979void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001980 // TODO
1981 assert(0);
1982 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001983 //EMIT_ARG(unary_op, "UNARY_STAR");
Damien429d7192013-10-04 19:53:11 +01001984}
1985
Damiend99b0522013-12-21 18:17:45 +00001986void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001987 c_binary_op(comp, pns, RT_BINARY_OP_OR);
1988}
1989
Damiend99b0522013-12-21 18:17:45 +00001990void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001991 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
1992}
1993
Damiend99b0522013-12-21 18:17:45 +00001994void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001995 c_binary_op(comp, pns, RT_BINARY_OP_AND);
1996}
1997
Damiend99b0522013-12-21 18:17:45 +00001998void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1999 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002000 compile_node(comp, pns->nodes[0]);
2001 for (int i = 1; i + 1 < num_nodes; i += 2) {
2002 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002003 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002004 EMIT_ARG(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00002005 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002006 EMIT_ARG(binary_op, RT_BINARY_OP_RSHIFT);
Damien429d7192013-10-04 19:53:11 +01002007 } else {
2008 // shouldn't happen
2009 assert(0);
2010 }
2011 }
2012}
2013
Damiend99b0522013-12-21 18:17:45 +00002014void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2015 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002016 compile_node(comp, pns->nodes[0]);
2017 for (int i = 1; i + 1 < num_nodes; i += 2) {
2018 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002019 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002020 EMIT_ARG(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002021 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002022 EMIT_ARG(binary_op, RT_BINARY_OP_SUBTRACT);
Damien429d7192013-10-04 19:53:11 +01002023 } else {
2024 // shouldn't happen
2025 assert(0);
2026 }
2027 }
2028}
2029
Damiend99b0522013-12-21 18:17:45 +00002030void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2031 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002032 compile_node(comp, pns->nodes[0]);
2033 for (int i = 1; i + 1 < num_nodes; i += 2) {
2034 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002035 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002036 EMIT_ARG(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002037 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002038 EMIT_ARG(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002039 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002040 EMIT_ARG(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002041 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002042 EMIT_ARG(binary_op, RT_BINARY_OP_MODULO);
Damien429d7192013-10-04 19:53:11 +01002043 } else {
2044 // shouldn't happen
2045 assert(0);
2046 }
2047 }
2048}
2049
Damiend99b0522013-12-21 18:17:45 +00002050void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002051 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002052 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002053 EMIT_ARG(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002054 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002055 EMIT_ARG(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002056 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002057 EMIT_ARG(unary_op, RT_UNARY_OP_INVERT);
Damien429d7192013-10-04 19:53:11 +01002058 } else {
2059 // shouldn't happen
2060 assert(0);
2061 }
2062}
2063
Damien George35e2a4e2014-02-05 00:51:47 +00002064void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
2065 // this is to handle special super() call
2066 comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
2067
2068 compile_generic_all_nodes(comp, pns);
2069}
2070
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002071STATIC 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 +01002072 // function to call is on top of stack
2073
Damien George35e2a4e2014-02-05 00:51:47 +00002074#if !MICROPY_EMIT_CPYTHON
2075 // this is to handle special super() call
Damien Georgebbcd49a2014-02-06 20:30:16 +00002076 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 +00002077 EMIT_ARG(load_id, MP_QSTR___class__);
2078 // get first argument to function
2079 bool found = false;
2080 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
2081 if (comp->scope_cur->id_info[i].param) {
2082 EMIT_ARG(load_fast, MP_QSTR_, comp->scope_cur->id_info[i].local_num);
2083 found = true;
2084 break;
2085 }
2086 }
2087 if (!found) {
2088 printf("TypeError: super() call cannot find self\n");
2089 return;
2090 }
2091 EMIT_ARG(call_function, 2, 0, false, false);
2092 return;
2093 }
2094#endif
2095
Damien429d7192013-10-04 19:53:11 +01002096 int old_n_arg_keyword = comp->n_arg_keyword;
2097 bool old_have_star_arg = comp->have_star_arg;
2098 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2099 comp->n_arg_keyword = 0;
2100 comp->have_star_arg = false;
2101 comp->have_dbl_star_arg = false;
2102
Damien Georgebbcd49a2014-02-06 20:30:16 +00002103 compile_node(comp, pn_arglist); // arguments to function call; can be null
Damien429d7192013-10-04 19:53:11 +01002104
2105 // compute number of positional arguments
Damien Georgebbcd49a2014-02-06 20:30:16 +00002106 int n_positional = n_positional_extra + list_len(pn_arglist, PN_arglist) - comp->n_arg_keyword;
Damien429d7192013-10-04 19:53:11 +01002107 if (comp->have_star_arg) {
2108 n_positional -= 1;
2109 }
2110 if (comp->have_dbl_star_arg) {
2111 n_positional -= 1;
2112 }
2113
2114 if (is_method_call) {
Damien Georgeb9791222014-01-23 00:34:21 +00002115 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 +01002116 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002117 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 +01002118 }
2119
2120 comp->n_arg_keyword = old_n_arg_keyword;
2121 comp->have_star_arg = old_have_star_arg;
2122 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2123}
2124
Damiend99b0522013-12-21 18:17:45 +00002125void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2126 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002127 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002128 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 +01002129 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002130 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2131 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
Damien Georgeb9791222014-01-23 00:34:21 +00002132 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien Georgebbcd49a2014-02-06 20:30:16 +00002133 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
Damien429d7192013-10-04 19:53:11 +01002134 i += 1;
2135 } else {
2136 compile_node(comp, pns->nodes[i]);
2137 }
Damien George35e2a4e2014-02-05 00:51:47 +00002138 comp->func_arg_is_super = false;
Damien429d7192013-10-04 19:53:11 +01002139 }
2140}
2141
Damiend99b0522013-12-21 18:17:45 +00002142void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002143 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002144 EMIT_ARG(binary_op, RT_BINARY_OP_POWER);
Damien429d7192013-10-04 19:53:11 +01002145}
2146
Damiend99b0522013-12-21 18:17:45 +00002147void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002148 // a list of strings
Damien63321742013-12-10 17:41:49 +00002149
2150 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002151 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002152 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002153 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002154 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002155 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2156 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2157 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002158 if (i == 0) {
2159 string_kind = pn_kind;
2160 } else if (pn_kind != string_kind) {
2161 printf("SyntaxError: cannot mix bytes and nonbytes literals\n");
2162 return;
2163 }
Damien George55baff42014-01-21 21:40:13 +00002164 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01002165 }
Damien63321742013-12-10 17:41:49 +00002166
Damien63321742013-12-10 17:41:49 +00002167 // concatenate string/bytes
Damien George55baff42014-01-21 21:40:13 +00002168 byte *q_ptr;
2169 byte *s_dest = qstr_build_start(n_bytes, &q_ptr);
Damien63321742013-12-10 17:41:49 +00002170 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00002171 uint s_len;
2172 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00002173 memcpy(s_dest, s, s_len);
2174 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002175 }
Damien George55baff42014-01-21 21:40:13 +00002176 qstr q = qstr_build_end(q_ptr);
Damien63321742013-12-10 17:41:49 +00002177
Damien Georgeb9791222014-01-23 00:34:21 +00002178 EMIT_ARG(load_const_str, q, string_kind == MP_PARSE_NODE_BYTES);
Damien429d7192013-10-04 19:53:11 +01002179}
2180
2181// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002182void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2183 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2184 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2185 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002186
2187 if (comp->pass == PASS_1) {
2188 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002189 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 +01002190 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002191 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002192 }
2193
2194 // get the scope for this comprehension
2195 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2196
2197 // compile the comprehension
2198 close_over_variables_etc(comp, this_scope, 0, 0);
2199
2200 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2201 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002202 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01002203}
2204
Damiend99b0522013-12-21 18:17:45 +00002205void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2206 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002207 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002208 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2209 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2210 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2211 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2212 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2213 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2214 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002215 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002216 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002217 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002218 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002219 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002220 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002221 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002222 // generator expression
2223 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2224 } else {
2225 // tuple with 2 items
2226 goto tuple_with_2_items;
2227 }
2228 } else {
2229 // tuple with 2 items
2230 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002231 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002232 }
2233 } else {
2234 // parenthesis around a single item, is just that item
2235 compile_node(comp, pns->nodes[0]);
2236 }
2237}
2238
Damiend99b0522013-12-21 18:17:45 +00002239void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2240 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002241 // empty list
Damien Georgeb9791222014-01-23 00:34:21 +00002242 EMIT_ARG(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002243 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2244 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2245 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2246 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2247 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002248 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002249 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002250 compile_node(comp, pns2->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002251 EMIT_ARG(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002252 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002253 // list of many items
2254 compile_node(comp, pns2->nodes[0]);
2255 compile_generic_all_nodes(comp, pns3);
Damien Georgeb9791222014-01-23 00:34:21 +00002256 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
Damiend99b0522013-12-21 18:17:45 +00002257 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002258 // list comprehension
2259 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2260 } else {
2261 // list with 2 items
2262 goto list_with_2_items;
2263 }
2264 } else {
2265 // list with 2 items
2266 list_with_2_items:
2267 compile_node(comp, pns2->nodes[0]);
2268 compile_node(comp, pns2->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00002269 EMIT_ARG(build_list, 2);
Damien429d7192013-10-04 19:53:11 +01002270 }
2271 } else {
2272 // list with 1 item
2273 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002274 EMIT_ARG(build_list, 1);
Damien429d7192013-10-04 19:53:11 +01002275 }
2276}
2277
Damiend99b0522013-12-21 18:17:45 +00002278void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2279 mp_parse_node_t pn = pns->nodes[0];
2280 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002281 // empty dict
Damien Georgeb9791222014-01-23 00:34:21 +00002282 EMIT_ARG(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002283 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2284 pns = (mp_parse_node_struct_t*)pn;
2285 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002286 // dict with one element
Damien Georgeb9791222014-01-23 00:34:21 +00002287 EMIT_ARG(build_map, 1);
Damien429d7192013-10-04 19:53:11 +01002288 compile_node(comp, pn);
2289 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002290 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2291 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2292 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2293 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002294 // dict/set with multiple elements
2295
2296 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002297 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002298 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2299
2300 // first element sets whether it's a dict or set
2301 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002302 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002303 // a dictionary
Damien Georgeb9791222014-01-23 00:34:21 +00002304 EMIT_ARG(build_map, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002305 compile_node(comp, pns->nodes[0]);
2306 EMIT(store_map);
2307 is_dict = true;
2308 } else {
2309 // a set
2310 compile_node(comp, pns->nodes[0]); // 1st value of set
2311 is_dict = false;
2312 }
2313
2314 // process rest of elements
2315 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002316 mp_parse_node_t pn = nodes[i];
2317 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002318 compile_node(comp, pn);
2319 if (is_dict) {
2320 if (!is_key_value) {
2321 printf("SyntaxError?: expecting key:value for dictionary");
2322 return;
2323 }
2324 EMIT(store_map);
2325 } else {
2326 if (is_key_value) {
2327 printf("SyntaxError?: expecting just a value for set");
2328 return;
2329 }
2330 }
2331 }
2332
2333 // if it's a set, build it
2334 if (!is_dict) {
Damien Georgeb9791222014-01-23 00:34:21 +00002335 EMIT_ARG(build_set, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002336 }
Damiend99b0522013-12-21 18:17:45 +00002337 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002338 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002339 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002340 // a dictionary comprehension
2341 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2342 } else {
2343 // a set comprehension
2344 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2345 }
2346 } else {
2347 // shouldn't happen
2348 assert(0);
2349 }
2350 } else {
2351 // set with one element
2352 goto set_with_one_element;
2353 }
2354 } else {
2355 // set with one element
2356 set_with_one_element:
2357 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002358 EMIT_ARG(build_set, 1);
Damien429d7192013-10-04 19:53:11 +01002359 }
2360}
2361
Damiend99b0522013-12-21 18:17:45 +00002362void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgebbcd49a2014-02-06 20:30:16 +00002363 compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
Damien429d7192013-10-04 19:53:11 +01002364}
2365
Damiend99b0522013-12-21 18:17:45 +00002366void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002367 // object who's index we want is on top of stack
2368 compile_node(comp, pns->nodes[0]); // the index
Damien Georgeb9791222014-01-23 00:34:21 +00002369 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +01002370}
2371
Damiend99b0522013-12-21 18:17:45 +00002372void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002373 // object who's attribute we want is on top of stack
Damien Georgeb9791222014-01-23 00:34:21 +00002374 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002375}
2376
Damiend99b0522013-12-21 18:17:45 +00002377void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2378 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2379 mp_parse_node_t pn = pns->nodes[0];
2380 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002381 // [?:]
Damien Georgeb9791222014-01-23 00:34:21 +00002382 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
2383 EMIT_ARG(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002384 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2385 pns = (mp_parse_node_struct_t*)pn;
2386 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
Damien Georgeb9791222014-01-23 00:34:21 +00002387 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002388 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002389 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002390 // [?::]
Damien Georgeb9791222014-01-23 00:34:21 +00002391 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002392 } else {
2393 // [?::x]
2394 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002395 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002396 }
Damiend99b0522013-12-21 18:17:45 +00002397 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002398 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002399 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2400 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2401 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2402 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002403 // [?:x:]
Damien Georgeb9791222014-01-23 00:34:21 +00002404 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002405 } else {
2406 // [?:x:x]
2407 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002408 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002409 }
2410 } else {
2411 // [?:x]
2412 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002413 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002414 }
2415 } else {
2416 // [?:x]
2417 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002418 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002419 }
2420}
2421
Damiend99b0522013-12-21 18:17:45 +00002422void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002423 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002424 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2425 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002426}
2427
Damiend99b0522013-12-21 18:17:45 +00002428void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgeb9791222014-01-23 00:34:21 +00002429 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002430 compile_subscript_3_helper(comp, pns);
2431}
2432
Damiend99b0522013-12-21 18:17:45 +00002433void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002434 // if this is called then we are compiling a dict key:value pair
2435 compile_node(comp, pns->nodes[1]); // value
2436 compile_node(comp, pns->nodes[0]); // key
2437}
2438
Damiend99b0522013-12-21 18:17:45 +00002439void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002440 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002441 // store class object into class name
Damien Georgeb9791222014-01-23 00:34:21 +00002442 EMIT_ARG(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002443}
2444
Damiend99b0522013-12-21 18:17:45 +00002445void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002446 if (comp->have_star_arg) {
2447 printf("SyntaxError?: can't have multiple *x\n");
2448 return;
2449 }
2450 comp->have_star_arg = true;
2451 compile_node(comp, pns->nodes[0]);
2452}
2453
Damiend99b0522013-12-21 18:17:45 +00002454void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002455 if (comp->have_dbl_star_arg) {
2456 printf("SyntaxError?: can't have multiple **x\n");
2457 return;
2458 }
2459 comp->have_dbl_star_arg = true;
2460 compile_node(comp, pns->nodes[0]);
2461}
2462
Damiend99b0522013-12-21 18:17:45 +00002463void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2464 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2465 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2466 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2467 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002468 printf("SyntaxError?: lhs of keyword argument must be an id\n");
2469 return;
2470 }
Damien Georgeb9791222014-01-23 00:34:21 +00002471 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002472 compile_node(comp, pns2->nodes[0]);
2473 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002474 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002475 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2476 } else {
2477 // shouldn't happen
2478 assert(0);
2479 }
2480}
2481
Damiend99b0522013-12-21 18:17:45 +00002482void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002483 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
2484 printf("SyntaxError: 'yield' outside function\n");
2485 return;
2486 }
Damiend99b0522013-12-21 18:17:45 +00002487 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00002488 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002489 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002490 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2491 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002492 compile_node(comp, pns->nodes[0]);
2493 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002494 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002495 EMIT(yield_from);
2496 } else {
2497 compile_node(comp, pns->nodes[0]);
2498 EMIT(yield_value);
2499 }
2500}
2501
Damiend99b0522013-12-21 18:17:45 +00002502typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002503STATIC compile_function_t compile_function[] = {
Damien429d7192013-10-04 19:53:11 +01002504 NULL,
2505#define nc NULL
2506#define c(f) compile_##f
2507#define DEF_RULE(rule, comp, kind, arg...) comp,
2508#include "grammar.h"
2509#undef nc
2510#undef c
2511#undef DEF_RULE
2512};
2513
Damiend99b0522013-12-21 18:17:45 +00002514void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2515 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002516 // pass
Damiend99b0522013-12-21 18:17:45 +00002517 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien George08d07552014-01-29 18:58:52 +00002518 machine_int_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +00002519 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002520 case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
2521 case MP_PARSE_NODE_SMALL_INT: EMIT_ARG(load_const_small_int, arg); break;
2522 case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
2523 case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
2524 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
2525 case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
Damiend99b0522013-12-21 18:17:45 +00002526 case MP_PARSE_NODE_TOKEN:
2527 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002528 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002529 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002530 // do nothing
2531 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002532 EMIT_ARG(load_const_tok, arg);
Damien91d387d2013-10-09 15:09:52 +01002533 }
2534 break;
Damien429d7192013-10-04 19:53:11 +01002535 default: assert(0);
2536 }
2537 } else {
Damiend99b0522013-12-21 18:17:45 +00002538 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien Georgeb9791222014-01-23 00:34:21 +00002539 EMIT_ARG(set_line_number, pns->source_line);
Damiend99b0522013-12-21 18:17:45 +00002540 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002541 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002542 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien Georgecbd2f742014-01-19 11:48:48 +00002543#if MICROPY_DEBUG_PRINTERS
2544 mp_parse_node_print(pn, 0);
2545#endif
Damien429d7192013-10-04 19:53:11 +01002546 assert(0);
2547 } else {
2548 f(comp, pns);
2549 }
2550 }
2551}
2552
Damiend99b0522013-12-21 18:17:45 +00002553void 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 +01002554 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002555 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002556 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2557 if (MP_PARSE_NODE_IS_ID(pn)) {
2558 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002559 if (comp->have_bare_star) {
2560 // comes after a bare star, so doesn't count as a parameter
2561 } else {
2562 comp->scope_cur->num_params += 1;
2563 }
Damienb14de212013-10-06 00:28:28 +01002564 } else {
Damiend99b0522013-12-21 18:17:45 +00002565 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2566 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2567 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2568 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002569 //int node_index = 1; unused
2570 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002571 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002572 // this parameter has an annotation
2573 pn_annotation = pns->nodes[1];
2574 }
2575 //node_index = 2; unused
2576 }
2577 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002578 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002579 // this parameter has a default value
2580 if (comp->have_bare_star) {
2581 comp->scope_cur->num_dict_params += 1;
2582 } else {
2583 comp->scope_cur->num_default_params += 1;
2584 }
2585 }
2586 */
2587 if (comp->have_bare_star) {
2588 // comes after a bare star, so doesn't count as a parameter
2589 } else {
2590 comp->scope_cur->num_params += 1;
2591 }
Damiend99b0522013-12-21 18:17:45 +00002592 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2593 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002594 // bare star
2595 // TODO see http://www.python.org/dev/peps/pep-3102/
2596 comp->have_bare_star = true;
2597 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002598 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002599 // named star
Damien George8725f8f2014-02-15 19:33:11 +00002600 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002601 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2602 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002603 // named star with annotation
Damien George8725f8f2014-02-15 19:33:11 +00002604 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002605 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2606 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002607 pn_annotation = pns->nodes[1];
2608 } else {
2609 // shouldn't happen
2610 assert(0);
2611 }
Damiend99b0522013-12-21 18:17:45 +00002612 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2613 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2614 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002615 // this parameter has an annotation
2616 pn_annotation = pns->nodes[1];
2617 }
Damien George8725f8f2014-02-15 19:33:11 +00002618 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002619 } else {
Damienb14de212013-10-06 00:28:28 +01002620 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002621 assert(0);
2622 }
Damien429d7192013-10-04 19:53:11 +01002623 }
2624
2625 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002626 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002627 // TODO this parameter has an annotation
2628 }
2629 bool added;
2630 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2631 if (!added) {
2632 printf("SyntaxError?: same name used for parameter; %s\n", qstr_str(param_name));
2633 return;
2634 }
2635 id_info->param = true;
2636 id_info->kind = ID_INFO_KIND_LOCAL;
2637 }
2638}
2639
Damiend99b0522013-12-21 18:17:45 +00002640void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002641 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2642}
2643
Damiend99b0522013-12-21 18:17:45 +00002644void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002645 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2646}
2647
Damiend99b0522013-12-21 18:17:45 +00002648void 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 +01002649 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002650 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002651 // no more nested if/for; compile inner expression
2652 compile_node(comp, pn_inner_expr);
2653 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002654 EMIT_ARG(list_append, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002655 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002656 EMIT_ARG(map_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002657 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002658 EMIT_ARG(set_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002659 } else {
2660 EMIT(yield_value);
2661 EMIT(pop_top);
2662 }
Damiend99b0522013-12-21 18:17:45 +00002663 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002664 // if condition
Damiend99b0522013-12-21 18:17:45 +00002665 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002666 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2667 pn_iter = pns_comp_if->nodes[1];
2668 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002669 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002670 // for loop
Damiend99b0522013-12-21 18:17:45 +00002671 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002672 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002673 int l_end2 = comp_next_label(comp);
2674 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002675 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002676 EMIT_ARG(label_assign, l_top2);
2677 EMIT_ARG(for_iter, l_end2);
Damien429d7192013-10-04 19:53:11 +01002678 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2679 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 +00002680 EMIT_ARG(jump, l_top2);
2681 EMIT_ARG(label_assign, l_end2);
Damien429d7192013-10-04 19:53:11 +01002682 EMIT(for_iter_end);
2683 } else {
2684 // shouldn't happen
2685 assert(0);
2686 }
2687}
2688
Damiend99b0522013-12-21 18:17:45 +00002689void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002690 // see http://www.python.org/dev/peps/pep-0257/
2691
2692 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002693 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002694 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002695 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002696 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002697 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2698 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002699 for (int i = 0; i < num_nodes; i++) {
2700 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002701 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 +00002702 // not a newline, so this is the first statement; finish search
2703 break;
2704 }
2705 }
2706 // 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 +00002707 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002708 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002709 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002710 } else {
2711 return;
2712 }
2713
2714 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002715 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2716 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2717 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2718 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2719 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002720 compile_node(comp, pns->nodes[0]); // a doc string
2721 // store doc string
Damien Georgeb9791222014-01-23 00:34:21 +00002722 EMIT_ARG(store_id, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002723 }
2724 }
2725 }
2726}
2727
2728void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2729 comp->pass = pass;
2730 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002731 comp->next_label = 1;
Damien Georgeb9791222014-01-23 00:34:21 +00002732 EMIT_ARG(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002733
2734 if (comp->pass == PASS_1) {
2735 scope->stack_size = 0;
2736 }
2737
Damien5ac1b2e2013-10-18 19:58:12 +01002738#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002739 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002740 scope_print_info(scope);
2741 }
Damien5ac1b2e2013-10-18 19:58:12 +01002742#endif
Damien429d7192013-10-04 19:53:11 +01002743
2744 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002745 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2746 assert(scope->kind == SCOPE_MODULE);
2747 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2748 compile_node(comp, pns->nodes[0]); // compile the expression
2749 EMIT(return_value);
2750 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002751 if (!comp->is_repl) {
2752 check_for_doc_string(comp, scope->pn);
2753 }
Damien429d7192013-10-04 19:53:11 +01002754 compile_node(comp, scope->pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002755 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002756 EMIT(return_value);
2757 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002758 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2759 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2760 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002761
2762 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002763 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002764 if (comp->pass == PASS_1) {
2765 comp->have_bare_star = false;
2766 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2767 }
2768
Paul Sokolovsky2f0b0262014-02-10 02:04:26 +02002769 // pns->nodes[2] is return/whole function annotation
Damien429d7192013-10-04 19:53:11 +01002770
2771 compile_node(comp, pns->nodes[3]); // 3 is function body
2772 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002773 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002774 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002775 EMIT(return_value);
2776 }
2777 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002778 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2779 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2780 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002781
2782 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002783 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002784 if (comp->pass == PASS_1) {
2785 comp->have_bare_star = false;
2786 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2787 }
2788
2789 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2790 EMIT(return_value);
2791 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2792 // a bit of a hack at the moment
2793
Damiend99b0522013-12-21 18:17:45 +00002794 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2795 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2796 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2797 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2798 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002799
Damien George55baff42014-01-21 21:40:13 +00002800 qstr qstr_arg = QSTR_FROM_STR_STATIC(".0");
Damien429d7192013-10-04 19:53:11 +01002801 if (comp->pass == PASS_1) {
2802 bool added;
2803 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2804 assert(added);
2805 id_info->kind = ID_INFO_KIND_LOCAL;
2806 scope->num_params = 1;
2807 }
2808
2809 if (scope->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002810 EMIT_ARG(build_list, 0);
Damien429d7192013-10-04 19:53:11 +01002811 } else if (scope->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002812 EMIT_ARG(build_map, 0);
Damien429d7192013-10-04 19:53:11 +01002813 } else if (scope->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002814 EMIT_ARG(build_set, 0);
Damien429d7192013-10-04 19:53:11 +01002815 }
2816
Damienb05d7072013-10-05 13:37:10 +01002817 int l_end = comp_next_label(comp);
2818 int l_top = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002819 EMIT_ARG(load_id, qstr_arg);
2820 EMIT_ARG(label_assign, l_top);
2821 EMIT_ARG(for_iter, l_end);
Damien429d7192013-10-04 19:53:11 +01002822 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2823 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
Damien Georgeb9791222014-01-23 00:34:21 +00002824 EMIT_ARG(jump, l_top);
2825 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002826 EMIT(for_iter_end);
2827
2828 if (scope->kind == SCOPE_GEN_EXPR) {
Damien Georgeb9791222014-01-23 00:34:21 +00002829 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002830 }
2831 EMIT(return_value);
2832 } else {
2833 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00002834 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2835 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2836 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01002837
2838 if (comp->pass == PASS_1) {
2839 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002840 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01002841 assert(added);
2842 id_info->kind = ID_INFO_KIND_LOCAL;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002843 id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
Damien429d7192013-10-04 19:53:11 +01002844 assert(added);
2845 id_info->kind = ID_INFO_KIND_LOCAL;
2846 id_info->param = true;
2847 scope->num_params = 1; // __locals__ is the parameter
2848 }
2849
Damien Georgeb9791222014-01-23 00:34:21 +00002850 EMIT_ARG(load_id, MP_QSTR___locals__);
Damien429d7192013-10-04 19:53:11 +01002851 EMIT(store_locals);
Damien Georgeb9791222014-01-23 00:34:21 +00002852 EMIT_ARG(load_id, MP_QSTR___name__);
2853 EMIT_ARG(store_id, MP_QSTR___module__);
2854 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
2855 EMIT_ARG(store_id, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01002856
2857 check_for_doc_string(comp, pns->nodes[2]);
2858 compile_node(comp, pns->nodes[2]); // 2 is class body
2859
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002860 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01002861 assert(id != NULL);
2862 if (id->kind == ID_INFO_KIND_LOCAL) {
Damien Georgeb9791222014-01-23 00:34:21 +00002863 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002864 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002865#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00002866 EMIT_ARG(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002867#else
Damien George35e2a4e2014-02-05 00:51:47 +00002868 EMIT_ARG(load_fast, MP_QSTR___class__, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +00002869#endif
Damien429d7192013-10-04 19:53:11 +01002870 }
2871 EMIT(return_value);
2872 }
2873
Damien415eb6f2013-10-05 12:19:06 +01002874 EMIT(end_pass);
Damien826005c2013-10-05 23:17:28 +01002875}
2876
2877void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2878 comp->pass = pass;
2879 comp->scope_cur = scope;
2880 comp->next_label = 1;
2881
2882 if (scope->kind != SCOPE_FUNCTION) {
2883 printf("Error: inline assembler must be a function\n");
2884 return;
2885 }
2886
Damiena2f2f7d2013-10-06 00:14:13 +01002887 if (comp->pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002888 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur);
Damiena2f2f7d2013-10-06 00:14:13 +01002889 }
2890
Damien826005c2013-10-05 23:17:28 +01002891 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002892 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2893 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2894 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002895
Damiend99b0522013-12-21 18:17:45 +00002896 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002897
Damiena2f2f7d2013-10-06 00:14:13 +01002898 // parameters are in pns->nodes[1]
2899 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002900 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002901 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
Damien Georgeb9791222014-01-23 00:34:21 +00002902 scope->num_params = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
Damiena2f2f7d2013-10-06 00:14:13 +01002903 }
2904
Damiend99b0522013-12-21 18:17:45 +00002905 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002906
Damiend99b0522013-12-21 18:17:45 +00002907 mp_parse_node_t pn_body = pns->nodes[3]; // body
2908 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002909 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2910
Damien Georgecbd2f742014-01-19 11:48:48 +00002911 /*
Damien826005c2013-10-05 23:17:28 +01002912 if (comp->pass == PASS_3) {
2913 //printf("----\n");
2914 scope_print_info(scope);
2915 }
Damien Georgecbd2f742014-01-19 11:48:48 +00002916 */
Damien826005c2013-10-05 23:17:28 +01002917
2918 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002919 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2920 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2921 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2922 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2923 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2924 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2925 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2926 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2927 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2928 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2929 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2930 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2931 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002932 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2933
2934 // emit instructions
2935 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00002936 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien826005c2013-10-05 23:17:28 +01002937 printf("SyntaxError: inline assembler 'label' requires 1 argument\n");
2938 return;
2939 }
2940 int lab = comp_next_label(comp);
2941 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002942 EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01002943 }
2944 } else {
2945 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002946 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
Damien826005c2013-10-05 23:17:28 +01002947 }
2948 }
2949 }
2950
2951 if (comp->pass > PASS_1) {
2952 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01002953 }
Damien429d7192013-10-04 19:53:11 +01002954}
2955
2956void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
2957 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00002958 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01002959 scope->num_locals = 0;
2960 for (int i = 0; i < scope->id_info_len; i++) {
2961 id_info_t *id = &scope->id_info[i];
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002962 if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01002963 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
2964 continue;
2965 }
2966 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
2967 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
2968 }
Damien9ecbcff2013-12-11 00:41:43 +00002969 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01002970 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
2971 id->local_num = scope->num_locals;
2972 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002973 }
2974 }
2975
2976 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00002977#if MICROPY_EMIT_CPYTHON
2978 int num_cell = 0;
2979#endif
Damien9ecbcff2013-12-11 00:41:43 +00002980 for (int i = 0; i < scope->id_info_len; i++) {
2981 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00002982#if MICROPY_EMIT_CPYTHON
2983 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00002984 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00002985 id->local_num = num_cell;
2986 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00002987 }
Damien George6baf76e2013-12-30 22:32:17 +00002988#else
2989 // in Micro Python the cells come right after the fast locals
2990 // parameters are not counted here, since they remain at the start
2991 // of the locals, even if they are cell vars
2992 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
2993 id->local_num = scope->num_locals;
2994 scope->num_locals += 1;
2995 }
2996#endif
Damien9ecbcff2013-12-11 00:41:43 +00002997 }
Damien9ecbcff2013-12-11 00:41:43 +00002998
2999 // compute the index of free vars (freevars[idx] in CPython)
3000 // make sure they are in the order of the parent scope
3001 if (scope->parent != NULL) {
3002 int num_free = 0;
3003 for (int i = 0; i < scope->parent->id_info_len; i++) {
3004 id_info_t *id = &scope->parent->id_info[i];
3005 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3006 for (int j = 0; j < scope->id_info_len; j++) {
3007 id_info_t *id2 = &scope->id_info[j];
3008 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00003009 assert(!id2->param); // free vars should not be params
3010#if MICROPY_EMIT_CPYTHON
3011 // in CPython the frees are numbered after the cells
3012 id2->local_num = num_cell + num_free;
3013#else
3014 // in Micro Python the frees come first, before the params
3015 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00003016#endif
3017 num_free += 1;
3018 }
3019 }
3020 }
Damien429d7192013-10-04 19:53:11 +01003021 }
Damien George6baf76e2013-12-30 22:32:17 +00003022#if !MICROPY_EMIT_CPYTHON
3023 // in Micro Python shift all other locals after the free locals
3024 if (num_free > 0) {
3025 for (int i = 0; i < scope->id_info_len; i++) {
3026 id_info_t *id = &scope->id_info[i];
3027 if (id->param || id->kind != ID_INFO_KIND_FREE) {
3028 id->local_num += num_free;
3029 }
3030 }
3031 scope->num_params += num_free; // free vars are counted as params for passing them into the function
3032 scope->num_locals += num_free;
3033 }
3034#endif
Damien429d7192013-10-04 19:53:11 +01003035 }
3036
Damien George8725f8f2014-02-15 19:33:11 +00003037 // compute scope_flags
3038 //scope->scope_flags = 0; since we set some things in parameters
Damien429d7192013-10-04 19:53:11 +01003039 if (scope->kind != SCOPE_MODULE) {
Damien George8725f8f2014-02-15 19:33:11 +00003040 scope->scope_flags |= MP_SCOPE_FLAG_NEWLOCALS;
Damien429d7192013-10-04 19:53:11 +01003041 }
3042 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) {
3043 assert(scope->parent != NULL);
Damien George8725f8f2014-02-15 19:33:11 +00003044 scope->scope_flags |= MP_SCOPE_FLAG_OPTIMISED;
Damien429d7192013-10-04 19:53:11 +01003045
3046 // TODO possibly other ways it can be nested
Damien George08d07552014-01-29 18:58:52 +00003047 // Note that we don't actually use this information at the moment (for CPython compat only)
3048 if ((SCOPE_FUNCTION <= scope->parent->kind && scope->parent->kind <= SCOPE_SET_COMP) || (scope->parent->kind == SCOPE_CLASS && scope->parent->parent->kind == SCOPE_FUNCTION)) {
Damien George8725f8f2014-02-15 19:33:11 +00003049 scope->scope_flags |= MP_SCOPE_FLAG_NESTED;
Damien429d7192013-10-04 19:53:11 +01003050 }
3051 }
3052 int num_free = 0;
3053 for (int i = 0; i < scope->id_info_len; i++) {
3054 id_info_t *id = &scope->id_info[i];
3055 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3056 num_free += 1;
3057 }
3058 }
3059 if (num_free == 0) {
Damien George8725f8f2014-02-15 19:33:11 +00003060 scope->scope_flags |= MP_SCOPE_FLAG_NOFREE;
Damien429d7192013-10-04 19:53:11 +01003061 }
3062}
3063
Damien George08335002014-01-18 23:24:36 +00003064mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003065 compiler_t *comp = m_new(compiler_t, 1);
3066
Damien Georgecbd2f742014-01-19 11:48:48 +00003067 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003068 comp->is_repl = is_repl;
3069 comp->had_error = false;
3070
Damien429d7192013-10-04 19:53:11 +01003071 comp->break_label = 0;
3072 comp->continue_label = 0;
Damien Georgecbddb272014-02-01 20:08:18 +00003073 comp->break_continue_except_level = 0;
3074 comp->cur_except_level = 0;
3075
Damien George35e2a4e2014-02-05 00:51:47 +00003076 comp->func_arg_is_super = false;
3077
Damien429d7192013-10-04 19:53:11 +01003078 comp->scope_head = NULL;
3079 comp->scope_cur = NULL;
3080
Damien826005c2013-10-05 23:17:28 +01003081 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003082 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003083
3084 // set the outer scope
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003085 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003086
Damien826005c2013-10-05 23:17:28 +01003087 // compile pass 1
Damien George35e2a4e2014-02-05 00:51:47 +00003088 comp->emit = emit_pass1_new();
Damien826005c2013-10-05 23:17:28 +01003089 comp->emit_method_table = &emit_pass1_method_table;
3090 comp->emit_inline_asm = NULL;
3091 comp->emit_inline_asm_method_table = NULL;
3092 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003093 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003094 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003095#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003096 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003097 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003098#endif
Damien826005c2013-10-05 23:17:28 +01003099 } else {
3100 compile_scope(comp, s, PASS_1);
3101 }
3102
3103 // update maximim number of labels needed
3104 if (comp->next_label > max_num_labels) {
3105 max_num_labels = comp->next_label;
3106 }
Damien429d7192013-10-04 19:53:11 +01003107 }
3108
Damien826005c2013-10-05 23:17:28 +01003109 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003110 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003111 compile_scope_compute_things(comp, s);
3112 }
3113
Damien826005c2013-10-05 23:17:28 +01003114 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003115 emit_pass1_free(comp->emit);
3116
Damien826005c2013-10-05 23:17:28 +01003117 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003118#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003119 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003120#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003121 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003122#endif
Damien3ef4abb2013-10-12 16:53:13 +01003123#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003124 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003125#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003126#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003127 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003128 if (false) {
3129 // dummy
3130
Damien3ef4abb2013-10-12 16:53:13 +01003131#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003132 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3133 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003134 if (emit_inline_thumb == NULL) {
3135 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3136 }
3137 comp->emit = NULL;
3138 comp->emit_method_table = NULL;
3139 comp->emit_inline_asm = emit_inline_thumb;
3140 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3141 compile_scope_inline_asm(comp, s, PASS_2);
3142 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003143#endif
3144
Damien826005c2013-10-05 23:17:28 +01003145 } else {
Damienc025ebb2013-10-12 14:30:21 +01003146
3147 // choose the emit type
3148
Damien3ef4abb2013-10-12 16:53:13 +01003149#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003150 comp->emit = emit_cpython_new(max_num_labels);
3151 comp->emit_method_table = &emit_cpython_method_table;
3152#else
Damien826005c2013-10-05 23:17:28 +01003153 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003154
3155#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003156 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003157 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003158#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003159 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003160 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003161 }
Damien13ed3a62013-10-08 09:05:10 +01003162 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003163#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003164 if (emit_native == NULL) {
3165 emit_native = emit_native_thumb_new(max_num_labels);
3166 }
3167 comp->emit_method_table = &emit_native_thumb_method_table;
3168#endif
3169 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003170 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003171 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003172#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003173
Damien826005c2013-10-05 23:17:28 +01003174 default:
3175 if (emit_bc == NULL) {
Damien Georgecbd2f742014-01-19 11:48:48 +00003176 emit_bc = emit_bc_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003177 }
3178 comp->emit = emit_bc;
3179 comp->emit_method_table = &emit_bc_method_table;
3180 break;
3181 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003182#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003183
3184 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003185 compile_scope(comp, s, PASS_2);
3186 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003187 }
Damien429d7192013-10-04 19:53:11 +01003188 }
3189
Damien George41d02b62014-01-24 22:42:28 +00003190 // free the emitters
3191#if !MICROPY_EMIT_CPYTHON
3192 if (emit_bc != NULL) {
3193 emit_bc_free(emit_bc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +02003194 }
Damien George41d02b62014-01-24 22:42:28 +00003195#if MICROPY_EMIT_NATIVE
3196 if (emit_native != NULL) {
3197#if MICROPY_EMIT_X64
3198 emit_native_x64_free(emit_native);
3199#elif MICROPY_EMIT_THUMB
3200 emit_native_thumb_free(emit_native);
3201#endif
3202 }
3203#endif
3204#if MICROPY_EMIT_INLINE_THUMB
3205 if (emit_inline_thumb != NULL) {
3206 emit_inline_thumb_free(emit_inline_thumb);
3207 }
3208#endif
3209#endif // !MICROPY_EMIT_CPYTHON
3210
3211 // free the scopes
Paul Sokolovskyfd313582014-01-23 23:05:47 +02003212 uint unique_code_id = module_scope->unique_code_id;
3213 for (scope_t *s = module_scope; s;) {
3214 scope_t *next = s->next;
3215 scope_free(s);
3216 s = next;
3217 }
Damien5ac1b2e2013-10-18 19:58:12 +01003218
Damien George41d02b62014-01-24 22:42:28 +00003219 // free the compiler
3220 bool had_error = comp->had_error;
3221 m_del_obj(compiler_t, comp);
3222
Damien George1fb03172014-01-03 14:22:03 +00003223 if (had_error) {
3224 // TODO return a proper error message
3225 return mp_const_none;
3226 } else {
3227#if MICROPY_EMIT_CPYTHON
3228 // can't create code, so just return true
Damien George41d02b62014-01-24 22:42:28 +00003229 (void)unique_code_id; // to suppress warning that unique_code_id is unused
Damien George1fb03172014-01-03 14:22:03 +00003230 return mp_const_true;
3231#else
3232 // return function that executes the outer module
Paul Sokolovsky90750022014-02-01 15:05:04 +02003233 return rt_make_function_from_id(unique_code_id, MP_OBJ_NULL);
Damien George1fb03172014-01-03 14:22:03 +00003234#endif
3235 }
Damien429d7192013-10-04 19:53:11 +01003236}