blob: bb688d5d8e81eac6d0fab43b562b47d3a7c48c8e [file] [log] [blame]
xbeefe34222014-03-16 00:14:26 -07001#include <stdbool.h>
Damien429d7192013-10-04 19:53:11 +01002#include <stdint.h>
3#include <stdio.h>
4#include <string.h>
5#include <assert.h>
6
7#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00008#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +00009#include "qstr.h"
Damien429d7192013-10-04 19:53:11 +010010#include "lexer.h"
Damien429d7192013-10-04 19:53:11 +010011#include "parse.h"
12#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000013#include "runtime0.h"
Damien429d7192013-10-04 19:53:11 +010014#include "emit.h"
Damien George1fb03172014-01-03 14:22:03 +000015#include "obj.h"
16#include "compile.h"
17#include "runtime.h"
Damien429d7192013-10-04 19:53:11 +010018
19// TODO need to mangle __attr names
20
Damience89a212013-10-15 22:25:17 +010021#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)
22
Damien429d7192013-10-04 19:53:11 +010023typedef enum {
24 PN_none = 0,
Damien George00208ce2014-01-23 00:00:53 +000025#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
Damien429d7192013-10-04 19:53:11 +010026#include "grammar.h"
27#undef DEF_RULE
28 PN_maximum_number_of,
29} pn_kind_t;
30
Damien Georgeb9791222014-01-23 00:34:21 +000031#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
32#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
33#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
34#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 +010035
Damien6cdd3af2013-10-05 18:08:26 +010036#define EMIT_OPT_NONE (0)
37#define EMIT_OPT_BYTE_CODE (1)
38#define EMIT_OPT_NATIVE_PYTHON (2)
Damien7af3d192013-10-07 00:02:49 +010039#define EMIT_OPT_VIPER (3)
40#define EMIT_OPT_ASM_THUMB (4)
Damien6cdd3af2013-10-05 18:08:26 +010041
Damien429d7192013-10-04 19:53:11 +010042typedef struct _compiler_t {
Damien Georgecbd2f742014-01-19 11:48:48 +000043 qstr source_file;
Damien5ac1b2e2013-10-18 19:58:12 +010044 bool is_repl;
Damien429d7192013-10-04 19:53:11 +010045 pass_kind_t pass;
Damien5ac1b2e2013-10-18 19:58:12 +010046 bool had_error; // try to keep compiler clean from nlr
Damien429d7192013-10-04 19:53:11 +010047
Damienb05d7072013-10-05 13:37:10 +010048 int next_label;
Damienb05d7072013-10-05 13:37:10 +010049
Damien429d7192013-10-04 19:53:11 +010050 int break_label;
51 int continue_label;
Damien Georgecbddb272014-02-01 20:08:18 +000052 int break_continue_except_level;
53 int cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
Damien429d7192013-10-04 19:53:11 +010054
55 int n_arg_keyword;
56 bool have_star_arg;
57 bool have_dbl_star_arg;
58 bool have_bare_star;
59 int param_pass;
60 int param_pass_num_dict_params;
61 int param_pass_num_default_params;
62
Damien George35e2a4e2014-02-05 00:51:47 +000063 bool func_arg_is_super; // used to compile special case of super() function call
64
Damien429d7192013-10-04 19:53:11 +010065 scope_t *scope_head;
66 scope_t *scope_cur;
67
Damien6cdd3af2013-10-05 18:08:26 +010068 emit_t *emit; // current emitter
69 const emit_method_table_t *emit_method_table; // current emit method table
Damien826005c2013-10-05 23:17:28 +010070
71 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
72 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 +010073} compiler_t;
74
Damien Georgef41fdd02014-03-03 23:19:11 +000075STATIC void compile_syntax_error(compiler_t *comp, const char *msg) {
76 // TODO store the error message to a variable in compiler_t instead of printing it
77 printf("SyntaxError: %s\n", msg);
78 comp->had_error = true;
79}
80
Damiend99b0522013-12-21 18:17:45 +000081mp_parse_node_t fold_constants(mp_parse_node_t pn) {
82 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
83 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
84 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +010085
86 // fold arguments first
87 for (int i = 0; i < n; i++) {
88 pns->nodes[i] = fold_constants(pns->nodes[i]);
89 }
90
Damiend99b0522013-12-21 18:17:45 +000091 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +010092 case PN_shift_expr:
Damiend99b0522013-12-21 18:17:45 +000093 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +020094 int arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
95 int arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damiend99b0522013-12-21 18:17:45 +000096 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
Damien3ef4abb2013-10-12 16:53:13 +010097#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +010098 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +000099 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
Damien0efb3a12013-10-12 16:16:56 +0100100#endif
Damiend99b0522013-12-21 18:17:45 +0000101 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
102 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien429d7192013-10-04 19:53:11 +0100103 } else {
104 // shouldn't happen
105 assert(0);
106 }
107 }
108 break;
109
110 case PN_arith_expr:
Damien0efb3a12013-10-12 16:16:56 +0100111 // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
Damiend99b0522013-12-21 18:17:45 +0000112 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200113 machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
114 machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damien0efb3a12013-10-12 16:16:56 +0100115 machine_int_t res;
Damiend99b0522013-12-21 18:17:45 +0000116 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100117 res = arg0 + arg1;
Damiend99b0522013-12-21 18:17:45 +0000118 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100119 res = arg0 - arg1;
Damien429d7192013-10-04 19:53:11 +0100120 } else {
121 // shouldn't happen
122 assert(0);
Damien0efb3a12013-10-12 16:16:56 +0100123 res = 0;
124 }
Paul Sokolovskybbf0e2f2014-02-21 02:04:32 +0200125 if (MP_PARSE_FITS_SMALL_INT(res)) {
Damiend99b0522013-12-21 18:17:45 +0000126 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
Damien429d7192013-10-04 19:53:11 +0100127 }
128 }
129 break;
130
131 case PN_term:
Damiend99b0522013-12-21 18:17:45 +0000132 if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200133 int arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
134 int arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damiend99b0522013-12-21 18:17:45 +0000135 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien3ef4abb2013-10-12 16:53:13 +0100136#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100137 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000138 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
Damien0efb3a12013-10-12 16:16:56 +0100139#endif
Damiend99b0522013-12-21 18:17:45 +0000140 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +0100141 ; // pass
Damiend99b0522013-12-21 18:17:45 +0000142 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
Damien0efb3a12013-10-12 16:16:56 +0100143 // XXX implement this properly as Python's % operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000144 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1);
145 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
Damien0efb3a12013-10-12 16:16:56 +0100146 // XXX implement this properly as Python's // operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000147 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1);
Damien429d7192013-10-04 19:53:11 +0100148 } else {
149 // shouldn't happen
150 assert(0);
151 }
152 }
153 break;
154
155 case PN_factor_2:
Damiend99b0522013-12-21 18:17:45 +0000156 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200157 machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +0000158 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
159 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
160 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
161 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
162 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
163 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien429d7192013-10-04 19:53:11 +0100164 } else {
165 // shouldn't happen
166 assert(0);
167 }
168 }
169 break;
170
Damien3ef4abb2013-10-12 16:53:13 +0100171#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +0100172 case PN_power:
Damien0efb3a12013-10-12 16:16:56 +0100173 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000174 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])) {
175 mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
176 if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200177 int power = MP_PARSE_NODE_LEAF_SMALL_INT(pns2->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100178 if (power >= 0) {
179 int ans = 1;
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200180 int base = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100181 for (; power > 0; power--) {
182 ans *= base;
183 }
Damiend99b0522013-12-21 18:17:45 +0000184 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien429d7192013-10-04 19:53:11 +0100185 }
186 }
187 }
188 break;
Damien0efb3a12013-10-12 16:16:56 +0100189#endif
Damien429d7192013-10-04 19:53:11 +0100190 }
191 }
192
193 return pn;
194}
195
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200196STATIC 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 +0000197void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100198
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200199STATIC int comp_next_label(compiler_t *comp) {
Damienb05d7072013-10-05 13:37:10 +0100200 return comp->next_label++;
201}
202
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200203STATIC 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 +0000204 scope_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
Damien429d7192013-10-04 19:53:11 +0100205 scope->parent = comp->scope_cur;
206 scope->next = NULL;
207 if (comp->scope_head == NULL) {
208 comp->scope_head = scope;
209 } else {
210 scope_t *s = comp->scope_head;
211 while (s->next != NULL) {
212 s = s->next;
213 }
214 s->next = scope;
215 }
216 return scope;
217}
218
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200219STATIC int list_len(mp_parse_node_t pn, int pn_kind) {
Damiend99b0522013-12-21 18:17:45 +0000220 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100221 return 0;
Damiend99b0522013-12-21 18:17:45 +0000222 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100223 return 1;
224 } else {
Damiend99b0522013-12-21 18:17:45 +0000225 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
226 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100227 return 1;
228 } else {
Damiend99b0522013-12-21 18:17:45 +0000229 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100230 }
231 }
232}
233
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200234STATIC 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 +0000235 if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
236 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
237 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100238 for (int i = 0; i < num_nodes; i++) {
239 f(comp, pns->nodes[i]);
240 }
Damiend99b0522013-12-21 18:17:45 +0000241 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100242 f(comp, pn);
243 }
244}
245
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200246STATIC int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
Damiend99b0522013-12-21 18:17:45 +0000247 if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100248 *nodes = NULL;
249 return 0;
Damiend99b0522013-12-21 18:17:45 +0000250 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100251 *nodes = pn;
252 return 1;
253 } else {
Damiend99b0522013-12-21 18:17:45 +0000254 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
255 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100256 *nodes = pn;
257 return 1;
258 } else {
259 *nodes = pns->nodes;
Damiend99b0522013-12-21 18:17:45 +0000260 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100261 }
262 }
263}
264
Damiend99b0522013-12-21 18:17:45 +0000265void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100266}
267
Damiend99b0522013-12-21 18:17:45 +0000268void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
269 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100270 for (int i = 0; i < num_nodes; i++) {
271 compile_node(comp, pns->nodes[i]);
272 }
273}
274
Damien3ef4abb2013-10-12 16:53:13 +0100275#if MICROPY_EMIT_CPYTHON
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200276STATIC bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000277 if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100278 return false;
279 }
Damiend99b0522013-12-21 18:17:45 +0000280 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +0100281 return false;
282 }
283 return true;
284}
285
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200286STATIC void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
Damien George55baff42014-01-21 21:40:13 +0000287 uint len;
288 const byte *str = qstr_data(qstr, &len);
Damien02f89412013-12-12 15:13:36 +0000289 bool has_single_quote = false;
290 bool has_double_quote = false;
291 for (int i = 0; i < len; i++) {
292 if (str[i] == '\'') {
293 has_single_quote = true;
294 } else if (str[i] == '"') {
295 has_double_quote = true;
296 }
297 }
298 if (bytes) {
299 vstr_printf(vstr, "b");
300 }
301 bool quote_single = false;
302 if (has_single_quote && !has_double_quote) {
303 vstr_printf(vstr, "\"");
304 } else {
305 quote_single = true;
306 vstr_printf(vstr, "'");
307 }
308 for (int i = 0; i < len; i++) {
309 if (str[i] == '\n') {
310 vstr_printf(vstr, "\\n");
311 } else if (str[i] == '\\') {
312 vstr_printf(vstr, "\\\\");
313 } else if (str[i] == '\'' && quote_single) {
314 vstr_printf(vstr, "\\'");
315 } else {
316 vstr_printf(vstr, "%c", str[i]);
317 }
318 }
319 if (has_single_quote && !has_double_quote) {
320 vstr_printf(vstr, "\"");
321 } else {
322 vstr_printf(vstr, "'");
323 }
324}
325
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200326STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
Damiend99b0522013-12-21 18:17:45 +0000327 assert(MP_PARSE_NODE_IS_LEAF(pn));
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200328 if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
329 vstr_printf(vstr, INT_FMT, MP_PARSE_NODE_LEAF_SMALL_INT(pn));
330 return;
331 }
332
Damiend99b0522013-12-21 18:17:45 +0000333 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
334 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
335 case MP_PARSE_NODE_ID: assert(0);
Damiend99b0522013-12-21 18:17:45 +0000336 case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
337 case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
338 case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
339 case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
340 case MP_PARSE_NODE_TOKEN:
Damien429d7192013-10-04 19:53:11 +0100341 switch (arg) {
Damiend99b0522013-12-21 18:17:45 +0000342 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
343 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
344 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
Damien429d7192013-10-04 19:53:11 +0100345 default: assert(0);
346 }
347 break;
348 default: assert(0);
349 }
350}
351
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200352STATIC 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 +0100353 int n = 0;
354 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000355 n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien429d7192013-10-04 19:53:11 +0100356 }
357 int total = n;
358 bool is_const = true;
Damiend99b0522013-12-21 18:17:45 +0000359 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100360 total += 1;
Damien3a205172013-10-12 15:01:56 +0100361 if (!cpython_c_tuple_is_const(pn)) {
Damien429d7192013-10-04 19:53:11 +0100362 is_const = false;
363 }
364 }
365 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100366 if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien429d7192013-10-04 19:53:11 +0100367 is_const = false;
368 break;
369 }
370 }
371 if (total > 0 && is_const) {
372 bool need_comma = false;
Damien02f89412013-12-12 15:13:36 +0000373 vstr_t *vstr = vstr_new();
374 vstr_printf(vstr, "(");
Damiend99b0522013-12-21 18:17:45 +0000375 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien02f89412013-12-12 15:13:36 +0000376 cpython_c_tuple_emit_const(comp, pn, vstr);
Damien429d7192013-10-04 19:53:11 +0100377 need_comma = true;
378 }
379 for (int i = 0; i < n; i++) {
380 if (need_comma) {
Damien02f89412013-12-12 15:13:36 +0000381 vstr_printf(vstr, ", ");
Damien429d7192013-10-04 19:53:11 +0100382 }
Damien02f89412013-12-12 15:13:36 +0000383 cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien429d7192013-10-04 19:53:11 +0100384 need_comma = true;
385 }
386 if (total == 1) {
Damien02f89412013-12-12 15:13:36 +0000387 vstr_printf(vstr, ",)");
Damien429d7192013-10-04 19:53:11 +0100388 } else {
Damien02f89412013-12-12 15:13:36 +0000389 vstr_printf(vstr, ")");
Damien429d7192013-10-04 19:53:11 +0100390 }
Damien Georgeb9791222014-01-23 00:34:21 +0000391 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +0000392 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +0100393 } else {
Damiend99b0522013-12-21 18:17:45 +0000394 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100395 compile_node(comp, pn);
396 }
397 for (int i = 0; i < n; i++) {
398 compile_node(comp, pns_list->nodes[i]);
399 }
Damien Georgeb9791222014-01-23 00:34:21 +0000400 EMIT_ARG(build_tuple, total);
Damien429d7192013-10-04 19:53:11 +0100401 }
402}
Damien3a205172013-10-12 15:01:56 +0100403#endif
404
405// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
Damiend99b0522013-12-21 18:17:45 +0000406void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3ef4abb2013-10-12 16:53:13 +0100407#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100408 cpython_c_tuple(comp, pn, pns_list);
409#else
410 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000411 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100412 compile_node(comp, pn);
413 total += 1;
414 }
415 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000416 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100417 for (int i = 0; i < n; i++) {
418 compile_node(comp, pns_list->nodes[i]);
419 }
420 total += n;
421 }
Damien Georgeb9791222014-01-23 00:34:21 +0000422 EMIT_ARG(build_tuple, total);
Damien3a205172013-10-12 15:01:56 +0100423#endif
424}
Damien429d7192013-10-04 19:53:11 +0100425
Damiend99b0522013-12-21 18:17:45 +0000426void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100427 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000428 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100429}
430
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200431STATIC bool node_is_const_false(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000432 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200433 // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
Damien429d7192013-10-04 19:53:11 +0100434}
435
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200436STATIC bool node_is_const_true(mp_parse_node_t pn) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200437 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 1);
Damien429d7192013-10-04 19:53:11 +0100438}
439
Damien3ef4abb2013-10-12 16:53:13 +0100440#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100441// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200442STATIC 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 +0100443 if (node_is_const_false(pn)) {
444 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000445 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100446 }
447 return;
448 } else if (node_is_const_true(pn)) {
449 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000450 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100451 }
452 return;
Damiend99b0522013-12-21 18:17:45 +0000453 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
454 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
455 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
456 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien429d7192013-10-04 19:53:11 +0100457 if (jump_if == false) {
Damienb05d7072013-10-05 13:37:10 +0100458 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100459 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100460 cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien429d7192013-10-04 19:53:11 +0100461 }
Damien3a205172013-10-12 15:01:56 +0100462 cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000463 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100464 } else {
465 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100466 cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100467 }
468 }
469 return;
Damiend99b0522013-12-21 18:17:45 +0000470 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien429d7192013-10-04 19:53:11 +0100471 if (jump_if == false) {
472 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100473 cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100474 }
475 } else {
Damienb05d7072013-10-05 13:37:10 +0100476 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100477 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100478 cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien429d7192013-10-04 19:53:11 +0100479 }
Damien3a205172013-10-12 15:01:56 +0100480 cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000481 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100482 }
483 return;
Damiend99b0522013-12-21 18:17:45 +0000484 } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100485 cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien429d7192013-10-04 19:53:11 +0100486 return;
487 }
488 }
489
490 // nothing special, fall back to default compiling for node and jump
491 compile_node(comp, pn);
492 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000493 EMIT_ARG(pop_jump_if_false, label);
Damien429d7192013-10-04 19:53:11 +0100494 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000495 EMIT_ARG(pop_jump_if_true, label);
Damien429d7192013-10-04 19:53:11 +0100496 }
497}
Damien3a205172013-10-12 15:01:56 +0100498#endif
Damien429d7192013-10-04 19:53:11 +0100499
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200500STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien3ef4abb2013-10-12 16:53:13 +0100501#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100502 cpython_c_if_cond(comp, pn, jump_if, label, false);
503#else
504 if (node_is_const_false(pn)) {
505 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000506 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100507 }
508 return;
509 } else if (node_is_const_true(pn)) {
510 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000511 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100512 }
513 return;
Damiend99b0522013-12-21 18:17:45 +0000514 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
515 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
516 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
517 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100518 if (jump_if == false) {
519 int label2 = comp_next_label(comp);
520 for (int i = 0; i < n - 1; i++) {
521 c_if_cond(comp, pns->nodes[i], true, label2);
522 }
523 c_if_cond(comp, pns->nodes[n - 1], false, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000524 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100525 } else {
526 for (int i = 0; i < n; i++) {
527 c_if_cond(comp, pns->nodes[i], true, label);
528 }
529 }
530 return;
Damiend99b0522013-12-21 18:17:45 +0000531 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100532 if (jump_if == false) {
533 for (int i = 0; i < n; i++) {
534 c_if_cond(comp, pns->nodes[i], false, label);
535 }
536 } else {
537 int label2 = comp_next_label(comp);
538 for (int i = 0; i < n - 1; i++) {
539 c_if_cond(comp, pns->nodes[i], false, label2);
540 }
541 c_if_cond(comp, pns->nodes[n - 1], true, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000542 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100543 }
544 return;
Damiend99b0522013-12-21 18:17:45 +0000545 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100546 c_if_cond(comp, pns->nodes[0], !jump_if, label);
547 return;
548 }
549 }
550
551 // nothing special, fall back to default compiling for node and jump
552 compile_node(comp, pn);
553 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000554 EMIT_ARG(pop_jump_if_false, label);
Damien3a205172013-10-12 15:01:56 +0100555 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000556 EMIT_ARG(pop_jump_if_true, label);
Damien3a205172013-10-12 15:01:56 +0100557 }
558#endif
Damien429d7192013-10-04 19:53:11 +0100559}
560
561typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damiend99b0522013-12-21 18:17:45 +0000562void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100563
Damiend99b0522013-12-21 18:17:45 +0000564void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100565 if (assign_kind != ASSIGN_AUG_STORE) {
566 compile_node(comp, pns->nodes[0]);
567 }
568
Damiend99b0522013-12-21 18:17:45 +0000569 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
570 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
571 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
572 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100573 if (assign_kind != ASSIGN_AUG_STORE) {
574 for (int i = 0; i < n - 1; i++) {
575 compile_node(comp, pns1->nodes[i]);
576 }
577 }
Damiend99b0522013-12-21 18:17:45 +0000578 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
579 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100580 }
Damiend99b0522013-12-21 18:17:45 +0000581 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000582 compile_syntax_error(comp, "can't assign to function call");
Damien429d7192013-10-04 19:53:11 +0100583 return;
Damiend99b0522013-12-21 18:17:45 +0000584 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100585 if (assign_kind == ASSIGN_AUG_STORE) {
586 EMIT(rot_three);
587 EMIT(store_subscr);
588 } else {
589 compile_node(comp, pns1->nodes[0]);
590 if (assign_kind == ASSIGN_AUG_LOAD) {
591 EMIT(dup_top_two);
Damien Georgeb9791222014-01-23 00:34:21 +0000592 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +0100593 } else {
594 EMIT(store_subscr);
595 }
596 }
Damiend99b0522013-12-21 18:17:45 +0000597 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
598 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100599 if (assign_kind == ASSIGN_AUG_LOAD) {
600 EMIT(dup_top);
Damien Georgeb9791222014-01-23 00:34:21 +0000601 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100602 } else {
603 if (assign_kind == ASSIGN_AUG_STORE) {
604 EMIT(rot_two);
605 }
Damien Georgeb9791222014-01-23 00:34:21 +0000606 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100607 }
608 } else {
609 // shouldn't happen
610 assert(0);
611 }
612 } else {
613 // shouldn't happen
614 assert(0);
615 }
616
Damiend99b0522013-12-21 18:17:45 +0000617 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100618 // SyntaxError, cannot assign
619 assert(0);
620 }
621}
622
Damiend99b0522013-12-21 18:17:45 +0000623void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
Damien429d7192013-10-04 19:53:11 +0100624 assert(n >= 0);
625 int have_star_index = -1;
626 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000627 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) {
Damien429d7192013-10-04 19:53:11 +0100628 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000629 EMIT_ARG(unpack_ex, i, n - i - 1);
Damien429d7192013-10-04 19:53:11 +0100630 have_star_index = i;
631 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000632 compile_syntax_error(comp, "two starred expressions in assignment");
Damien429d7192013-10-04 19:53:11 +0100633 return;
634 }
635 }
636 }
637 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000638 EMIT_ARG(unpack_sequence, n);
Damien429d7192013-10-04 19:53:11 +0100639 }
640 for (int i = 0; i < n; i++) {
641 if (i == have_star_index) {
Damiend99b0522013-12-21 18:17:45 +0000642 c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100643 } else {
644 c_assign(comp, nodes[i], ASSIGN_STORE);
645 }
646 }
647}
648
649// assigns top of stack to pn
Damiend99b0522013-12-21 18:17:45 +0000650void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100651 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +0000652 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100653 assert(0);
Damiend99b0522013-12-21 18:17:45 +0000654 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
655 if (MP_PARSE_NODE_IS_ID(pn)) {
656 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100657 switch (assign_kind) {
658 case ASSIGN_STORE:
659 case ASSIGN_AUG_STORE:
Damien Georgeb9791222014-01-23 00:34:21 +0000660 EMIT_ARG(store_id, arg);
Damien429d7192013-10-04 19:53:11 +0100661 break;
662 case ASSIGN_AUG_LOAD:
Damien Georgeb9791222014-01-23 00:34:21 +0000663 EMIT_ARG(load_id, arg);
Damien429d7192013-10-04 19:53:11 +0100664 break;
665 }
666 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000667 compile_syntax_error(comp, "can't assign to literal");
Damien429d7192013-10-04 19:53:11 +0100668 return;
669 }
670 } else {
Damiend99b0522013-12-21 18:17:45 +0000671 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
672 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +0100673 case PN_power:
674 // lhs is an index or attribute
675 c_assign_power(comp, pns, assign_kind);
676 break;
677
678 case PN_testlist_star_expr:
679 case PN_exprlist:
680 // lhs is a tuple
681 if (assign_kind != ASSIGN_STORE) {
682 goto bad_aug;
683 }
Damiend99b0522013-12-21 18:17:45 +0000684 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100685 break;
686
687 case PN_atom_paren:
688 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000689 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100690 // empty tuple
Damien Georgef41fdd02014-03-03 23:19:11 +0000691 compile_syntax_error(comp, "can't assign to ()");
Damien429d7192013-10-04 19:53:11 +0100692 return;
Damiend99b0522013-12-21 18:17:45 +0000693 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
694 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100695 goto testlist_comp;
696 } else {
697 // parenthesis around 1 item, is just that item
698 pn = pns->nodes[0];
699 goto tail_recursion;
700 }
701 break;
702
703 case PN_atom_bracket:
704 // lhs is something in brackets
705 if (assign_kind != ASSIGN_STORE) {
706 goto bad_aug;
707 }
Damiend99b0522013-12-21 18:17:45 +0000708 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100709 // empty list, assignment allowed
710 c_assign_tuple(comp, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000711 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
712 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100713 goto testlist_comp;
714 } else {
715 // brackets around 1 item
716 c_assign_tuple(comp, 1, &pns->nodes[0]);
717 }
718 break;
719
720 default:
Damiend99b0522013-12-21 18:17:45 +0000721 printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien429d7192013-10-04 19:53:11 +0100722 assert(0);
723 }
724 return;
725
726 testlist_comp:
727 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000728 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
729 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
730 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100731 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000732 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100733 c_assign_tuple(comp, 1, &pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000734 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100735 // sequence of many items
736 // TODO call c_assign_tuple instead
Damiend99b0522013-12-21 18:17:45 +0000737 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
Damien Georgeb9791222014-01-23 00:34:21 +0000738 EMIT_ARG(unpack_sequence, 1 + n);
Damien429d7192013-10-04 19:53:11 +0100739 c_assign(comp, pns->nodes[0], ASSIGN_STORE);
740 for (int i = 0; i < n; i++) {
741 c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
742 }
Damiend99b0522013-12-21 18:17:45 +0000743 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +0100744 // TODO not implemented
745 assert(0);
746 } else {
747 // sequence with 2 items
748 goto sequence_with_2_items;
749 }
750 } else {
751 // sequence with 2 items
752 sequence_with_2_items:
753 c_assign_tuple(comp, 2, pns->nodes);
754 }
755 return;
756 }
757 return;
758
759 bad_aug:
Damien Georgef41fdd02014-03-03 23:19:11 +0000760 compile_syntax_error(comp, "illegal expression for augmented assignment");
Damien429d7192013-10-04 19:53:11 +0100761}
762
763// stuff for lambda and comprehensions and generators
764void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
765 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000766 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100767 int nfree = 0;
768 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000769 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
770 id_info_t *id = &comp->scope_cur->id_info[i];
771 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
772 for (int j = 0; j < this_scope->id_info_len; j++) {
773 id_info_t *id2 = &this_scope->id_info[j];
774 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +0000775#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +0000776 EMIT_ARG(load_closure, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000777#else
778 // in Micro Python we load closures using LOAD_FAST
Damien Georgeb9791222014-01-23 00:34:21 +0000779 EMIT_ARG(load_fast, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000780#endif
Damien318aec62013-12-10 18:28:17 +0000781 nfree += 1;
782 }
783 }
Damien429d7192013-10-04 19:53:11 +0100784 }
785 }
786 }
787 if (nfree > 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000788 EMIT_ARG(build_tuple, nfree);
Damien429d7192013-10-04 19:53:11 +0100789 }
790
791 // make the function/closure
792 if (nfree == 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000793 EMIT_ARG(make_function, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100794 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000795 EMIT_ARG(make_closure, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100796 }
797}
798
Damiend99b0522013-12-21 18:17:45 +0000799void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000800 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
Damiend99b0522013-12-21 18:17:45 +0000801 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
802 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100803 // bare star
804 comp->have_bare_star = true;
805 }
Damien Georgef41fdd02014-03-03 23:19:11 +0000806
807 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)) {
808 // TODO do we need to do anything with this?
809
810 } else {
811 mp_parse_node_t pn_id;
812 mp_parse_node_t pn_colon;
813 mp_parse_node_t pn_equal;
814 if (MP_PARSE_NODE_IS_ID(pn)) {
815 // this parameter is just an id
816
817 pn_id = pn;
818 pn_colon = MP_PARSE_NODE_NULL;
819 pn_equal = MP_PARSE_NODE_NULL;
820
821 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
822 // this parameter has a colon and/or equal specifier
823
824 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
825 pn_id = pns->nodes[0];
826 pn_colon = pns->nodes[1];
827 pn_equal = pns->nodes[2];
828
829 } else {
830 assert(0);
831 return;
832 }
833
834 if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
835 // this parameter does not have a default value
836
837 // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
838 if (!comp->have_bare_star && comp->param_pass_num_default_params != 0) {
839 compile_syntax_error(comp, "non-default argument follows default argument");
840 return;
841 }
842
843 } else {
844 // this parameter has a default value
845 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
846
847 if (comp->have_bare_star) {
848 comp->param_pass_num_dict_params += 1;
849 if (comp->param_pass == 1) {
850 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pn_id));
851 compile_node(comp, pn_equal);
852 }
853 } else {
854 comp->param_pass_num_default_params += 1;
855 if (comp->param_pass == 2) {
856 compile_node(comp, pn_equal);
857 }
858 }
859 }
860
861 // TODO pn_colon not implemented
862 (void)pn_colon;
Damien429d7192013-10-04 19:53:11 +0100863 }
864}
865
866// leaves function object on stack
867// returns function name
Damiend99b0522013-12-21 18:17:45 +0000868qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100869 if (comp->pass == PASS_1) {
870 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000871 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100872 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000873 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100874 }
875
876 // save variables (probably don't need to do this, since we can't have nested definitions..?)
877 bool old_have_bare_star = comp->have_bare_star;
878 int old_param_pass = comp->param_pass;
879 int old_param_pass_num_dict_params = comp->param_pass_num_dict_params;
880 int old_param_pass_num_default_params = comp->param_pass_num_default_params;
881
882 // compile default parameters
Damien Georgef41fdd02014-03-03 23:19:11 +0000883
884 // pass 1 does any default parameters after bare star
Damien429d7192013-10-04 19:53:11 +0100885 comp->have_bare_star = false;
Damien Georgef41fdd02014-03-03 23:19:11 +0000886 comp->param_pass = 1;
Damien429d7192013-10-04 19:53:11 +0100887 comp->param_pass_num_dict_params = 0;
888 comp->param_pass_num_default_params = 0;
889 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
Damien Georgef41fdd02014-03-03 23:19:11 +0000890
891 if (comp->had_error) {
892 return MP_QSTR_NULL;
893 }
894
895 // pass 2 does any default parameters before bare star
Damien429d7192013-10-04 19:53:11 +0100896 comp->have_bare_star = false;
Damien Georgef41fdd02014-03-03 23:19:11 +0000897 comp->param_pass = 2;
Damien429d7192013-10-04 19:53:11 +0100898 comp->param_pass_num_dict_params = 0;
899 comp->param_pass_num_default_params = 0;
900 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
901
902 // get the scope for this function
903 scope_t *fscope = (scope_t*)pns->nodes[4];
904
905 // make the function
906 close_over_variables_etc(comp, fscope, comp->param_pass_num_dict_params, comp->param_pass_num_default_params);
907
908 // restore variables
909 comp->have_bare_star = old_have_bare_star;
910 comp->param_pass = old_param_pass;
911 comp->param_pass_num_dict_params = old_param_pass_num_dict_params;
912 comp->param_pass_num_default_params = old_param_pass_num_default_params;
913
914 // return its name (the 'f' in "def f(...):")
915 return fscope->simple_name;
916}
917
918// leaves class object on stack
919// returns class name
Damiend99b0522013-12-21 18:17:45 +0000920qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100921 if (comp->pass == PASS_1) {
922 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000923 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100924 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000925 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100926 }
927
928 EMIT(load_build_class);
929
930 // scope for this class
931 scope_t *cscope = (scope_t*)pns->nodes[3];
932
933 // compile the class
934 close_over_variables_etc(comp, cscope, 0, 0);
935
936 // get its name
Damien Georgeb9791222014-01-23 00:34:21 +0000937 EMIT_ARG(load_const_id, cscope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100938
939 // nodes[1] has parent classes, if any
Damien Georgebbcd49a2014-02-06 20:30:16 +0000940 comp->func_arg_is_super = false;
941 compile_trailer_paren_helper(comp, pns->nodes[1], false, 2);
Damien429d7192013-10-04 19:53:11 +0100942
943 // return its name (the 'C' in class C(...):")
944 return cscope->simple_name;
945}
946
Damien6cdd3af2013-10-05 18:08:26 +0100947// returns true if it was a built-in decorator (even if the built-in had an error)
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200948STATIC 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 +0000949 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100950 return false;
951 }
952
953 if (name_len != 2) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000954 compile_syntax_error(comp, "invalid micropython decorator");
Damien6cdd3af2013-10-05 18:08:26 +0100955 return true;
956 }
957
Damiend99b0522013-12-21 18:17:45 +0000958 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000959 if (attr == MP_QSTR_byte_code) {
Damien5ac1b2e2013-10-18 19:58:12 +0100960 *emit_options = EMIT_OPT_BYTE_CODE;
Damience89a212013-10-15 22:25:17 +0100961#if MICROPY_EMIT_NATIVE
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000962 } else if (attr == MP_QSTR_native) {
Damien6cdd3af2013-10-05 18:08:26 +0100963 *emit_options = EMIT_OPT_NATIVE_PYTHON;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000964 } else if (attr == MP_QSTR_viper) {
Damien7af3d192013-10-07 00:02:49 +0100965 *emit_options = EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100966#endif
Damien3ef4abb2013-10-12 16:53:13 +0100967#if MICROPY_EMIT_INLINE_THUMB
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000968 } else if (attr == MP_QSTR_asm_thumb) {
Damien5bfb7592013-10-05 18:41:24 +0100969 *emit_options = EMIT_OPT_ASM_THUMB;
Damienc025ebb2013-10-12 14:30:21 +0100970#endif
Damien6cdd3af2013-10-05 18:08:26 +0100971 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000972 compile_syntax_error(comp, "invalid micropython decorator");
Damien6cdd3af2013-10-05 18:08:26 +0100973 }
974
975 return true;
976}
977
Damiend99b0522013-12-21 18:17:45 +0000978void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100979 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000980 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +0100981 int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
982
Damien6cdd3af2013-10-05 18:08:26 +0100983 // inherit emit options for this function/class definition
984 uint emit_options = comp->scope_cur->emit_options;
985
986 // compile each decorator
987 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100988 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000989 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
990 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100991
992 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +0000993 mp_parse_node_t *name_nodes;
Damien6cdd3af2013-10-05 18:08:26 +0100994 int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
995
996 // check for built-in decorators
997 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
998 // this was a built-in
999 num_built_in_decorators += 1;
1000
1001 } else {
1002 // not a built-in, compile normally
1003
1004 // compile the decorator function
1005 compile_node(comp, name_nodes[0]);
1006 for (int i = 1; i < name_len; i++) {
Damiend99b0522013-12-21 18:17:45 +00001007 assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be
Damien Georgeb9791222014-01-23 00:34:21 +00001008 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i]));
Damien6cdd3af2013-10-05 18:08:26 +01001009 }
1010
1011 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +00001012 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +01001013 // call the decorator function with the arguments in nodes[1]
Damien George35e2a4e2014-02-05 00:51:47 +00001014 comp->func_arg_is_super = false;
Damien6cdd3af2013-10-05 18:08:26 +01001015 compile_node(comp, pns_decorator->nodes[1]);
1016 }
Damien429d7192013-10-04 19:53:11 +01001017 }
1018 }
1019
1020 // compile the body (funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +00001021 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001022 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +00001023 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +01001024 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Damiend99b0522013-12-21 18:17:45 +00001025 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) {
Damien6cdd3af2013-10-05 18:08:26 +01001026 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +01001027 } else {
1028 // shouldn't happen
1029 assert(0);
1030 }
1031
1032 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +01001033 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001034 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001035 }
1036
1037 // store func/class object into name
Damien Georgeb9791222014-01-23 00:34:21 +00001038 EMIT_ARG(store_id, body_name);
Damien429d7192013-10-04 19:53:11 +01001039}
1040
Damiend99b0522013-12-21 18:17:45 +00001041void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01001042 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01001043 // store function object into function name
Damien Georgeb9791222014-01-23 00:34:21 +00001044 EMIT_ARG(store_id, fname);
Damien429d7192013-10-04 19:53:11 +01001045}
1046
Damiend99b0522013-12-21 18:17:45 +00001047void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
1048 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001049 EMIT_ARG(delete_id, MP_PARSE_NODE_LEAF_ARG(pn));
Damiend99b0522013-12-21 18:17:45 +00001050 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
1051 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001052
1053 compile_node(comp, pns->nodes[0]); // base of the power node
1054
Damiend99b0522013-12-21 18:17:45 +00001055 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1056 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1057 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
1058 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001059 for (int i = 0; i < n - 1; i++) {
1060 compile_node(comp, pns1->nodes[i]);
1061 }
Damiend99b0522013-12-21 18:17:45 +00001062 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
1063 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +01001064 }
Damiend99b0522013-12-21 18:17:45 +00001065 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +01001066 // SyntaxError: can't delete a function call
1067 assert(0);
Damiend99b0522013-12-21 18:17:45 +00001068 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +01001069 compile_node(comp, pns1->nodes[0]);
1070 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +00001071 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
1072 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien Georgeb9791222014-01-23 00:34:21 +00001073 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001074 } else {
1075 // shouldn't happen
1076 assert(0);
1077 }
1078 } else {
1079 // shouldn't happen
1080 assert(0);
1081 }
1082
Damiend99b0522013-12-21 18:17:45 +00001083 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001084 // SyntaxError, cannot delete
1085 assert(0);
1086 }
Damiend99b0522013-12-21 18:17:45 +00001087 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
1088 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
1089 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) {
1090 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001091 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
1092
Damiend99b0522013-12-21 18:17:45 +00001093 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1094 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1095 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01001096 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00001097 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001098 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00001099 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01001100 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +00001101 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001102 c_del_stmt(comp, pns->nodes[0]);
1103 for (int i = 0; i < n; i++) {
1104 c_del_stmt(comp, pns1->nodes[i]);
1105 }
Damiend99b0522013-12-21 18:17:45 +00001106 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01001107 // TODO not implemented; can't del comprehension?
1108 assert(0);
1109 } else {
1110 // sequence with 2 items
1111 goto sequence_with_2_items;
1112 }
1113 } else {
1114 // sequence with 2 items
1115 sequence_with_2_items:
1116 c_del_stmt(comp, pns->nodes[0]);
1117 c_del_stmt(comp, pns->nodes[1]);
1118 }
1119 } else {
1120 // tuple with 1 element
1121 c_del_stmt(comp, pn);
1122 }
1123 } else {
1124 // not implemented
1125 assert(0);
1126 }
1127}
1128
Damiend99b0522013-12-21 18:17:45 +00001129void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001130 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
1131}
1132
Damiend99b0522013-12-21 18:17:45 +00001133void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001134 if (comp->break_label == 0) {
1135 printf("ERROR: cannot break from here\n");
1136 }
Damien Georgecbddb272014-02-01 20:08:18 +00001137 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001138}
1139
Damiend99b0522013-12-21 18:17:45 +00001140void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001141 if (comp->continue_label == 0) {
1142 printf("ERROR: cannot continue from here\n");
1143 }
Damien Georgecbddb272014-02-01 20:08:18 +00001144 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001145}
1146
Damiend99b0522013-12-21 18:17:45 +00001147void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +01001148 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
Damien Georgef41fdd02014-03-03 23:19:11 +00001149 compile_syntax_error(comp, "'return' outside function");
Damien5ac1b2e2013-10-18 19:58:12 +01001150 return;
1151 }
Damiend99b0522013-12-21 18:17:45 +00001152 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001153 // no argument to 'return', so return None
Damien Georgeb9791222014-01-23 00:34:21 +00001154 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damiend99b0522013-12-21 18:17:45 +00001155 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +01001156 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +00001157 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
1158 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 +01001159
Damienb05d7072013-10-05 13:37:10 +01001160 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001161 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1162 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
1163 EMIT(return_value);
Damien Georgeb9791222014-01-23 00:34:21 +00001164 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001165 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1166 } else {
1167 compile_node(comp, pns->nodes[0]);
1168 }
1169 EMIT(return_value);
1170}
1171
Damiend99b0522013-12-21 18:17:45 +00001172void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001173 compile_node(comp, pns->nodes[0]);
1174 EMIT(pop_top);
1175}
1176
Damiend99b0522013-12-21 18:17:45 +00001177void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1178 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001179 // raise
Damien Georgeb9791222014-01-23 00:34:21 +00001180 EMIT_ARG(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001181 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001182 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001183 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001184 compile_node(comp, pns->nodes[0]);
1185 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001186 EMIT_ARG(raise_varargs, 2);
Damien429d7192013-10-04 19:53:11 +01001187 } else {
1188 // raise x
1189 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001190 EMIT_ARG(raise_varargs, 1);
Damien429d7192013-10-04 19:53:11 +01001191 }
1192}
1193
1194// q1 holds the base, q2 the full name
1195// eg a -> q1=q2=a
1196// a.b.c -> q1=a, q2=a.b.c
Damiend99b0522013-12-21 18:17:45 +00001197void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
Damien429d7192013-10-04 19:53:11 +01001198 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001199 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1200 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001201 // a name of the form x as y; unwrap it
Damiend99b0522013-12-21 18:17:45 +00001202 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001203 pn = pns->nodes[0];
1204 is_as = true;
1205 }
Damiend99b0522013-12-21 18:17:45 +00001206 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001207 // just a simple name
Damiend99b0522013-12-21 18:17:45 +00001208 *q2 = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001209 if (!is_as) {
1210 *q1 = *q2;
1211 }
Damien Georgeb9791222014-01-23 00:34:21 +00001212 EMIT_ARG(import_name, *q2);
Damiend99b0522013-12-21 18:17:45 +00001213 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
1214 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
1215 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) {
Damien429d7192013-10-04 19:53:11 +01001216 // a name of the form a.b.c
1217 if (!is_as) {
Damiend99b0522013-12-21 18:17:45 +00001218 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001219 }
Damiend99b0522013-12-21 18:17:45 +00001220 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001221 int len = n - 1;
1222 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00001223 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001224 }
Damien George55baff42014-01-21 21:40:13 +00001225 byte *q_ptr;
1226 byte *str_dest = qstr_build_start(len, &q_ptr);
Damien429d7192013-10-04 19:53:11 +01001227 for (int i = 0; i < n; i++) {
1228 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001229 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001230 }
Damien George55baff42014-01-21 21:40:13 +00001231 uint str_src_len;
1232 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00001233 memcpy(str_dest, str_src, str_src_len);
1234 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001235 }
Damien George55baff42014-01-21 21:40:13 +00001236 *q2 = qstr_build_end(q_ptr);
Damien Georgeb9791222014-01-23 00:34:21 +00001237 EMIT_ARG(import_name, *q2);
Damien429d7192013-10-04 19:53:11 +01001238 if (is_as) {
1239 for (int i = 1; i < n; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001240 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001241 }
1242 }
1243 } else {
1244 // TODO not implemented
Paul Sokolovskya1aba362014-02-20 13:21:31 +02001245 // This covers relative imports starting with dot(s) like "from .foo import"
Damien429d7192013-10-04 19:53:11 +01001246 assert(0);
1247 }
1248 } else {
1249 // TODO not implemented
Paul Sokolovskya1aba362014-02-20 13:21:31 +02001250 // This covers relative imports with dots only like "from .. import"
Damien429d7192013-10-04 19:53:11 +01001251 assert(0);
1252 }
1253}
1254
Damiend99b0522013-12-21 18:17:45 +00001255void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgeb9791222014-01-23 00:34:21 +00001256 EMIT_ARG(load_const_small_int, 0); // ??
1257 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001258 qstr q1, q2;
1259 do_import_name(comp, pn, &q1, &q2);
Damien Georgeb9791222014-01-23 00:34:21 +00001260 EMIT_ARG(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001261}
1262
Damiend99b0522013-12-21 18:17:45 +00001263void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001264 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1265}
1266
Damiend99b0522013-12-21 18:17:45 +00001267void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1268 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001269 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001270
1271 // build the "fromlist" tuple
1272#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001273 EMIT_ARG(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001274#else
Damien Georgeb9791222014-01-23 00:34:21 +00001275 EMIT_ARG(load_const_str, QSTR_FROM_STR_STATIC("*"), false);
1276 EMIT_ARG(build_tuple, 1);
Damiendb4c3612013-12-10 17:27:24 +00001277#endif
1278
1279 // do the import
Damien429d7192013-10-04 19:53:11 +01001280 qstr dummy_q, id1;
1281 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1282 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001283
Damien429d7192013-10-04 19:53:11 +01001284 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001285 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001286
1287 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001288 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001289 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001290#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001291 {
1292 vstr_t *vstr = vstr_new();
1293 vstr_printf(vstr, "(");
1294 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001295 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1296 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1297 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001298 if (i > 0) {
1299 vstr_printf(vstr, ", ");
1300 }
1301 vstr_printf(vstr, "'");
Damien George55baff42014-01-21 21:40:13 +00001302 uint len;
1303 const byte *str = qstr_data(id2, &len);
1304 vstr_add_strn(vstr, (const char*)str, len);
Damien02f89412013-12-12 15:13:36 +00001305 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001306 }
Damien02f89412013-12-12 15:13:36 +00001307 if (n == 1) {
1308 vstr_printf(vstr, ",");
1309 }
1310 vstr_printf(vstr, ")");
Damien Georgeb9791222014-01-23 00:34:21 +00001311 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001312 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001313 }
Damiendb4c3612013-12-10 17:27:24 +00001314#else
1315 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001316 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1317 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1318 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001319 EMIT_ARG(load_const_str, id2, false);
Damiendb4c3612013-12-10 17:27:24 +00001320 }
Damien Georgeb9791222014-01-23 00:34:21 +00001321 EMIT_ARG(build_tuple, n);
Damiendb4c3612013-12-10 17:27:24 +00001322#endif
1323
1324 // do the import
Damien429d7192013-10-04 19:53:11 +01001325 qstr dummy_q, id1;
1326 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1327 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001328 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1329 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1330 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001331 EMIT_ARG(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001332 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001333 EMIT_ARG(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001334 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001335 EMIT_ARG(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001336 }
1337 }
1338 EMIT(pop_top);
1339 }
1340}
1341
Damiend99b0522013-12-21 18:17:45 +00001342void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001343 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001344 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1345 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001346 } else {
Damiend99b0522013-12-21 18:17:45 +00001347 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1348 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001349 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001350 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001351 }
Damien429d7192013-10-04 19:53:11 +01001352 }
1353 }
1354}
1355
Damiend99b0522013-12-21 18:17:45 +00001356void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001357 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001358 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1359 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001360 } else {
Damiend99b0522013-12-21 18:17:45 +00001361 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1362 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001363 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001364 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001365 }
Damien429d7192013-10-04 19:53:11 +01001366 }
1367 }
1368}
1369
Damiend99b0522013-12-21 18:17:45 +00001370void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001371 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001372 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien Georgeb9791222014-01-23 00:34:21 +00001373 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 +00001374 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001375 // assertion message
1376 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001377 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001378 }
Damien Georgeb9791222014-01-23 00:34:21 +00001379 EMIT_ARG(raise_varargs, 1);
1380 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001381}
1382
Damiend99b0522013-12-21 18:17:45 +00001383void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001384 // TODO proper and/or short circuiting
1385
Damienb05d7072013-10-05 13:37:10 +01001386 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001387
Damienb05d7072013-10-05 13:37:10 +01001388 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001389 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1390
1391 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001392 //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 +01001393 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001394 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001395 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001396 }
1397 //}
Damien Georgeb9791222014-01-23 00:34:21 +00001398 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001399
Damiend99b0522013-12-21 18:17:45 +00001400 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001401 // compile elif blocks
1402
Damiend99b0522013-12-21 18:17:45 +00001403 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001404
Damiend99b0522013-12-21 18:17:45 +00001405 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001406 // multiple elif blocks
1407
Damiend99b0522013-12-21 18:17:45 +00001408 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001409 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001410 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
Damienb05d7072013-10-05 13:37:10 +01001411 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001412 c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition
1413
1414 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001415 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001416 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001417 }
Damien Georgeb9791222014-01-23 00:34:21 +00001418 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001419 }
1420
1421 } else {
1422 // a single elif block
1423
Damienb05d7072013-10-05 13:37:10 +01001424 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001425 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1426
1427 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001428 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001429 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001430 }
Damien Georgeb9791222014-01-23 00:34:21 +00001431 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001432 }
1433 }
1434
1435 // compile else block
1436 compile_node(comp, pns->nodes[3]); // can be null
1437
Damien Georgeb9791222014-01-23 00:34:21 +00001438 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001439}
1440
Damien Georgecbddb272014-02-01 20:08:18 +00001441#define START_BREAK_CONTINUE_BLOCK \
1442 int old_break_label = comp->break_label; \
1443 int old_continue_label = comp->continue_label; \
1444 int break_label = comp_next_label(comp); \
1445 int continue_label = comp_next_label(comp); \
1446 comp->break_label = break_label; \
1447 comp->continue_label = continue_label; \
1448 comp->break_continue_except_level = comp->cur_except_level;
1449
1450#define END_BREAK_CONTINUE_BLOCK \
1451 comp->break_label = old_break_label; \
1452 comp->continue_label = old_continue_label; \
1453 comp->break_continue_except_level = comp->cur_except_level;
1454
Damiend99b0522013-12-21 18:17:45 +00001455void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgecbddb272014-02-01 20:08:18 +00001456 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001457
Damience89a212013-10-15 22:25:17 +01001458 // compared to CPython, we have an optimised version of while loops
1459#if MICROPY_EMIT_CPYTHON
1460 int done_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001461 EMIT_ARG(setup_loop, break_label);
1462 EMIT_ARG(label_assign, continue_label);
Damien429d7192013-10-04 19:53:11 +01001463 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1464 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001465 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001466 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001467 }
Damien Georgeb9791222014-01-23 00:34:21 +00001468 EMIT_ARG(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001469 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1470 // this is a small hack to agree with CPython
1471 if (!node_is_const_true(pns->nodes[0])) {
1472 EMIT(pop_block);
1473 }
Damience89a212013-10-15 22:25:17 +01001474#else
1475 int top_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001476 EMIT_ARG(jump, continue_label);
1477 EMIT_ARG(label_assign, top_label);
Damience89a212013-10-15 22:25:17 +01001478 compile_node(comp, pns->nodes[1]); // body
Damien Georgeb9791222014-01-23 00:34:21 +00001479 EMIT_ARG(label_assign, continue_label);
Damience89a212013-10-15 22:25:17 +01001480 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1481#endif
1482
1483 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001484 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001485
1486 compile_node(comp, pns->nodes[2]); // else
1487
Damien Georgeb9791222014-01-23 00:34:21 +00001488 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001489}
1490
Damienf72fd0e2013-11-06 20:20:49 +00001491// TODO preload end and step onto stack if they are not constants
1492// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001493void 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 +00001494 START_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001495
1496 int top_label = comp_next_label(comp);
Damien George600ae732014-01-21 23:48:04 +00001497 int entry_label = comp_next_label(comp);
Damienf72fd0e2013-11-06 20:20:49 +00001498
1499 // compile: var = start
1500 compile_node(comp, pn_start);
1501 c_assign(comp, pn_var, ASSIGN_STORE);
1502
Damien Georgeb9791222014-01-23 00:34:21 +00001503 EMIT_ARG(jump, entry_label);
1504 EMIT_ARG(label_assign, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001505
Damienf3822fc2013-11-09 20:12:03 +00001506 // compile body
1507 compile_node(comp, pn_body);
1508
Damien Georgeb9791222014-01-23 00:34:21 +00001509 EMIT_ARG(label_assign, continue_label);
Damien George600ae732014-01-21 23:48:04 +00001510
Damienf72fd0e2013-11-06 20:20:49 +00001511 // compile: var += step
1512 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1513 compile_node(comp, pn_step);
Damien Georgeb9791222014-01-23 00:34:21 +00001514 EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_ADD);
Damienf72fd0e2013-11-06 20:20:49 +00001515 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1516
Damien Georgeb9791222014-01-23 00:34:21 +00001517 EMIT_ARG(label_assign, entry_label);
Damienf72fd0e2013-11-06 20:20:49 +00001518
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001519 // compile: if var <cond> end: goto top
Damienf72fd0e2013-11-06 20:20:49 +00001520 compile_node(comp, pn_var);
1521 compile_node(comp, pn_end);
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02001522 assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
1523 if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
Damien George9aa2a522014-02-01 23:04:09 +00001524 EMIT_ARG(binary_op, RT_BINARY_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001525 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001526 EMIT_ARG(binary_op, RT_BINARY_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001527 }
Damien Georgeb9791222014-01-23 00:34:21 +00001528 EMIT_ARG(pop_jump_if_true, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001529
1530 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001531 END_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001532
1533 compile_node(comp, pn_else);
1534
Damien Georgeb9791222014-01-23 00:34:21 +00001535 EMIT_ARG(label_assign, break_label);
Damienf72fd0e2013-11-06 20:20:49 +00001536}
1537
Damiend99b0522013-12-21 18:17:45 +00001538void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001539#if !MICROPY_EMIT_CPYTHON
1540 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1541 // this is actually slower, but uses no heap memory
1542 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001543 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)) {
1544 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001545 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1546 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1547 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
1548 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
Damiend99b0522013-12-21 18:17:45 +00001549 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1550 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001551 int n_args = list_get(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001552 mp_parse_node_t pn_range_start;
1553 mp_parse_node_t pn_range_end;
1554 mp_parse_node_t pn_range_step;
1555 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001556 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001557 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001558 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001559 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001560 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001561 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001562 } else if (n_args == 2) {
1563 pn_range_start = args[0];
1564 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001565 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001566 } else {
1567 pn_range_start = args[0];
1568 pn_range_end = args[1];
1569 pn_range_step = args[2];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001570 // We need to know sign of step. This is possible only if it's constant
1571 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
1572 optimize = false;
1573 }
Damienf72fd0e2013-11-06 20:20:49 +00001574 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001575 }
1576 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001577 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1578 return;
1579 }
1580 }
1581 }
1582#endif
1583
Damien Georgecbddb272014-02-01 20:08:18 +00001584 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001585
Damienb05d7072013-10-05 13:37:10 +01001586 int pop_label = comp_next_label(comp);
1587 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001588
Damience89a212013-10-15 22:25:17 +01001589 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1590#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001591 EMIT_ARG(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001592#endif
1593
Damien429d7192013-10-04 19:53:11 +01001594 compile_node(comp, pns->nodes[1]); // iterator
1595 EMIT(get_iter);
Damien Georgecbddb272014-02-01 20:08:18 +00001596 EMIT_ARG(label_assign, continue_label);
Damien Georgeb9791222014-01-23 00:34:21 +00001597 EMIT_ARG(for_iter, pop_label);
Damien429d7192013-10-04 19:53:11 +01001598 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1599 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001600 if (!EMIT(last_emit_was_return_value)) {
Damien Georgecbddb272014-02-01 20:08:18 +00001601 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001602 }
Damien Georgeb9791222014-01-23 00:34:21 +00001603 EMIT_ARG(label_assign, pop_label);
Damien429d7192013-10-04 19:53:11 +01001604 EMIT(for_iter_end);
1605
1606 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001607 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001608
Damience89a212013-10-15 22:25:17 +01001609#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001610 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001611#endif
Damien429d7192013-10-04 19:53:11 +01001612
1613 compile_node(comp, pns->nodes[3]); // else (not tested)
1614
Damien Georgeb9791222014-01-23 00:34:21 +00001615 EMIT_ARG(label_assign, break_label);
1616 EMIT_ARG(label_assign, end_label);
Damien429d7192013-10-04 19:53:11 +01001617}
1618
Damiend99b0522013-12-21 18:17:45 +00001619void 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 +01001620 // this function is a bit of a hack at the moment
1621 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1622
1623 // setup code
1624 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001625 int l1 = comp_next_label(comp);
1626 int success_label = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001627
Damien Georgeb9791222014-01-23 00:34:21 +00001628 EMIT_ARG(setup_except, l1);
Damien Georgecbddb272014-02-01 20:08:18 +00001629 comp->cur_except_level += 1;
1630
Damien429d7192013-10-04 19:53:11 +01001631 compile_node(comp, pn_body); // body
1632 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001633 EMIT_ARG(jump, success_label);
1634 EMIT_ARG(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001635 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001636
1637 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001638 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1639 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001640
1641 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001642 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001643
Damiend99b0522013-12-21 18:17:45 +00001644 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001645 // this is a catch all exception handler
1646 if (i + 1 != n_except) {
Damien Georgef41fdd02014-03-03 23:19:11 +00001647 compile_syntax_error(comp, "default 'except:' must be last");
Damien429d7192013-10-04 19:53:11 +01001648 return;
1649 }
1650 } else {
1651 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001652 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1653 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1654 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1655 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001656 // handler binds the exception to a local
1657 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001658 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001659 }
1660 }
1661 EMIT(dup_top);
1662 compile_node(comp, pns_exception_expr);
Damien George9aa2a522014-02-01 23:04:09 +00001663 EMIT_ARG(binary_op, RT_BINARY_OP_EXCEPTION_MATCH);
Damien Georgeb9791222014-01-23 00:34:21 +00001664 EMIT_ARG(pop_jump_if_false, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001665 }
1666
1667 EMIT(pop_top);
1668
1669 if (qstr_exception_local == 0) {
1670 EMIT(pop_top);
1671 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001672 EMIT_ARG(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001673 }
1674
1675 EMIT(pop_top);
1676
Damiene2880aa2013-12-20 14:22:59 +00001677 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001678 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001679 l3 = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001680 EMIT_ARG(setup_finally, l3);
Damien Georgecbddb272014-02-01 20:08:18 +00001681 comp->cur_except_level += 1;
Damien429d7192013-10-04 19:53:11 +01001682 }
1683 compile_node(comp, pns_except->nodes[1]);
1684 if (qstr_exception_local != 0) {
1685 EMIT(pop_block);
1686 }
1687 EMIT(pop_except);
1688 if (qstr_exception_local != 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001689 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1690 EMIT_ARG(label_assign, l3);
1691 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1692 EMIT_ARG(store_id, qstr_exception_local);
1693 EMIT_ARG(delete_id, qstr_exception_local);
Damien Georgecbddb272014-02-01 20:08:18 +00001694
1695 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001696 EMIT(end_finally);
1697 }
Damien Georgeb9791222014-01-23 00:34:21 +00001698 EMIT_ARG(jump, l2);
1699 EMIT_ARG(label_assign, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001700 }
1701
Damien Georgecbddb272014-02-01 20:08:18 +00001702 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001703 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001704
Damien Georgeb9791222014-01-23 00:34:21 +00001705 EMIT_ARG(label_assign, success_label);
Damien429d7192013-10-04 19:53:11 +01001706 compile_node(comp, pn_else); // else block, can be null
Damien Georgeb9791222014-01-23 00:34:21 +00001707 EMIT_ARG(label_assign, l2);
1708 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001709}
1710
Damiend99b0522013-12-21 18:17:45 +00001711void 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 +01001712 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1713 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001714 int l_finally_block = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001715
Damien Georgeb9791222014-01-23 00:34:21 +00001716 EMIT_ARG(setup_finally, l_finally_block);
Damien Georgecbddb272014-02-01 20:08:18 +00001717 comp->cur_except_level += 1;
1718
Damien429d7192013-10-04 19:53:11 +01001719 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001720 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001721 compile_node(comp, pn_body);
1722 } else {
1723 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1724 }
1725 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001726 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1727 EMIT_ARG(label_assign, l_finally_block);
Damien429d7192013-10-04 19:53:11 +01001728 compile_node(comp, pn_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001729
1730 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001731 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001732
Damien Georgeb9791222014-01-23 00:34:21 +00001733 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001734}
1735
Damiend99b0522013-12-21 18:17:45 +00001736void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1737 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1738 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1739 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001740 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001741 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1742 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001743 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001744 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001745 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001746 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001747 // no finally
1748 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1749 } else {
1750 // have finally
Damiend99b0522013-12-21 18:17:45 +00001751 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 +01001752 }
1753 } else {
1754 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001755 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001756 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001757 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001758 }
1759 } else {
1760 // shouldn't happen
1761 assert(0);
1762 }
1763}
1764
Damiend99b0522013-12-21 18:17:45 +00001765void 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 +01001766 if (n == 0) {
1767 // no more pre-bits, compile the body of the with
1768 compile_node(comp, body);
1769 } else {
Damienb05d7072013-10-05 13:37:10 +01001770 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001771 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001772 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001773 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001774 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001775 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001776 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1777 } else {
1778 // this pre-bit is just an expression
1779 compile_node(comp, nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001780 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001781 EMIT(pop_top);
1782 }
1783 // compile additional pre-bits and the body
1784 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1785 // finish this with block
1786 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001787 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1788 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001789 EMIT(with_cleanup);
1790 EMIT(end_finally);
1791 }
1792}
1793
Damiend99b0522013-12-21 18:17:45 +00001794void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001795 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001796 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001797 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1798 assert(n > 0);
1799
1800 // compile in a nested fashion
1801 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1802}
1803
Damiend99b0522013-12-21 18:17:45 +00001804void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1805 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001806 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1807 // for REPL, evaluate then print the expression
Damien Georgeb9791222014-01-23 00:34:21 +00001808 EMIT_ARG(load_id, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001809 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001810 EMIT_ARG(call_function, 1, 0, false, false);
Damien5ac1b2e2013-10-18 19:58:12 +01001811 EMIT(pop_top);
1812
Damien429d7192013-10-04 19:53:11 +01001813 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001814 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001815 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001816 // do nothing with a lonely constant
1817 } else {
1818 compile_node(comp, pns->nodes[0]); // just an expression
1819 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1820 }
Damien429d7192013-10-04 19:53:11 +01001821 }
1822 } else {
Damiend99b0522013-12-21 18:17:45 +00001823 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1824 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001825 if (kind == PN_expr_stmt_augassign) {
1826 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1827 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001828 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien George7e5fb242014-02-01 22:18:47 +00001829 rt_binary_op_t op;
Damiend99b0522013-12-21 18:17:45 +00001830 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
Damien George7e5fb242014-02-01 22:18:47 +00001831 case MP_TOKEN_DEL_PIPE_EQUAL: op = RT_BINARY_OP_INPLACE_OR; break;
1832 case MP_TOKEN_DEL_CARET_EQUAL: op = RT_BINARY_OP_INPLACE_XOR; break;
1833 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = RT_BINARY_OP_INPLACE_AND; break;
1834 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = RT_BINARY_OP_INPLACE_LSHIFT; break;
1835 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = RT_BINARY_OP_INPLACE_RSHIFT; break;
1836 case MP_TOKEN_DEL_PLUS_EQUAL: op = RT_BINARY_OP_INPLACE_ADD; break;
1837 case MP_TOKEN_DEL_MINUS_EQUAL: op = RT_BINARY_OP_INPLACE_SUBTRACT; break;
1838 case MP_TOKEN_DEL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_MULTIPLY; break;
1839 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
1840 case MP_TOKEN_DEL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
1841 case MP_TOKEN_DEL_PERCENT_EQUAL: op = RT_BINARY_OP_INPLACE_MODULO; break;
1842 case MP_TOKEN_DEL_DBL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_POWER; break;
1843 default: assert(0); op = RT_BINARY_OP_INPLACE_OR; // shouldn't happen
Damien429d7192013-10-04 19:53:11 +01001844 }
Damien George7e5fb242014-02-01 22:18:47 +00001845 EMIT_ARG(binary_op, op);
Damien429d7192013-10-04 19:53:11 +01001846 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1847 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001848 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1849 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001850 // following CPython, we store left-most first
1851 if (rhs > 0) {
1852 EMIT(dup_top);
1853 }
1854 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1855 for (int i = 0; i < rhs; i++) {
1856 if (i + 1 < rhs) {
1857 EMIT(dup_top);
1858 }
Damiend99b0522013-12-21 18:17:45 +00001859 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001860 }
1861 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001862 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1863 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1864 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1865 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001866 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001867 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1868 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001869 compile_node(comp, pns10->nodes[0]); // rhs
1870 compile_node(comp, pns10->nodes[1]); // rhs
1871 EMIT(rot_two);
1872 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1873 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001874 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1875 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1876 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1877 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001878 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001879 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1880 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001881 compile_node(comp, pns10->nodes[0]); // rhs
1882 compile_node(comp, pns10->nodes[1]); // rhs
1883 compile_node(comp, pns10->nodes[2]); // rhs
1884 EMIT(rot_three);
1885 EMIT(rot_two);
1886 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1887 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1888 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1889 } else {
1890 compile_node(comp, pns1->nodes[0]); // rhs
1891 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1892 }
1893 } else {
1894 // shouldn't happen
1895 assert(0);
1896 }
1897 }
1898}
1899
Damiend99b0522013-12-21 18:17:45 +00001900void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1901 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001902 compile_node(comp, pns->nodes[0]);
1903 for (int i = 1; i < num_nodes; i += 1) {
1904 compile_node(comp, pns->nodes[i]);
Damien Georgeb9791222014-01-23 00:34:21 +00001905 EMIT_ARG(binary_op, binary_op);
Damien429d7192013-10-04 19:53:11 +01001906 }
1907}
1908
Damiend99b0522013-12-21 18:17:45 +00001909void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1910 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1911 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001912
1913 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001914 int l_fail = comp_next_label(comp);
1915 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001916 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1917 compile_node(comp, pns->nodes[0]); // success value
Damien Georgeb9791222014-01-23 00:34:21 +00001918 EMIT_ARG(jump, l_end);
1919 EMIT_ARG(label_assign, l_fail);
1920 EMIT_ARG(set_stack_size, stack_size); // force stack size reset
Damien429d7192013-10-04 19:53:11 +01001921 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
Damien Georgeb9791222014-01-23 00:34:21 +00001922 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001923}
1924
Damiend99b0522013-12-21 18:17:45 +00001925void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001926 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001927 //mp_parse_node_t pn_params = pns->nodes[0];
1928 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001929
1930 if (comp->pass == PASS_1) {
1931 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001932 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 +01001933 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001934 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001935 }
1936
1937 // get the scope for this lambda
1938 scope_t *this_scope = (scope_t*)pns->nodes[2];
1939
1940 // make the lambda
1941 close_over_variables_etc(comp, this_scope, 0, 0);
1942}
1943
Damiend99b0522013-12-21 18:17:45 +00001944void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001945 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001946 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001947 for (int i = 0; i < n; i += 1) {
1948 compile_node(comp, pns->nodes[i]);
1949 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001950 EMIT_ARG(jump_if_true_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001951 }
1952 }
Damien Georgeb9791222014-01-23 00:34:21 +00001953 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001954}
1955
Damiend99b0522013-12-21 18:17:45 +00001956void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001957 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001958 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001959 for (int i = 0; i < n; i += 1) {
1960 compile_node(comp, pns->nodes[i]);
1961 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001962 EMIT_ARG(jump_if_false_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001963 }
1964 }
Damien Georgeb9791222014-01-23 00:34:21 +00001965 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001966}
1967
Damiend99b0522013-12-21 18:17:45 +00001968void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001969 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001970 EMIT_ARG(unary_op, RT_UNARY_OP_NOT);
Damien429d7192013-10-04 19:53:11 +01001971}
1972
Damiend99b0522013-12-21 18:17:45 +00001973void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001974 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001975 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001976 compile_node(comp, pns->nodes[0]);
1977 bool multi = (num_nodes > 3);
1978 int l_fail = 0;
1979 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001980 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001981 }
1982 for (int i = 1; i + 1 < num_nodes; i += 2) {
1983 compile_node(comp, pns->nodes[i + 1]);
1984 if (i + 2 < num_nodes) {
1985 EMIT(dup_top);
1986 EMIT(rot_three);
1987 }
Damien George7e5fb242014-02-01 22:18:47 +00001988 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
1989 rt_binary_op_t op;
1990 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
Damien George9aa2a522014-02-01 23:04:09 +00001991 case MP_TOKEN_OP_LESS: op = RT_BINARY_OP_LESS; break;
1992 case MP_TOKEN_OP_MORE: op = RT_BINARY_OP_MORE; break;
1993 case MP_TOKEN_OP_DBL_EQUAL: op = RT_BINARY_OP_EQUAL; break;
1994 case MP_TOKEN_OP_LESS_EQUAL: op = RT_BINARY_OP_LESS_EQUAL; break;
1995 case MP_TOKEN_OP_MORE_EQUAL: op = RT_BINARY_OP_MORE_EQUAL; break;
1996 case MP_TOKEN_OP_NOT_EQUAL: op = RT_BINARY_OP_NOT_EQUAL; break;
1997 case MP_TOKEN_KW_IN: op = RT_BINARY_OP_IN; break;
1998 default: assert(0); op = RT_BINARY_OP_LESS; // shouldn't happen
Damien George7e5fb242014-02-01 22:18:47 +00001999 }
2000 EMIT_ARG(binary_op, op);
Damiend99b0522013-12-21 18:17:45 +00002001 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
2002 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
2003 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01002004 if (kind == PN_comp_op_not_in) {
Damien George9aa2a522014-02-01 23:04:09 +00002005 EMIT_ARG(binary_op, RT_BINARY_OP_NOT_IN);
Damien429d7192013-10-04 19:53:11 +01002006 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00002007 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien George9aa2a522014-02-01 23:04:09 +00002008 EMIT_ARG(binary_op, RT_BINARY_OP_IS);
Damien429d7192013-10-04 19:53:11 +01002009 } else {
Damien George9aa2a522014-02-01 23:04:09 +00002010 EMIT_ARG(binary_op, RT_BINARY_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01002011 }
2012 } else {
2013 // shouldn't happen
2014 assert(0);
2015 }
2016 } else {
2017 // shouldn't happen
2018 assert(0);
2019 }
2020 if (i + 2 < num_nodes) {
Damien Georgeb9791222014-01-23 00:34:21 +00002021 EMIT_ARG(jump_if_false_or_pop, l_fail);
Damien429d7192013-10-04 19:53:11 +01002022 }
2023 }
2024 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01002025 int l_end = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002026 EMIT_ARG(jump, l_end);
2027 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01002028 EMIT(rot_two);
2029 EMIT(pop_top);
Damien Georgeb9791222014-01-23 00:34:21 +00002030 EMIT_ARG(label_assign, l_end);
2031 EMIT_ARG(set_stack_size, stack_size + 1); // force stack size
Damien429d7192013-10-04 19:53:11 +01002032 }
2033}
2034
Damiend99b0522013-12-21 18:17:45 +00002035void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002036 // TODO
2037 assert(0);
2038 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002039 //EMIT_ARG(unary_op, "UNARY_STAR");
Damien429d7192013-10-04 19:53:11 +01002040}
2041
Damiend99b0522013-12-21 18:17:45 +00002042void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002043 c_binary_op(comp, pns, RT_BINARY_OP_OR);
2044}
2045
Damiend99b0522013-12-21 18:17:45 +00002046void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002047 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
2048}
2049
Damiend99b0522013-12-21 18:17:45 +00002050void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002051 c_binary_op(comp, pns, RT_BINARY_OP_AND);
2052}
2053
Damiend99b0522013-12-21 18:17:45 +00002054void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2055 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002056 compile_node(comp, pns->nodes[0]);
2057 for (int i = 1; i + 1 < num_nodes; i += 2) {
2058 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002059 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002060 EMIT_ARG(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00002061 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002062 EMIT_ARG(binary_op, RT_BINARY_OP_RSHIFT);
Damien429d7192013-10-04 19:53:11 +01002063 } else {
2064 // shouldn't happen
2065 assert(0);
2066 }
2067 }
2068}
2069
Damiend99b0522013-12-21 18:17:45 +00002070void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2071 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002072 compile_node(comp, pns->nodes[0]);
2073 for (int i = 1; i + 1 < num_nodes; i += 2) {
2074 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002075 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002076 EMIT_ARG(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002077 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002078 EMIT_ARG(binary_op, RT_BINARY_OP_SUBTRACT);
Damien429d7192013-10-04 19:53:11 +01002079 } else {
2080 // shouldn't happen
2081 assert(0);
2082 }
2083 }
2084}
2085
Damiend99b0522013-12-21 18:17:45 +00002086void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2087 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002088 compile_node(comp, pns->nodes[0]);
2089 for (int i = 1; i + 1 < num_nodes; i += 2) {
2090 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002091 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002092 EMIT_ARG(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002093 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002094 EMIT_ARG(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002095 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002096 EMIT_ARG(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002097 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002098 EMIT_ARG(binary_op, RT_BINARY_OP_MODULO);
Damien429d7192013-10-04 19:53:11 +01002099 } else {
2100 // shouldn't happen
2101 assert(0);
2102 }
2103 }
2104}
2105
Damiend99b0522013-12-21 18:17:45 +00002106void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002107 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002108 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002109 EMIT_ARG(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002110 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002111 EMIT_ARG(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002112 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002113 EMIT_ARG(unary_op, RT_UNARY_OP_INVERT);
Damien429d7192013-10-04 19:53:11 +01002114 } else {
2115 // shouldn't happen
2116 assert(0);
2117 }
2118}
2119
Damien George35e2a4e2014-02-05 00:51:47 +00002120void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
2121 // this is to handle special super() call
2122 comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
2123
2124 compile_generic_all_nodes(comp, pns);
2125}
2126
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002127STATIC 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 +01002128 // function to call is on top of stack
2129
Damien George35e2a4e2014-02-05 00:51:47 +00002130#if !MICROPY_EMIT_CPYTHON
2131 // this is to handle special super() call
Damien Georgebbcd49a2014-02-06 20:30:16 +00002132 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 +00002133 EMIT_ARG(load_id, MP_QSTR___class__);
2134 // get first argument to function
2135 bool found = false;
2136 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
2137 if (comp->scope_cur->id_info[i].param) {
2138 EMIT_ARG(load_fast, MP_QSTR_, comp->scope_cur->id_info[i].local_num);
2139 found = true;
2140 break;
2141 }
2142 }
2143 if (!found) {
2144 printf("TypeError: super() call cannot find self\n");
2145 return;
2146 }
2147 EMIT_ARG(call_function, 2, 0, false, false);
2148 return;
2149 }
2150#endif
2151
Damien429d7192013-10-04 19:53:11 +01002152 int old_n_arg_keyword = comp->n_arg_keyword;
2153 bool old_have_star_arg = comp->have_star_arg;
2154 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2155 comp->n_arg_keyword = 0;
2156 comp->have_star_arg = false;
2157 comp->have_dbl_star_arg = false;
2158
Damien Georgebbcd49a2014-02-06 20:30:16 +00002159 compile_node(comp, pn_arglist); // arguments to function call; can be null
Damien429d7192013-10-04 19:53:11 +01002160
2161 // compute number of positional arguments
Damien Georgebbcd49a2014-02-06 20:30:16 +00002162 int n_positional = n_positional_extra + list_len(pn_arglist, PN_arglist) - comp->n_arg_keyword;
Damien429d7192013-10-04 19:53:11 +01002163 if (comp->have_star_arg) {
2164 n_positional -= 1;
2165 }
2166 if (comp->have_dbl_star_arg) {
2167 n_positional -= 1;
2168 }
2169
2170 if (is_method_call) {
Damien Georgeb9791222014-01-23 00:34:21 +00002171 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 +01002172 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002173 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 +01002174 }
2175
2176 comp->n_arg_keyword = old_n_arg_keyword;
2177 comp->have_star_arg = old_have_star_arg;
2178 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2179}
2180
Damiend99b0522013-12-21 18:17:45 +00002181void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2182 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002183 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002184 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 +01002185 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002186 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2187 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
Damien Georgeb9791222014-01-23 00:34:21 +00002188 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien Georgebbcd49a2014-02-06 20:30:16 +00002189 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
Damien429d7192013-10-04 19:53:11 +01002190 i += 1;
2191 } else {
2192 compile_node(comp, pns->nodes[i]);
2193 }
Damien George35e2a4e2014-02-05 00:51:47 +00002194 comp->func_arg_is_super = false;
Damien429d7192013-10-04 19:53:11 +01002195 }
2196}
2197
Damiend99b0522013-12-21 18:17:45 +00002198void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002199 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002200 EMIT_ARG(binary_op, RT_BINARY_OP_POWER);
Damien429d7192013-10-04 19:53:11 +01002201}
2202
Damiend99b0522013-12-21 18:17:45 +00002203void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002204 // a list of strings
Damien63321742013-12-10 17:41:49 +00002205
2206 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002207 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002208 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002209 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002210 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002211 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2212 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2213 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002214 if (i == 0) {
2215 string_kind = pn_kind;
2216 } else if (pn_kind != string_kind) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002217 compile_syntax_error(comp, "cannot mix bytes and nonbytes literals");
Damien63321742013-12-10 17:41:49 +00002218 return;
2219 }
Damien George55baff42014-01-21 21:40:13 +00002220 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01002221 }
Damien63321742013-12-10 17:41:49 +00002222
Damien63321742013-12-10 17:41:49 +00002223 // concatenate string/bytes
Damien George55baff42014-01-21 21:40:13 +00002224 byte *q_ptr;
2225 byte *s_dest = qstr_build_start(n_bytes, &q_ptr);
Damien63321742013-12-10 17:41:49 +00002226 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00002227 uint s_len;
2228 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00002229 memcpy(s_dest, s, s_len);
2230 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002231 }
Damien George55baff42014-01-21 21:40:13 +00002232 qstr q = qstr_build_end(q_ptr);
Damien63321742013-12-10 17:41:49 +00002233
Damien Georgeb9791222014-01-23 00:34:21 +00002234 EMIT_ARG(load_const_str, q, string_kind == MP_PARSE_NODE_BYTES);
Damien429d7192013-10-04 19:53:11 +01002235}
2236
2237// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002238void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2239 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2240 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2241 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002242
2243 if (comp->pass == PASS_1) {
2244 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002245 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 +01002246 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002247 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002248 }
2249
2250 // get the scope for this comprehension
2251 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2252
2253 // compile the comprehension
2254 close_over_variables_etc(comp, this_scope, 0, 0);
2255
2256 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2257 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002258 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01002259}
2260
Damiend99b0522013-12-21 18:17:45 +00002261void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2262 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002263 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002264 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2265 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2266 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2267 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2268 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2269 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2270 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002271 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002272 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002273 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002274 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002275 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002276 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002277 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002278 // generator expression
2279 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2280 } else {
2281 // tuple with 2 items
2282 goto tuple_with_2_items;
2283 }
2284 } else {
2285 // tuple with 2 items
2286 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002287 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002288 }
2289 } else {
2290 // parenthesis around a single item, is just that item
2291 compile_node(comp, pns->nodes[0]);
2292 }
2293}
2294
Damiend99b0522013-12-21 18:17:45 +00002295void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2296 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002297 // empty list
Damien Georgeb9791222014-01-23 00:34:21 +00002298 EMIT_ARG(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002299 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2300 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2301 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2302 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2303 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002304 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002305 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002306 compile_node(comp, pns2->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002307 EMIT_ARG(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002308 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002309 // list of many items
2310 compile_node(comp, pns2->nodes[0]);
2311 compile_generic_all_nodes(comp, pns3);
Damien Georgeb9791222014-01-23 00:34:21 +00002312 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
Damiend99b0522013-12-21 18:17:45 +00002313 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002314 // list comprehension
2315 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2316 } else {
2317 // list with 2 items
2318 goto list_with_2_items;
2319 }
2320 } else {
2321 // list with 2 items
2322 list_with_2_items:
2323 compile_node(comp, pns2->nodes[0]);
2324 compile_node(comp, pns2->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00002325 EMIT_ARG(build_list, 2);
Damien429d7192013-10-04 19:53:11 +01002326 }
2327 } else {
2328 // list with 1 item
2329 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002330 EMIT_ARG(build_list, 1);
Damien429d7192013-10-04 19:53:11 +01002331 }
2332}
2333
Damiend99b0522013-12-21 18:17:45 +00002334void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2335 mp_parse_node_t pn = pns->nodes[0];
2336 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002337 // empty dict
Damien Georgeb9791222014-01-23 00:34:21 +00002338 EMIT_ARG(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002339 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2340 pns = (mp_parse_node_struct_t*)pn;
2341 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002342 // dict with one element
Damien Georgeb9791222014-01-23 00:34:21 +00002343 EMIT_ARG(build_map, 1);
Damien429d7192013-10-04 19:53:11 +01002344 compile_node(comp, pn);
2345 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002346 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2347 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2348 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2349 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002350 // dict/set with multiple elements
2351
2352 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002353 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002354 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2355
2356 // first element sets whether it's a dict or set
2357 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002358 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002359 // a dictionary
Damien Georgeb9791222014-01-23 00:34:21 +00002360 EMIT_ARG(build_map, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002361 compile_node(comp, pns->nodes[0]);
2362 EMIT(store_map);
2363 is_dict = true;
2364 } else {
2365 // a set
2366 compile_node(comp, pns->nodes[0]); // 1st value of set
2367 is_dict = false;
2368 }
2369
2370 // process rest of elements
2371 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002372 mp_parse_node_t pn = nodes[i];
2373 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002374 compile_node(comp, pn);
2375 if (is_dict) {
2376 if (!is_key_value) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002377 compile_syntax_error(comp, "?expecting key:value for dictiona");
Damien429d7192013-10-04 19:53:11 +01002378 return;
2379 }
2380 EMIT(store_map);
2381 } else {
2382 if (is_key_value) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002383 compile_syntax_error(comp, "?expecting just a value for s");
Damien429d7192013-10-04 19:53:11 +01002384 return;
2385 }
2386 }
2387 }
2388
2389 // if it's a set, build it
2390 if (!is_dict) {
Damien Georgeb9791222014-01-23 00:34:21 +00002391 EMIT_ARG(build_set, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002392 }
Damiend99b0522013-12-21 18:17:45 +00002393 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002394 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002395 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002396 // a dictionary comprehension
2397 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2398 } else {
2399 // a set comprehension
2400 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2401 }
2402 } else {
2403 // shouldn't happen
2404 assert(0);
2405 }
2406 } else {
2407 // set with one element
2408 goto set_with_one_element;
2409 }
2410 } else {
2411 // set with one element
2412 set_with_one_element:
2413 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002414 EMIT_ARG(build_set, 1);
Damien429d7192013-10-04 19:53:11 +01002415 }
2416}
2417
Damiend99b0522013-12-21 18:17:45 +00002418void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgebbcd49a2014-02-06 20:30:16 +00002419 compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
Damien429d7192013-10-04 19:53:11 +01002420}
2421
Damiend99b0522013-12-21 18:17:45 +00002422void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002423 // object who's index we want is on top of stack
2424 compile_node(comp, pns->nodes[0]); // the index
Damien Georgeb9791222014-01-23 00:34:21 +00002425 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +01002426}
2427
Damiend99b0522013-12-21 18:17:45 +00002428void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002429 // object who's attribute we want is on top of stack
Damien Georgeb9791222014-01-23 00:34:21 +00002430 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002431}
2432
Damiend99b0522013-12-21 18:17:45 +00002433void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2434 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2435 mp_parse_node_t pn = pns->nodes[0];
2436 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002437 // [?:]
Damien Georgeb9791222014-01-23 00:34:21 +00002438 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
2439 EMIT_ARG(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002440 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2441 pns = (mp_parse_node_struct_t*)pn;
2442 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
Damien Georgeb9791222014-01-23 00:34:21 +00002443 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002444 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002445 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002446 // [?::]
Damien Georgeb9791222014-01-23 00:34:21 +00002447 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002448 } else {
2449 // [?::x]
2450 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002451 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002452 }
Damiend99b0522013-12-21 18:17:45 +00002453 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002454 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002455 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2456 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2457 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2458 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002459 // [?:x:]
Damien Georgeb9791222014-01-23 00:34:21 +00002460 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002461 } else {
2462 // [?:x:x]
2463 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002464 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002465 }
2466 } else {
2467 // [?:x]
2468 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002469 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002470 }
2471 } else {
2472 // [?:x]
2473 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002474 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002475 }
2476}
2477
Damiend99b0522013-12-21 18:17:45 +00002478void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002479 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002480 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2481 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002482}
2483
Damiend99b0522013-12-21 18:17:45 +00002484void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgeb9791222014-01-23 00:34:21 +00002485 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002486 compile_subscript_3_helper(comp, pns);
2487}
2488
Damiend99b0522013-12-21 18:17:45 +00002489void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002490 // if this is called then we are compiling a dict key:value pair
2491 compile_node(comp, pns->nodes[1]); // value
2492 compile_node(comp, pns->nodes[0]); // key
2493}
2494
Damiend99b0522013-12-21 18:17:45 +00002495void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002496 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002497 // store class object into class name
Damien Georgeb9791222014-01-23 00:34:21 +00002498 EMIT_ARG(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002499}
2500
Damiend99b0522013-12-21 18:17:45 +00002501void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002502 if (comp->have_star_arg) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002503 compile_syntax_error(comp, "?can't have multiple *x");
Damien429d7192013-10-04 19:53:11 +01002504 return;
2505 }
2506 comp->have_star_arg = true;
2507 compile_node(comp, pns->nodes[0]);
2508}
2509
Damiend99b0522013-12-21 18:17:45 +00002510void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002511 if (comp->have_dbl_star_arg) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002512 compile_syntax_error(comp, "?can't have multiple **x");
Damien429d7192013-10-04 19:53:11 +01002513 return;
2514 }
2515 comp->have_dbl_star_arg = true;
2516 compile_node(comp, pns->nodes[0]);
2517}
2518
Damiend99b0522013-12-21 18:17:45 +00002519void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2520 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2521 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2522 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2523 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002524 compile_syntax_error(comp, "?lhs of keyword argument must be an id");
Damien429d7192013-10-04 19:53:11 +01002525 return;
2526 }
Damien Georgeb9791222014-01-23 00:34:21 +00002527 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002528 compile_node(comp, pns2->nodes[0]);
2529 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002530 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002531 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2532 } else {
2533 // shouldn't happen
2534 assert(0);
2535 }
2536}
2537
Damiend99b0522013-12-21 18:17:45 +00002538void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002539 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002540 compile_syntax_error(comp, "'yield' outside function");
Damien429d7192013-10-04 19:53:11 +01002541 return;
2542 }
Damiend99b0522013-12-21 18:17:45 +00002543 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00002544 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002545 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002546 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2547 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002548 compile_node(comp, pns->nodes[0]);
2549 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002550 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002551 EMIT(yield_from);
2552 } else {
2553 compile_node(comp, pns->nodes[0]);
2554 EMIT(yield_value);
2555 }
2556}
2557
Damiend99b0522013-12-21 18:17:45 +00002558typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002559STATIC compile_function_t compile_function[] = {
Damien429d7192013-10-04 19:53:11 +01002560 NULL,
2561#define nc NULL
2562#define c(f) compile_##f
Damien George1dc76af2014-02-26 16:57:08 +00002563#define DEF_RULE(rule, comp, kind, ...) comp,
Damien429d7192013-10-04 19:53:11 +01002564#include "grammar.h"
2565#undef nc
2566#undef c
2567#undef DEF_RULE
2568};
2569
Damiend99b0522013-12-21 18:17:45 +00002570void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2571 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002572 // pass
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02002573 } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
2574 machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
2575 EMIT_ARG(load_const_small_int, arg);
Damiend99b0522013-12-21 18:17:45 +00002576 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02002577 machine_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +00002578 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002579 case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
Damien Georgeb9791222014-01-23 00:34:21 +00002580 case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
2581 case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
2582 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
2583 case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
Damiend99b0522013-12-21 18:17:45 +00002584 case MP_PARSE_NODE_TOKEN:
2585 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002586 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002587 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002588 // do nothing
2589 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002590 EMIT_ARG(load_const_tok, arg);
Damien91d387d2013-10-09 15:09:52 +01002591 }
2592 break;
Damien429d7192013-10-04 19:53:11 +01002593 default: assert(0);
2594 }
2595 } else {
Damiend99b0522013-12-21 18:17:45 +00002596 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien Georgeb9791222014-01-23 00:34:21 +00002597 EMIT_ARG(set_line_number, pns->source_line);
Damiend99b0522013-12-21 18:17:45 +00002598 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002599 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002600 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien Georgecbd2f742014-01-19 11:48:48 +00002601#if MICROPY_DEBUG_PRINTERS
2602 mp_parse_node_print(pn, 0);
2603#endif
Damien429d7192013-10-04 19:53:11 +01002604 assert(0);
2605 } else {
2606 f(comp, pns);
2607 }
2608 }
2609}
2610
Damiend99b0522013-12-21 18:17:45 +00002611void 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 +01002612 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002613 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002614 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2615 if (MP_PARSE_NODE_IS_ID(pn)) {
2616 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002617 if (comp->have_bare_star) {
2618 // comes after a bare star, so doesn't count as a parameter
2619 } else {
2620 comp->scope_cur->num_params += 1;
2621 }
Damienb14de212013-10-06 00:28:28 +01002622 } else {
Damiend99b0522013-12-21 18:17:45 +00002623 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2624 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2625 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2626 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002627 //int node_index = 1; unused
2628 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002629 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002630 // this parameter has an annotation
2631 pn_annotation = pns->nodes[1];
2632 }
2633 //node_index = 2; unused
2634 }
2635 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002636 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002637 // this parameter has a default value
2638 if (comp->have_bare_star) {
2639 comp->scope_cur->num_dict_params += 1;
2640 } else {
2641 comp->scope_cur->num_default_params += 1;
2642 }
2643 }
2644 */
2645 if (comp->have_bare_star) {
2646 // comes after a bare star, so doesn't count as a parameter
2647 } else {
2648 comp->scope_cur->num_params += 1;
2649 }
Damiend99b0522013-12-21 18:17:45 +00002650 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2651 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002652 // bare star
2653 // TODO see http://www.python.org/dev/peps/pep-3102/
2654 comp->have_bare_star = true;
2655 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002656 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002657 // named star
Damien George8725f8f2014-02-15 19:33:11 +00002658 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002659 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2660 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002661 // named star with annotation
Damien George8725f8f2014-02-15 19:33:11 +00002662 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002663 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2664 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002665 pn_annotation = pns->nodes[1];
2666 } else {
2667 // shouldn't happen
2668 assert(0);
2669 }
Damiend99b0522013-12-21 18:17:45 +00002670 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2671 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2672 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002673 // this parameter has an annotation
2674 pn_annotation = pns->nodes[1];
2675 }
Damien George8725f8f2014-02-15 19:33:11 +00002676 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002677 } else {
Damienb14de212013-10-06 00:28:28 +01002678 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002679 assert(0);
2680 }
Damien429d7192013-10-04 19:53:11 +01002681 }
2682
2683 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002684 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002685 // TODO this parameter has an annotation
2686 }
2687 bool added;
2688 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2689 if (!added) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002690 compile_syntax_error(comp, "?same name used for parameter");
Damien429d7192013-10-04 19:53:11 +01002691 return;
2692 }
2693 id_info->param = true;
2694 id_info->kind = ID_INFO_KIND_LOCAL;
2695 }
2696}
2697
Damiend99b0522013-12-21 18:17:45 +00002698void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002699 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2700}
2701
Damiend99b0522013-12-21 18:17:45 +00002702void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002703 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2704}
2705
Damiend99b0522013-12-21 18:17:45 +00002706void 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 +01002707 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002708 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002709 // no more nested if/for; compile inner expression
2710 compile_node(comp, pn_inner_expr);
2711 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002712 EMIT_ARG(list_append, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002713 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002714 EMIT_ARG(map_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002715 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002716 EMIT_ARG(set_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002717 } else {
2718 EMIT(yield_value);
2719 EMIT(pop_top);
2720 }
Damiend99b0522013-12-21 18:17:45 +00002721 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002722 // if condition
Damiend99b0522013-12-21 18:17:45 +00002723 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002724 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2725 pn_iter = pns_comp_if->nodes[1];
2726 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002727 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002728 // for loop
Damiend99b0522013-12-21 18:17:45 +00002729 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002730 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002731 int l_end2 = comp_next_label(comp);
2732 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002733 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002734 EMIT_ARG(label_assign, l_top2);
2735 EMIT_ARG(for_iter, l_end2);
Damien429d7192013-10-04 19:53:11 +01002736 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2737 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 +00002738 EMIT_ARG(jump, l_top2);
2739 EMIT_ARG(label_assign, l_end2);
Damien429d7192013-10-04 19:53:11 +01002740 EMIT(for_iter_end);
2741 } else {
2742 // shouldn't happen
2743 assert(0);
2744 }
2745}
2746
Damiend99b0522013-12-21 18:17:45 +00002747void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002748 // see http://www.python.org/dev/peps/pep-0257/
2749
2750 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002751 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002752 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002753 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002754 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002755 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2756 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002757 for (int i = 0; i < num_nodes; i++) {
2758 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002759 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 +00002760 // not a newline, so this is the first statement; finish search
2761 break;
2762 }
2763 }
2764 // 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 +00002765 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002766 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002767 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002768 } else {
2769 return;
2770 }
2771
2772 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002773 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2774 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2775 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2776 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2777 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002778 compile_node(comp, pns->nodes[0]); // a doc string
2779 // store doc string
Damien Georgeb9791222014-01-23 00:34:21 +00002780 EMIT_ARG(store_id, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002781 }
2782 }
2783 }
2784}
2785
2786void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2787 comp->pass = pass;
2788 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002789 comp->next_label = 1;
Damien Georgeb9791222014-01-23 00:34:21 +00002790 EMIT_ARG(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002791
2792 if (comp->pass == PASS_1) {
2793 scope->stack_size = 0;
2794 }
2795
Damien5ac1b2e2013-10-18 19:58:12 +01002796#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002797 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002798 scope_print_info(scope);
2799 }
Damien5ac1b2e2013-10-18 19:58:12 +01002800#endif
Damien429d7192013-10-04 19:53:11 +01002801
2802 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002803 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2804 assert(scope->kind == SCOPE_MODULE);
2805 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2806 compile_node(comp, pns->nodes[0]); // compile the expression
2807 EMIT(return_value);
2808 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002809 if (!comp->is_repl) {
2810 check_for_doc_string(comp, scope->pn);
2811 }
Damien429d7192013-10-04 19:53:11 +01002812 compile_node(comp, scope->pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002813 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002814 EMIT(return_value);
2815 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002816 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2817 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2818 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002819
2820 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002821 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002822 if (comp->pass == PASS_1) {
2823 comp->have_bare_star = false;
2824 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2825 }
2826
Paul Sokolovsky2f0b0262014-02-10 02:04:26 +02002827 // pns->nodes[2] is return/whole function annotation
Damien429d7192013-10-04 19:53:11 +01002828
2829 compile_node(comp, pns->nodes[3]); // 3 is function body
2830 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002831 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002832 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002833 EMIT(return_value);
2834 }
2835 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002836 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2837 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2838 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002839
2840 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002841 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002842 if (comp->pass == PASS_1) {
2843 comp->have_bare_star = false;
2844 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2845 }
2846
2847 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2848 EMIT(return_value);
2849 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2850 // a bit of a hack at the moment
2851
Damiend99b0522013-12-21 18:17:45 +00002852 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2853 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2854 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2855 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2856 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002857
Damien George55baff42014-01-21 21:40:13 +00002858 qstr qstr_arg = QSTR_FROM_STR_STATIC(".0");
Damien429d7192013-10-04 19:53:11 +01002859 if (comp->pass == PASS_1) {
2860 bool added;
2861 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2862 assert(added);
2863 id_info->kind = ID_INFO_KIND_LOCAL;
2864 scope->num_params = 1;
2865 }
2866
2867 if (scope->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002868 EMIT_ARG(build_list, 0);
Damien429d7192013-10-04 19:53:11 +01002869 } else if (scope->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002870 EMIT_ARG(build_map, 0);
Damien429d7192013-10-04 19:53:11 +01002871 } else if (scope->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002872 EMIT_ARG(build_set, 0);
Damien429d7192013-10-04 19:53:11 +01002873 }
2874
Damienb05d7072013-10-05 13:37:10 +01002875 int l_end = comp_next_label(comp);
2876 int l_top = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002877 EMIT_ARG(load_id, qstr_arg);
2878 EMIT_ARG(label_assign, l_top);
2879 EMIT_ARG(for_iter, l_end);
Damien429d7192013-10-04 19:53:11 +01002880 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2881 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
Damien Georgeb9791222014-01-23 00:34:21 +00002882 EMIT_ARG(jump, l_top);
2883 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002884 EMIT(for_iter_end);
2885
2886 if (scope->kind == SCOPE_GEN_EXPR) {
Damien Georgeb9791222014-01-23 00:34:21 +00002887 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002888 }
2889 EMIT(return_value);
2890 } else {
2891 assert(scope->kind == SCOPE_CLASS);
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_classdef);
Damien429d7192013-10-04 19:53:11 +01002895
2896 if (comp->pass == PASS_1) {
2897 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002898 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01002899 assert(added);
2900 id_info->kind = ID_INFO_KIND_LOCAL;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002901 id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
Damien429d7192013-10-04 19:53:11 +01002902 assert(added);
2903 id_info->kind = ID_INFO_KIND_LOCAL;
2904 id_info->param = true;
2905 scope->num_params = 1; // __locals__ is the parameter
2906 }
2907
Damien Georgeb9791222014-01-23 00:34:21 +00002908 EMIT_ARG(load_id, MP_QSTR___locals__);
Damien429d7192013-10-04 19:53:11 +01002909 EMIT(store_locals);
Damien Georgeb9791222014-01-23 00:34:21 +00002910 EMIT_ARG(load_id, MP_QSTR___name__);
2911 EMIT_ARG(store_id, MP_QSTR___module__);
2912 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
2913 EMIT_ARG(store_id, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01002914
2915 check_for_doc_string(comp, pns->nodes[2]);
2916 compile_node(comp, pns->nodes[2]); // 2 is class body
2917
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002918 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01002919 assert(id != NULL);
2920 if (id->kind == ID_INFO_KIND_LOCAL) {
Damien Georgeb9791222014-01-23 00:34:21 +00002921 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002922 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002923#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00002924 EMIT_ARG(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002925#else
Damien George35e2a4e2014-02-05 00:51:47 +00002926 EMIT_ARG(load_fast, MP_QSTR___class__, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +00002927#endif
Damien429d7192013-10-04 19:53:11 +01002928 }
2929 EMIT(return_value);
2930 }
2931
Damien415eb6f2013-10-05 12:19:06 +01002932 EMIT(end_pass);
Damien826005c2013-10-05 23:17:28 +01002933}
2934
2935void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2936 comp->pass = pass;
2937 comp->scope_cur = scope;
2938 comp->next_label = 1;
2939
2940 if (scope->kind != SCOPE_FUNCTION) {
2941 printf("Error: inline assembler must be a function\n");
2942 return;
2943 }
2944
Damiena2f2f7d2013-10-06 00:14:13 +01002945 if (comp->pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002946 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur);
Damiena2f2f7d2013-10-06 00:14:13 +01002947 }
2948
Damien826005c2013-10-05 23:17:28 +01002949 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002950 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2951 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2952 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002953
Damiend99b0522013-12-21 18:17:45 +00002954 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002955
Damiena2f2f7d2013-10-06 00:14:13 +01002956 // parameters are in pns->nodes[1]
2957 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002958 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002959 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
Damien Georgeb9791222014-01-23 00:34:21 +00002960 scope->num_params = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
Damiena2f2f7d2013-10-06 00:14:13 +01002961 }
2962
Damiend99b0522013-12-21 18:17:45 +00002963 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002964
Damiend99b0522013-12-21 18:17:45 +00002965 mp_parse_node_t pn_body = pns->nodes[3]; // body
2966 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002967 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2968
Damien Georgecbd2f742014-01-19 11:48:48 +00002969 /*
Damien826005c2013-10-05 23:17:28 +01002970 if (comp->pass == PASS_3) {
2971 //printf("----\n");
2972 scope_print_info(scope);
2973 }
Damien Georgecbd2f742014-01-19 11:48:48 +00002974 */
Damien826005c2013-10-05 23:17:28 +01002975
2976 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002977 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2978 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2979 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2980 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2981 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2982 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2983 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2984 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2985 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2986 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2987 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2988 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2989 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002990 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2991
2992 // emit instructions
2993 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00002994 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002995 compile_syntax_error(comp, "inline assembler 'label' requires 1 argument");
Damien826005c2013-10-05 23:17:28 +01002996 return;
2997 }
2998 int lab = comp_next_label(comp);
2999 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00003000 EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01003001 }
3002 } else {
3003 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00003004 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
Damien826005c2013-10-05 23:17:28 +01003005 }
3006 }
3007 }
3008
3009 if (comp->pass > PASS_1) {
3010 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01003011 }
Damien429d7192013-10-04 19:53:11 +01003012}
3013
3014void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
3015 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00003016 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01003017 scope->num_locals = 0;
3018 for (int i = 0; i < scope->id_info_len; i++) {
3019 id_info_t *id = &scope->id_info[i];
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003020 if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01003021 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
3022 continue;
3023 }
3024 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
3025 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
3026 }
Damien9ecbcff2013-12-11 00:41:43 +00003027 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01003028 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
3029 id->local_num = scope->num_locals;
3030 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00003031 }
3032 }
3033
3034 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00003035#if MICROPY_EMIT_CPYTHON
3036 int num_cell = 0;
3037#endif
Damien9ecbcff2013-12-11 00:41:43 +00003038 for (int i = 0; i < scope->id_info_len; i++) {
3039 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00003040#if MICROPY_EMIT_CPYTHON
3041 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00003042 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00003043 id->local_num = num_cell;
3044 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00003045 }
Damien George6baf76e2013-12-30 22:32:17 +00003046#else
3047 // in Micro Python the cells come right after the fast locals
3048 // parameters are not counted here, since they remain at the start
3049 // of the locals, even if they are cell vars
3050 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
3051 id->local_num = scope->num_locals;
3052 scope->num_locals += 1;
3053 }
3054#endif
Damien9ecbcff2013-12-11 00:41:43 +00003055 }
Damien9ecbcff2013-12-11 00:41:43 +00003056
3057 // compute the index of free vars (freevars[idx] in CPython)
3058 // make sure they are in the order of the parent scope
3059 if (scope->parent != NULL) {
3060 int num_free = 0;
3061 for (int i = 0; i < scope->parent->id_info_len; i++) {
3062 id_info_t *id = &scope->parent->id_info[i];
3063 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3064 for (int j = 0; j < scope->id_info_len; j++) {
3065 id_info_t *id2 = &scope->id_info[j];
3066 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00003067 assert(!id2->param); // free vars should not be params
3068#if MICROPY_EMIT_CPYTHON
3069 // in CPython the frees are numbered after the cells
3070 id2->local_num = num_cell + num_free;
3071#else
3072 // in Micro Python the frees come first, before the params
3073 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00003074#endif
3075 num_free += 1;
3076 }
3077 }
3078 }
Damien429d7192013-10-04 19:53:11 +01003079 }
Damien George6baf76e2013-12-30 22:32:17 +00003080#if !MICROPY_EMIT_CPYTHON
3081 // in Micro Python shift all other locals after the free locals
3082 if (num_free > 0) {
3083 for (int i = 0; i < scope->id_info_len; i++) {
3084 id_info_t *id = &scope->id_info[i];
3085 if (id->param || id->kind != ID_INFO_KIND_FREE) {
3086 id->local_num += num_free;
3087 }
3088 }
3089 scope->num_params += num_free; // free vars are counted as params for passing them into the function
3090 scope->num_locals += num_free;
3091 }
3092#endif
Damien429d7192013-10-04 19:53:11 +01003093 }
3094
Damien George8725f8f2014-02-15 19:33:11 +00003095 // compute scope_flags
3096 //scope->scope_flags = 0; since we set some things in parameters
Damien429d7192013-10-04 19:53:11 +01003097 if (scope->kind != SCOPE_MODULE) {
Damien George8725f8f2014-02-15 19:33:11 +00003098 scope->scope_flags |= MP_SCOPE_FLAG_NEWLOCALS;
Damien429d7192013-10-04 19:53:11 +01003099 }
3100 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) {
3101 assert(scope->parent != NULL);
Damien George8725f8f2014-02-15 19:33:11 +00003102 scope->scope_flags |= MP_SCOPE_FLAG_OPTIMISED;
Damien429d7192013-10-04 19:53:11 +01003103
3104 // TODO possibly other ways it can be nested
Damien George08d07552014-01-29 18:58:52 +00003105 // Note that we don't actually use this information at the moment (for CPython compat only)
3106 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 +00003107 scope->scope_flags |= MP_SCOPE_FLAG_NESTED;
Damien429d7192013-10-04 19:53:11 +01003108 }
3109 }
3110 int num_free = 0;
3111 for (int i = 0; i < scope->id_info_len; i++) {
3112 id_info_t *id = &scope->id_info[i];
3113 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3114 num_free += 1;
3115 }
3116 }
3117 if (num_free == 0) {
Damien George8725f8f2014-02-15 19:33:11 +00003118 scope->scope_flags |= MP_SCOPE_FLAG_NOFREE;
Damien429d7192013-10-04 19:53:11 +01003119 }
3120}
3121
Damien George08335002014-01-18 23:24:36 +00003122mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003123 compiler_t *comp = m_new(compiler_t, 1);
3124
Damien Georgecbd2f742014-01-19 11:48:48 +00003125 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003126 comp->is_repl = is_repl;
3127 comp->had_error = false;
3128
Damien429d7192013-10-04 19:53:11 +01003129 comp->break_label = 0;
3130 comp->continue_label = 0;
Damien Georgecbddb272014-02-01 20:08:18 +00003131 comp->break_continue_except_level = 0;
3132 comp->cur_except_level = 0;
3133
Damien George35e2a4e2014-02-05 00:51:47 +00003134 comp->func_arg_is_super = false;
3135
Damien429d7192013-10-04 19:53:11 +01003136 comp->scope_head = NULL;
3137 comp->scope_cur = NULL;
3138
Damien826005c2013-10-05 23:17:28 +01003139 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003140 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003141
3142 // set the outer scope
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003143 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003144
Damien826005c2013-10-05 23:17:28 +01003145 // compile pass 1
Damien George35e2a4e2014-02-05 00:51:47 +00003146 comp->emit = emit_pass1_new();
Damien826005c2013-10-05 23:17:28 +01003147 comp->emit_method_table = &emit_pass1_method_table;
3148 comp->emit_inline_asm = NULL;
3149 comp->emit_inline_asm_method_table = NULL;
3150 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003151 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003152 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003153#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003154 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003155 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003156#endif
Damien826005c2013-10-05 23:17:28 +01003157 } else {
3158 compile_scope(comp, s, PASS_1);
3159 }
3160
3161 // update maximim number of labels needed
3162 if (comp->next_label > max_num_labels) {
3163 max_num_labels = comp->next_label;
3164 }
Damien429d7192013-10-04 19:53:11 +01003165 }
3166
Damien826005c2013-10-05 23:17:28 +01003167 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003168 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003169 compile_scope_compute_things(comp, s);
3170 }
3171
Damien826005c2013-10-05 23:17:28 +01003172 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003173 emit_pass1_free(comp->emit);
3174
Damien826005c2013-10-05 23:17:28 +01003175 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003176#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003177 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003178#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003179 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003180#endif
Damien3ef4abb2013-10-12 16:53:13 +01003181#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003182 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003183#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003184#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003185 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003186 if (false) {
3187 // dummy
3188
Damien3ef4abb2013-10-12 16:53:13 +01003189#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003190 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3191 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003192 if (emit_inline_thumb == NULL) {
3193 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3194 }
3195 comp->emit = NULL;
3196 comp->emit_method_table = NULL;
3197 comp->emit_inline_asm = emit_inline_thumb;
3198 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3199 compile_scope_inline_asm(comp, s, PASS_2);
3200 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003201#endif
3202
Damien826005c2013-10-05 23:17:28 +01003203 } else {
Damienc025ebb2013-10-12 14:30:21 +01003204
3205 // choose the emit type
3206
Damien3ef4abb2013-10-12 16:53:13 +01003207#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003208 comp->emit = emit_cpython_new(max_num_labels);
3209 comp->emit_method_table = &emit_cpython_method_table;
3210#else
Damien826005c2013-10-05 23:17:28 +01003211 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003212
3213#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003214 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003215 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003216#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003217 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003218 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003219 }
Damien13ed3a62013-10-08 09:05:10 +01003220 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003221#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003222 if (emit_native == NULL) {
3223 emit_native = emit_native_thumb_new(max_num_labels);
3224 }
3225 comp->emit_method_table = &emit_native_thumb_method_table;
3226#endif
3227 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003228 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003229 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003230#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003231
Damien826005c2013-10-05 23:17:28 +01003232 default:
3233 if (emit_bc == NULL) {
Damien Georgecbd2f742014-01-19 11:48:48 +00003234 emit_bc = emit_bc_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003235 }
3236 comp->emit = emit_bc;
3237 comp->emit_method_table = &emit_bc_method_table;
3238 break;
3239 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003240#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003241
3242 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003243 compile_scope(comp, s, PASS_2);
3244 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003245 }
Damien429d7192013-10-04 19:53:11 +01003246 }
3247
Damien George41d02b62014-01-24 22:42:28 +00003248 // free the emitters
3249#if !MICROPY_EMIT_CPYTHON
3250 if (emit_bc != NULL) {
3251 emit_bc_free(emit_bc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +02003252 }
Damien George41d02b62014-01-24 22:42:28 +00003253#if MICROPY_EMIT_NATIVE
3254 if (emit_native != NULL) {
3255#if MICROPY_EMIT_X64
3256 emit_native_x64_free(emit_native);
3257#elif MICROPY_EMIT_THUMB
3258 emit_native_thumb_free(emit_native);
3259#endif
3260 }
3261#endif
3262#if MICROPY_EMIT_INLINE_THUMB
3263 if (emit_inline_thumb != NULL) {
3264 emit_inline_thumb_free(emit_inline_thumb);
3265 }
3266#endif
3267#endif // !MICROPY_EMIT_CPYTHON
3268
3269 // free the scopes
Paul Sokolovskyfd313582014-01-23 23:05:47 +02003270 uint unique_code_id = module_scope->unique_code_id;
3271 for (scope_t *s = module_scope; s;) {
3272 scope_t *next = s->next;
3273 scope_free(s);
3274 s = next;
3275 }
Damien5ac1b2e2013-10-18 19:58:12 +01003276
Damien George41d02b62014-01-24 22:42:28 +00003277 // free the compiler
3278 bool had_error = comp->had_error;
3279 m_del_obj(compiler_t, comp);
3280
Damien George1fb03172014-01-03 14:22:03 +00003281 if (had_error) {
3282 // TODO return a proper error message
3283 return mp_const_none;
3284 } else {
3285#if MICROPY_EMIT_CPYTHON
3286 // can't create code, so just return true
Damien George41d02b62014-01-24 22:42:28 +00003287 (void)unique_code_id; // to suppress warning that unique_code_id is unused
Damien George1fb03172014-01-03 14:22:03 +00003288 return mp_const_true;
3289#else
3290 // return function that executes the outer module
Paul Sokolovsky90750022014-02-01 15:05:04 +02003291 return rt_make_function_from_id(unique_code_id, MP_OBJ_NULL);
Damien George1fb03172014-01-03 14:22:03 +00003292#endif
3293 }
Damien429d7192013-10-04 19:53:11 +01003294}