blob: d1aec3095804201ce0dbc20fe05c7df74377cd91 [file] [log] [blame]
Damien429d7192013-10-04 19:53:11 +01001#include <unistd.h>
2#include <stdlib.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <string.h>
6#include <assert.h>
7
8#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +00009#include "mpconfig.h"
Damien George55baff42014-01-21 21:40:13 +000010#include "qstr.h"
Damien429d7192013-10-04 19:53:11 +010011#include "lexer.h"
Damien429d7192013-10-04 19:53:11 +010012#include "parse.h"
13#include "scope.h"
Damiend99b0522013-12-21 18:17:45 +000014#include "runtime0.h"
Damien429d7192013-10-04 19:53:11 +010015#include "emit.h"
Damien George1fb03172014-01-03 14:22:03 +000016#include "obj.h"
17#include "compile.h"
18#include "runtime.h"
Damien429d7192013-10-04 19:53:11 +010019
20// TODO need to mangle __attr names
21
Damience89a212013-10-15 22:25:17 +010022#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)
23
Damien429d7192013-10-04 19:53:11 +010024typedef enum {
25 PN_none = 0,
Damien George00208ce2014-01-23 00:00:53 +000026#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
Damien429d7192013-10-04 19:53:11 +010027#include "grammar.h"
28#undef DEF_RULE
29 PN_maximum_number_of,
30} pn_kind_t;
31
Damien Georgeb9791222014-01-23 00:34:21 +000032#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
33#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
34#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
35#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
Damien429d7192013-10-04 19:53:11 +010036
Damien6cdd3af2013-10-05 18:08:26 +010037#define EMIT_OPT_NONE (0)
38#define EMIT_OPT_BYTE_CODE (1)
39#define EMIT_OPT_NATIVE_PYTHON (2)
Damien7af3d192013-10-07 00:02:49 +010040#define EMIT_OPT_VIPER (3)
41#define EMIT_OPT_ASM_THUMB (4)
Damien6cdd3af2013-10-05 18:08:26 +010042
Damien429d7192013-10-04 19:53:11 +010043typedef struct _compiler_t {
Damien Georgecbd2f742014-01-19 11:48:48 +000044 qstr source_file;
Damien5ac1b2e2013-10-18 19:58:12 +010045 bool is_repl;
Damien429d7192013-10-04 19:53:11 +010046 pass_kind_t pass;
Damien5ac1b2e2013-10-18 19:58:12 +010047 bool had_error; // try to keep compiler clean from nlr
Damien429d7192013-10-04 19:53:11 +010048
Damienb05d7072013-10-05 13:37:10 +010049 int next_label;
Damienb05d7072013-10-05 13:37:10 +010050
Damien429d7192013-10-04 19:53:11 +010051 int break_label;
52 int continue_label;
Damien Georgecbddb272014-02-01 20:08:18 +000053 int break_continue_except_level;
54 int cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
Damien429d7192013-10-04 19:53:11 +010055
56 int n_arg_keyword;
57 bool have_star_arg;
58 bool have_dbl_star_arg;
59 bool have_bare_star;
60 int param_pass;
61 int param_pass_num_dict_params;
62 int param_pass_num_default_params;
63
Damien George35e2a4e2014-02-05 00:51:47 +000064 bool func_arg_is_super; // used to compile special case of super() function call
65
Damien429d7192013-10-04 19:53:11 +010066 scope_t *scope_head;
67 scope_t *scope_cur;
68
Damien6cdd3af2013-10-05 18:08:26 +010069 emit_t *emit; // current emitter
70 const emit_method_table_t *emit_method_table; // current emit method table
Damien826005c2013-10-05 23:17:28 +010071
72 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
73 const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
Damien429d7192013-10-04 19:53:11 +010074} compiler_t;
75
Damien Georgef41fdd02014-03-03 23:19:11 +000076STATIC void compile_syntax_error(compiler_t *comp, const char *msg) {
77 // TODO store the error message to a variable in compiler_t instead of printing it
78 printf("SyntaxError: %s\n", msg);
79 comp->had_error = true;
80}
81
Damiend99b0522013-12-21 18:17:45 +000082mp_parse_node_t fold_constants(mp_parse_node_t pn) {
83 if (MP_PARSE_NODE_IS_STRUCT(pn)) {
84 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
85 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +010086
87 // fold arguments first
88 for (int i = 0; i < n; i++) {
89 pns->nodes[i] = fold_constants(pns->nodes[i]);
90 }
91
Damiend99b0522013-12-21 18:17:45 +000092 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +010093 case PN_shift_expr:
Damiend99b0522013-12-21 18:17:45 +000094 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 +020095 int arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
96 int arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damiend99b0522013-12-21 18:17:45 +000097 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
Damien3ef4abb2013-10-12 16:53:13 +010098#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +010099 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000100 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
Damien0efb3a12013-10-12 16:16:56 +0100101#endif
Damiend99b0522013-12-21 18:17:45 +0000102 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
103 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien429d7192013-10-04 19:53:11 +0100104 } else {
105 // shouldn't happen
106 assert(0);
107 }
108 }
109 break;
110
111 case PN_arith_expr:
Damien0efb3a12013-10-12 16:16:56 +0100112 // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
Damiend99b0522013-12-21 18:17:45 +0000113 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 +0200114 machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
115 machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damien0efb3a12013-10-12 16:16:56 +0100116 machine_int_t res;
Damiend99b0522013-12-21 18:17:45 +0000117 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100118 res = arg0 + arg1;
Damiend99b0522013-12-21 18:17:45 +0000119 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
Damien0efb3a12013-10-12 16:16:56 +0100120 res = arg0 - arg1;
Damien429d7192013-10-04 19:53:11 +0100121 } else {
122 // shouldn't happen
123 assert(0);
Damien0efb3a12013-10-12 16:16:56 +0100124 res = 0;
125 }
Paul Sokolovskybbf0e2f2014-02-21 02:04:32 +0200126 if (MP_PARSE_FITS_SMALL_INT(res)) {
Damiend99b0522013-12-21 18:17:45 +0000127 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, res);
Damien429d7192013-10-04 19:53:11 +0100128 }
129 }
130 break;
131
132 case PN_term:
Damiend99b0522013-12-21 18:17:45 +0000133 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 +0200134 int arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
135 int arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
Damiend99b0522013-12-21 18:17:45 +0000136 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien3ef4abb2013-10-12 16:53:13 +0100137#if MICROPY_EMIT_CPYTHON
Damien0efb3a12013-10-12 16:16:56 +0100138 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000139 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 * arg1);
Damien0efb3a12013-10-12 16:16:56 +0100140#endif
Damiend99b0522013-12-21 18:17:45 +0000141 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien429d7192013-10-04 19:53:11 +0100142 ; // pass
Damiend99b0522013-12-21 18:17:45 +0000143 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
Damien0efb3a12013-10-12 16:16:56 +0100144 // XXX implement this properly as Python's % operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000145 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 % arg1);
146 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
Damien0efb3a12013-10-12 16:16:56 +0100147 // XXX implement this properly as Python's // operator acts differently to C's
Damiend99b0522013-12-21 18:17:45 +0000148 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 / arg1);
Damien429d7192013-10-04 19:53:11 +0100149 } else {
150 // shouldn't happen
151 assert(0);
152 }
153 }
154 break;
155
156 case PN_factor_2:
Damiend99b0522013-12-21 18:17:45 +0000157 if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200158 machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +0000159 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
160 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
161 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
162 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
163 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
164 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien429d7192013-10-04 19:53:11 +0100165 } else {
166 // shouldn't happen
167 assert(0);
168 }
169 }
170 break;
171
Damien3ef4abb2013-10-12 16:53:13 +0100172#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +0100173 case PN_power:
Damien0efb3a12013-10-12 16:16:56 +0100174 // can overflow; enabled only to compare with CPython
Damiend99b0522013-12-21 18:17:45 +0000175 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])) {
176 mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
177 if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200178 int power = MP_PARSE_NODE_LEAF_SMALL_INT(pns2->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100179 if (power >= 0) {
180 int ans = 1;
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200181 int base = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +0100182 for (; power > 0; power--) {
183 ans *= base;
184 }
Damiend99b0522013-12-21 18:17:45 +0000185 pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien429d7192013-10-04 19:53:11 +0100186 }
187 }
188 }
189 break;
Damien0efb3a12013-10-12 16:16:56 +0100190#endif
Damien429d7192013-10-04 19:53:11 +0100191 }
192 }
193
194 return pn;
195}
196
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200197STATIC 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 +0000198void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100199
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200200STATIC int comp_next_label(compiler_t *comp) {
Damienb05d7072013-10-05 13:37:10 +0100201 return comp->next_label++;
202}
203
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200204STATIC 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 +0000205 scope_t *scope = scope_new(kind, pn, comp->source_file, rt_get_unique_code_id(), emit_options);
Damien429d7192013-10-04 19:53:11 +0100206 scope->parent = comp->scope_cur;
207 scope->next = NULL;
208 if (comp->scope_head == NULL) {
209 comp->scope_head = scope;
210 } else {
211 scope_t *s = comp->scope_head;
212 while (s->next != NULL) {
213 s = s->next;
214 }
215 s->next = scope;
216 }
217 return scope;
218}
219
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200220STATIC int list_len(mp_parse_node_t pn, int pn_kind) {
Damiend99b0522013-12-21 18:17:45 +0000221 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100222 return 0;
Damiend99b0522013-12-21 18:17:45 +0000223 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100224 return 1;
225 } else {
Damiend99b0522013-12-21 18:17:45 +0000226 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
227 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100228 return 1;
229 } else {
Damiend99b0522013-12-21 18:17:45 +0000230 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100231 }
232 }
233}
234
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200235STATIC 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 +0000236 if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
237 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
238 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100239 for (int i = 0; i < num_nodes; i++) {
240 f(comp, pns->nodes[i]);
241 }
Damiend99b0522013-12-21 18:17:45 +0000242 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100243 f(comp, pn);
244 }
245}
246
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200247STATIC int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
Damiend99b0522013-12-21 18:17:45 +0000248 if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100249 *nodes = NULL;
250 return 0;
Damiend99b0522013-12-21 18:17:45 +0000251 } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien429d7192013-10-04 19:53:11 +0100252 *nodes = pn;
253 return 1;
254 } else {
Damiend99b0522013-12-21 18:17:45 +0000255 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
256 if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien429d7192013-10-04 19:53:11 +0100257 *nodes = pn;
258 return 1;
259 } else {
260 *nodes = pns->nodes;
Damiend99b0522013-12-21 18:17:45 +0000261 return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100262 }
263 }
264}
265
Damiend99b0522013-12-21 18:17:45 +0000266void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100267}
268
Damiend99b0522013-12-21 18:17:45 +0000269void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
270 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100271 for (int i = 0; i < num_nodes; i++) {
272 compile_node(comp, pns->nodes[i]);
273 }
274}
275
Damien3ef4abb2013-10-12 16:53:13 +0100276#if MICROPY_EMIT_CPYTHON
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200277STATIC bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000278 if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien429d7192013-10-04 19:53:11 +0100279 return false;
280 }
Damiend99b0522013-12-21 18:17:45 +0000281 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +0100282 return false;
283 }
284 return true;
285}
286
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200287STATIC void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
Damien George55baff42014-01-21 21:40:13 +0000288 uint len;
289 const byte *str = qstr_data(qstr, &len);
Damien02f89412013-12-12 15:13:36 +0000290 bool has_single_quote = false;
291 bool has_double_quote = false;
292 for (int i = 0; i < len; i++) {
293 if (str[i] == '\'') {
294 has_single_quote = true;
295 } else if (str[i] == '"') {
296 has_double_quote = true;
297 }
298 }
299 if (bytes) {
300 vstr_printf(vstr, "b");
301 }
302 bool quote_single = false;
303 if (has_single_quote && !has_double_quote) {
304 vstr_printf(vstr, "\"");
305 } else {
306 quote_single = true;
307 vstr_printf(vstr, "'");
308 }
309 for (int i = 0; i < len; i++) {
310 if (str[i] == '\n') {
311 vstr_printf(vstr, "\\n");
312 } else if (str[i] == '\\') {
313 vstr_printf(vstr, "\\\\");
314 } else if (str[i] == '\'' && quote_single) {
315 vstr_printf(vstr, "\\'");
316 } else {
317 vstr_printf(vstr, "%c", str[i]);
318 }
319 }
320 if (has_single_quote && !has_double_quote) {
321 vstr_printf(vstr, "\"");
322 } else {
323 vstr_printf(vstr, "'");
324 }
325}
326
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200327STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
Damiend99b0522013-12-21 18:17:45 +0000328 assert(MP_PARSE_NODE_IS_LEAF(pn));
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200329 if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
330 vstr_printf(vstr, INT_FMT, MP_PARSE_NODE_LEAF_SMALL_INT(pn));
331 return;
332 }
333
Damiend99b0522013-12-21 18:17:45 +0000334 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
335 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
336 case MP_PARSE_NODE_ID: assert(0);
Damiend99b0522013-12-21 18:17:45 +0000337 case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
338 case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
339 case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
340 case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
341 case MP_PARSE_NODE_TOKEN:
Damien429d7192013-10-04 19:53:11 +0100342 switch (arg) {
Damiend99b0522013-12-21 18:17:45 +0000343 case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
344 case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
345 case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
Damien429d7192013-10-04 19:53:11 +0100346 default: assert(0);
347 }
348 break;
349 default: assert(0);
350 }
351}
352
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200353STATIC 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 +0100354 int n = 0;
355 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000356 n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien429d7192013-10-04 19:53:11 +0100357 }
358 int total = n;
359 bool is_const = true;
Damiend99b0522013-12-21 18:17:45 +0000360 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100361 total += 1;
Damien3a205172013-10-12 15:01:56 +0100362 if (!cpython_c_tuple_is_const(pn)) {
Damien429d7192013-10-04 19:53:11 +0100363 is_const = false;
364 }
365 }
366 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100367 if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien429d7192013-10-04 19:53:11 +0100368 is_const = false;
369 break;
370 }
371 }
372 if (total > 0 && is_const) {
373 bool need_comma = false;
Damien02f89412013-12-12 15:13:36 +0000374 vstr_t *vstr = vstr_new();
375 vstr_printf(vstr, "(");
Damiend99b0522013-12-21 18:17:45 +0000376 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien02f89412013-12-12 15:13:36 +0000377 cpython_c_tuple_emit_const(comp, pn, vstr);
Damien429d7192013-10-04 19:53:11 +0100378 need_comma = true;
379 }
380 for (int i = 0; i < n; i++) {
381 if (need_comma) {
Damien02f89412013-12-12 15:13:36 +0000382 vstr_printf(vstr, ", ");
Damien429d7192013-10-04 19:53:11 +0100383 }
Damien02f89412013-12-12 15:13:36 +0000384 cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien429d7192013-10-04 19:53:11 +0100385 need_comma = true;
386 }
387 if (total == 1) {
Damien02f89412013-12-12 15:13:36 +0000388 vstr_printf(vstr, ",)");
Damien429d7192013-10-04 19:53:11 +0100389 } else {
Damien02f89412013-12-12 15:13:36 +0000390 vstr_printf(vstr, ")");
Damien429d7192013-10-04 19:53:11 +0100391 }
Damien Georgeb9791222014-01-23 00:34:21 +0000392 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +0000393 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +0100394 } else {
Damiend99b0522013-12-21 18:17:45 +0000395 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100396 compile_node(comp, pn);
397 }
398 for (int i = 0; i < n; i++) {
399 compile_node(comp, pns_list->nodes[i]);
400 }
Damien Georgeb9791222014-01-23 00:34:21 +0000401 EMIT_ARG(build_tuple, total);
Damien429d7192013-10-04 19:53:11 +0100402 }
403}
Damien3a205172013-10-12 15:01:56 +0100404#endif
405
406// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
Damiend99b0522013-12-21 18:17:45 +0000407void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3ef4abb2013-10-12 16:53:13 +0100408#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100409 cpython_c_tuple(comp, pn, pns_list);
410#else
411 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000412 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100413 compile_node(comp, pn);
414 total += 1;
415 }
416 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000417 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100418 for (int i = 0; i < n; i++) {
419 compile_node(comp, pns_list->nodes[i]);
420 }
421 total += n;
422 }
Damien Georgeb9791222014-01-23 00:34:21 +0000423 EMIT_ARG(build_tuple, total);
Damien3a205172013-10-12 15:01:56 +0100424#endif
425}
Damien429d7192013-10-04 19:53:11 +0100426
Damiend99b0522013-12-21 18:17:45 +0000427void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100428 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000429 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100430}
431
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200432STATIC bool node_is_const_false(mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000433 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200434 // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
Damien429d7192013-10-04 19:53:11 +0100435}
436
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200437STATIC bool node_is_const_true(mp_parse_node_t pn) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +0200438 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 +0100439}
440
Damien3ef4abb2013-10-12 16:53:13 +0100441#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100442// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200443STATIC 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 +0100444 if (node_is_const_false(pn)) {
445 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000446 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100447 }
448 return;
449 } else if (node_is_const_true(pn)) {
450 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000451 EMIT_ARG(jump, label);
Damien429d7192013-10-04 19:53:11 +0100452 }
453 return;
Damiend99b0522013-12-21 18:17:45 +0000454 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
455 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
456 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
457 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien429d7192013-10-04 19:53:11 +0100458 if (jump_if == false) {
Damienb05d7072013-10-05 13:37:10 +0100459 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100460 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100461 cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien429d7192013-10-04 19:53:11 +0100462 }
Damien3a205172013-10-12 15:01:56 +0100463 cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000464 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100465 } else {
466 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100467 cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien429d7192013-10-04 19:53:11 +0100468 }
469 }
470 return;
Damiend99b0522013-12-21 18:17:45 +0000471 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien429d7192013-10-04 19:53:11 +0100472 if (jump_if == false) {
473 for (int i = 0; i < n; i++) {
Damien3a205172013-10-12 15:01:56 +0100474 cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien429d7192013-10-04 19:53:11 +0100475 }
476 } else {
Damienb05d7072013-10-05 13:37:10 +0100477 int label2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100478 for (int i = 0; i < n - 1; i++) {
Damien3a205172013-10-12 15:01:56 +0100479 cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien429d7192013-10-04 19:53:11 +0100480 }
Damien3a205172013-10-12 15:01:56 +0100481 cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
Damien Georgeb9791222014-01-23 00:34:21 +0000482 EMIT_ARG(label_assign, label2);
Damien429d7192013-10-04 19:53:11 +0100483 }
484 return;
Damiend99b0522013-12-21 18:17:45 +0000485 } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100486 cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien429d7192013-10-04 19:53:11 +0100487 return;
488 }
489 }
490
491 // nothing special, fall back to default compiling for node and jump
492 compile_node(comp, pn);
493 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000494 EMIT_ARG(pop_jump_if_false, label);
Damien429d7192013-10-04 19:53:11 +0100495 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000496 EMIT_ARG(pop_jump_if_true, label);
Damien429d7192013-10-04 19:53:11 +0100497 }
498}
Damien3a205172013-10-12 15:01:56 +0100499#endif
Damien429d7192013-10-04 19:53:11 +0100500
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200501STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien3ef4abb2013-10-12 16:53:13 +0100502#if MICROPY_EMIT_CPYTHON
Damien3a205172013-10-12 15:01:56 +0100503 cpython_c_if_cond(comp, pn, jump_if, label, false);
504#else
505 if (node_is_const_false(pn)) {
506 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000507 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100508 }
509 return;
510 } else if (node_is_const_true(pn)) {
511 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000512 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100513 }
514 return;
Damiend99b0522013-12-21 18:17:45 +0000515 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
516 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
517 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
518 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100519 if (jump_if == false) {
520 int label2 = comp_next_label(comp);
521 for (int i = 0; i < n - 1; i++) {
522 c_if_cond(comp, pns->nodes[i], true, label2);
523 }
524 c_if_cond(comp, pns->nodes[n - 1], false, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000525 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100526 } else {
527 for (int i = 0; i < n; i++) {
528 c_if_cond(comp, pns->nodes[i], true, label);
529 }
530 }
531 return;
Damiend99b0522013-12-21 18:17:45 +0000532 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100533 if (jump_if == false) {
534 for (int i = 0; i < n; i++) {
535 c_if_cond(comp, pns->nodes[i], false, label);
536 }
537 } else {
538 int label2 = comp_next_label(comp);
539 for (int i = 0; i < n - 1; i++) {
540 c_if_cond(comp, pns->nodes[i], false, label2);
541 }
542 c_if_cond(comp, pns->nodes[n - 1], true, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000543 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100544 }
545 return;
Damiend99b0522013-12-21 18:17:45 +0000546 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100547 c_if_cond(comp, pns->nodes[0], !jump_if, label);
548 return;
549 }
550 }
551
552 // nothing special, fall back to default compiling for node and jump
553 compile_node(comp, pn);
554 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000555 EMIT_ARG(pop_jump_if_false, label);
Damien3a205172013-10-12 15:01:56 +0100556 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000557 EMIT_ARG(pop_jump_if_true, label);
Damien3a205172013-10-12 15:01:56 +0100558 }
559#endif
Damien429d7192013-10-04 19:53:11 +0100560}
561
562typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damiend99b0522013-12-21 18:17:45 +0000563void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100564
Damiend99b0522013-12-21 18:17:45 +0000565void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100566 if (assign_kind != ASSIGN_AUG_STORE) {
567 compile_node(comp, pns->nodes[0]);
568 }
569
Damiend99b0522013-12-21 18:17:45 +0000570 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
571 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
572 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
573 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100574 if (assign_kind != ASSIGN_AUG_STORE) {
575 for (int i = 0; i < n - 1; i++) {
576 compile_node(comp, pns1->nodes[i]);
577 }
578 }
Damiend99b0522013-12-21 18:17:45 +0000579 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
580 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100581 }
Damiend99b0522013-12-21 18:17:45 +0000582 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000583 compile_syntax_error(comp, "can't assign to function call");
Damien429d7192013-10-04 19:53:11 +0100584 return;
Damiend99b0522013-12-21 18:17:45 +0000585 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100586 if (assign_kind == ASSIGN_AUG_STORE) {
587 EMIT(rot_three);
588 EMIT(store_subscr);
589 } else {
590 compile_node(comp, pns1->nodes[0]);
591 if (assign_kind == ASSIGN_AUG_LOAD) {
592 EMIT(dup_top_two);
Damien Georgeb9791222014-01-23 00:34:21 +0000593 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +0100594 } else {
595 EMIT(store_subscr);
596 }
597 }
Damiend99b0522013-12-21 18:17:45 +0000598 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
599 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100600 if (assign_kind == ASSIGN_AUG_LOAD) {
601 EMIT(dup_top);
Damien Georgeb9791222014-01-23 00:34:21 +0000602 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100603 } else {
604 if (assign_kind == ASSIGN_AUG_STORE) {
605 EMIT(rot_two);
606 }
Damien Georgeb9791222014-01-23 00:34:21 +0000607 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100608 }
609 } else {
610 // shouldn't happen
611 assert(0);
612 }
613 } else {
614 // shouldn't happen
615 assert(0);
616 }
617
Damiend99b0522013-12-21 18:17:45 +0000618 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +0100619 // SyntaxError, cannot assign
620 assert(0);
621 }
622}
623
Damiend99b0522013-12-21 18:17:45 +0000624void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
Damien429d7192013-10-04 19:53:11 +0100625 assert(n >= 0);
626 int have_star_index = -1;
627 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000628 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_star_expr)) {
Damien429d7192013-10-04 19:53:11 +0100629 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000630 EMIT_ARG(unpack_ex, i, n - i - 1);
Damien429d7192013-10-04 19:53:11 +0100631 have_star_index = i;
632 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000633 compile_syntax_error(comp, "two starred expressions in assignment");
Damien429d7192013-10-04 19:53:11 +0100634 return;
635 }
636 }
637 }
638 if (have_star_index < 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000639 EMIT_ARG(unpack_sequence, n);
Damien429d7192013-10-04 19:53:11 +0100640 }
641 for (int i = 0; i < n; i++) {
642 if (i == have_star_index) {
Damiend99b0522013-12-21 18:17:45 +0000643 c_assign(comp, ((mp_parse_node_struct_t*)nodes[i])->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100644 } else {
645 c_assign(comp, nodes[i], ASSIGN_STORE);
646 }
647 }
648}
649
650// assigns top of stack to pn
Damiend99b0522013-12-21 18:17:45 +0000651void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100652 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +0000653 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100654 assert(0);
Damiend99b0522013-12-21 18:17:45 +0000655 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
656 if (MP_PARSE_NODE_IS_ID(pn)) {
657 int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100658 switch (assign_kind) {
659 case ASSIGN_STORE:
660 case ASSIGN_AUG_STORE:
Damien Georgeb9791222014-01-23 00:34:21 +0000661 EMIT_ARG(store_id, arg);
Damien429d7192013-10-04 19:53:11 +0100662 break;
663 case ASSIGN_AUG_LOAD:
Damien Georgeb9791222014-01-23 00:34:21 +0000664 EMIT_ARG(load_id, arg);
Damien429d7192013-10-04 19:53:11 +0100665 break;
666 }
667 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000668 compile_syntax_error(comp, "can't assign to literal");
Damien429d7192013-10-04 19:53:11 +0100669 return;
670 }
671 } else {
Damiend99b0522013-12-21 18:17:45 +0000672 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
673 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien429d7192013-10-04 19:53:11 +0100674 case PN_power:
675 // lhs is an index or attribute
676 c_assign_power(comp, pns, assign_kind);
677 break;
678
679 case PN_testlist_star_expr:
680 case PN_exprlist:
681 // lhs is a tuple
682 if (assign_kind != ASSIGN_STORE) {
683 goto bad_aug;
684 }
Damiend99b0522013-12-21 18:17:45 +0000685 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100686 break;
687
688 case PN_atom_paren:
689 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000690 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100691 // empty tuple
Damien Georgef41fdd02014-03-03 23:19:11 +0000692 compile_syntax_error(comp, "can't assign to ()");
Damien429d7192013-10-04 19:53:11 +0100693 return;
Damiend99b0522013-12-21 18:17:45 +0000694 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
695 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100696 goto testlist_comp;
697 } else {
698 // parenthesis around 1 item, is just that item
699 pn = pns->nodes[0];
700 goto tail_recursion;
701 }
702 break;
703
704 case PN_atom_bracket:
705 // lhs is something in brackets
706 if (assign_kind != ASSIGN_STORE) {
707 goto bad_aug;
708 }
Damiend99b0522013-12-21 18:17:45 +0000709 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100710 // empty list, assignment allowed
711 c_assign_tuple(comp, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000712 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
713 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100714 goto testlist_comp;
715 } else {
716 // brackets around 1 item
717 c_assign_tuple(comp, 1, &pns->nodes[0]);
718 }
719 break;
720
721 default:
Damiend99b0522013-12-21 18:17:45 +0000722 printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien429d7192013-10-04 19:53:11 +0100723 assert(0);
724 }
725 return;
726
727 testlist_comp:
728 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000729 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
730 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
731 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100732 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000733 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100734 c_assign_tuple(comp, 1, &pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000735 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100736 // sequence of many items
737 // TODO call c_assign_tuple instead
Damiend99b0522013-12-21 18:17:45 +0000738 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
Damien Georgeb9791222014-01-23 00:34:21 +0000739 EMIT_ARG(unpack_sequence, 1 + n);
Damien429d7192013-10-04 19:53:11 +0100740 c_assign(comp, pns->nodes[0], ASSIGN_STORE);
741 for (int i = 0; i < n; i++) {
742 c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
743 }
Damiend99b0522013-12-21 18:17:45 +0000744 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +0100745 // TODO not implemented
746 assert(0);
747 } else {
748 // sequence with 2 items
749 goto sequence_with_2_items;
750 }
751 } else {
752 // sequence with 2 items
753 sequence_with_2_items:
754 c_assign_tuple(comp, 2, pns->nodes);
755 }
756 return;
757 }
758 return;
759
760 bad_aug:
Damien Georgef41fdd02014-03-03 23:19:11 +0000761 compile_syntax_error(comp, "illegal expression for augmented assignment");
Damien429d7192013-10-04 19:53:11 +0100762}
763
764// stuff for lambda and comprehensions and generators
765void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_params, int n_default_params) {
766 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000767 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100768 int nfree = 0;
769 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000770 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
771 id_info_t *id = &comp->scope_cur->id_info[i];
772 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
773 for (int j = 0; j < this_scope->id_info_len; j++) {
774 id_info_t *id2 = &this_scope->id_info[j];
775 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +0000776#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +0000777 EMIT_ARG(load_closure, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000778#else
779 // in Micro Python we load closures using LOAD_FAST
Damien Georgeb9791222014-01-23 00:34:21 +0000780 EMIT_ARG(load_fast, id->qstr, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +0000781#endif
Damien318aec62013-12-10 18:28:17 +0000782 nfree += 1;
783 }
784 }
Damien429d7192013-10-04 19:53:11 +0100785 }
786 }
787 }
788 if (nfree > 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000789 EMIT_ARG(build_tuple, nfree);
Damien429d7192013-10-04 19:53:11 +0100790 }
791
792 // make the function/closure
793 if (nfree == 0) {
Damien Georgeb9791222014-01-23 00:34:21 +0000794 EMIT_ARG(make_function, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100795 } else {
Damien Georgeb9791222014-01-23 00:34:21 +0000796 EMIT_ARG(make_closure, this_scope, n_dict_params, n_default_params);
Damien429d7192013-10-04 19:53:11 +0100797 }
798}
799
Damiend99b0522013-12-21 18:17:45 +0000800void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000801 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
Damiend99b0522013-12-21 18:17:45 +0000802 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
803 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100804 // bare star
805 comp->have_bare_star = true;
806 }
Damien Georgef41fdd02014-03-03 23:19:11 +0000807
808 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)) {
809 // TODO do we need to do anything with this?
810
811 } else {
812 mp_parse_node_t pn_id;
813 mp_parse_node_t pn_colon;
814 mp_parse_node_t pn_equal;
815 if (MP_PARSE_NODE_IS_ID(pn)) {
816 // this parameter is just an id
817
818 pn_id = pn;
819 pn_colon = MP_PARSE_NODE_NULL;
820 pn_equal = MP_PARSE_NODE_NULL;
821
822 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
823 // this parameter has a colon and/or equal specifier
824
825 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
826 pn_id = pns->nodes[0];
827 pn_colon = pns->nodes[1];
828 pn_equal = pns->nodes[2];
829
830 } else {
831 assert(0);
832 return;
833 }
834
835 if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
836 // this parameter does not have a default value
837
838 // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
839 if (!comp->have_bare_star && comp->param_pass_num_default_params != 0) {
840 compile_syntax_error(comp, "non-default argument follows default argument");
841 return;
842 }
843
844 } else {
845 // this parameter has a default value
846 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
847
848 if (comp->have_bare_star) {
849 comp->param_pass_num_dict_params += 1;
850 if (comp->param_pass == 1) {
851 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pn_id));
852 compile_node(comp, pn_equal);
853 }
854 } else {
855 comp->param_pass_num_default_params += 1;
856 if (comp->param_pass == 2) {
857 compile_node(comp, pn_equal);
858 }
859 }
860 }
861
862 // TODO pn_colon not implemented
863 (void)pn_colon;
Damien429d7192013-10-04 19:53:11 +0100864 }
865}
866
867// leaves function object on stack
868// returns function name
Damiend99b0522013-12-21 18:17:45 +0000869qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100870 if (comp->pass == PASS_1) {
871 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000872 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100873 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000874 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100875 }
876
877 // save variables (probably don't need to do this, since we can't have nested definitions..?)
878 bool old_have_bare_star = comp->have_bare_star;
879 int old_param_pass = comp->param_pass;
880 int old_param_pass_num_dict_params = comp->param_pass_num_dict_params;
881 int old_param_pass_num_default_params = comp->param_pass_num_default_params;
882
883 // compile default parameters
Damien Georgef41fdd02014-03-03 23:19:11 +0000884
885 // pass 1 does any default parameters after bare star
Damien429d7192013-10-04 19:53:11 +0100886 comp->have_bare_star = false;
Damien Georgef41fdd02014-03-03 23:19:11 +0000887 comp->param_pass = 1;
Damien429d7192013-10-04 19:53:11 +0100888 comp->param_pass_num_dict_params = 0;
889 comp->param_pass_num_default_params = 0;
890 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
Damien Georgef41fdd02014-03-03 23:19:11 +0000891
892 if (comp->had_error) {
893 return MP_QSTR_NULL;
894 }
895
896 // pass 2 does any default parameters before bare star
Damien429d7192013-10-04 19:53:11 +0100897 comp->have_bare_star = false;
Damien Georgef41fdd02014-03-03 23:19:11 +0000898 comp->param_pass = 2;
Damien429d7192013-10-04 19:53:11 +0100899 comp->param_pass_num_dict_params = 0;
900 comp->param_pass_num_default_params = 0;
901 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
902
903 // get the scope for this function
904 scope_t *fscope = (scope_t*)pns->nodes[4];
905
906 // make the function
907 close_over_variables_etc(comp, fscope, comp->param_pass_num_dict_params, comp->param_pass_num_default_params);
908
909 // restore variables
910 comp->have_bare_star = old_have_bare_star;
911 comp->param_pass = old_param_pass;
912 comp->param_pass_num_dict_params = old_param_pass_num_dict_params;
913 comp->param_pass_num_default_params = old_param_pass_num_default_params;
914
915 // return its name (the 'f' in "def f(...):")
916 return fscope->simple_name;
917}
918
919// leaves class object on stack
920// returns class name
Damiend99b0522013-12-21 18:17:45 +0000921qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien429d7192013-10-04 19:53:11 +0100922 if (comp->pass == PASS_1) {
923 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000924 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100925 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000926 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100927 }
928
929 EMIT(load_build_class);
930
931 // scope for this class
932 scope_t *cscope = (scope_t*)pns->nodes[3];
933
934 // compile the class
935 close_over_variables_etc(comp, cscope, 0, 0);
936
937 // get its name
Damien Georgeb9791222014-01-23 00:34:21 +0000938 EMIT_ARG(load_const_id, cscope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100939
940 // nodes[1] has parent classes, if any
Damien Georgebbcd49a2014-02-06 20:30:16 +0000941 comp->func_arg_is_super = false;
942 compile_trailer_paren_helper(comp, pns->nodes[1], false, 2);
Damien429d7192013-10-04 19:53:11 +0100943
944 // return its name (the 'C' in class C(...):")
945 return cscope->simple_name;
946}
947
Damien6cdd3af2013-10-05 18:08:26 +0100948// returns true if it was a built-in decorator (even if the built-in had an error)
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200949STATIC 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 +0000950 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100951 return false;
952 }
953
954 if (name_len != 2) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000955 compile_syntax_error(comp, "invalid micropython decorator");
Damien6cdd3af2013-10-05 18:08:26 +0100956 return true;
957 }
958
Damiend99b0522013-12-21 18:17:45 +0000959 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000960 if (attr == MP_QSTR_byte_code) {
Damien5ac1b2e2013-10-18 19:58:12 +0100961 *emit_options = EMIT_OPT_BYTE_CODE;
Damience89a212013-10-15 22:25:17 +0100962#if MICROPY_EMIT_NATIVE
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000963 } else if (attr == MP_QSTR_native) {
Damien6cdd3af2013-10-05 18:08:26 +0100964 *emit_options = EMIT_OPT_NATIVE_PYTHON;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000965 } else if (attr == MP_QSTR_viper) {
Damien7af3d192013-10-07 00:02:49 +0100966 *emit_options = EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100967#endif
Damien3ef4abb2013-10-12 16:53:13 +0100968#if MICROPY_EMIT_INLINE_THUMB
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000969 } else if (attr == MP_QSTR_asm_thumb) {
Damien5bfb7592013-10-05 18:41:24 +0100970 *emit_options = EMIT_OPT_ASM_THUMB;
Damienc025ebb2013-10-12 14:30:21 +0100971#endif
Damien6cdd3af2013-10-05 18:08:26 +0100972 } else {
Damien Georgef41fdd02014-03-03 23:19:11 +0000973 compile_syntax_error(comp, "invalid micropython decorator");
Damien6cdd3af2013-10-05 18:08:26 +0100974 }
975
976 return true;
977}
978
Damiend99b0522013-12-21 18:17:45 +0000979void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100980 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000981 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +0100982 int n = list_get(&pns->nodes[0], PN_decorators, &nodes);
983
Damien6cdd3af2013-10-05 18:08:26 +0100984 // inherit emit options for this function/class definition
985 uint emit_options = comp->scope_cur->emit_options;
986
987 // compile each decorator
988 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100989 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000990 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
991 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100992
993 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +0000994 mp_parse_node_t *name_nodes;
Damien6cdd3af2013-10-05 18:08:26 +0100995 int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
996
997 // check for built-in decorators
998 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
999 // this was a built-in
1000 num_built_in_decorators += 1;
1001
1002 } else {
1003 // not a built-in, compile normally
1004
1005 // compile the decorator function
1006 compile_node(comp, name_nodes[0]);
1007 for (int i = 1; i < name_len; i++) {
Damiend99b0522013-12-21 18:17:45 +00001008 assert(MP_PARSE_NODE_IS_ID(name_nodes[i])); // should be
Damien Georgeb9791222014-01-23 00:34:21 +00001009 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[i]));
Damien6cdd3af2013-10-05 18:08:26 +01001010 }
1011
1012 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +00001013 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +01001014 // call the decorator function with the arguments in nodes[1]
Damien George35e2a4e2014-02-05 00:51:47 +00001015 comp->func_arg_is_super = false;
Damien6cdd3af2013-10-05 18:08:26 +01001016 compile_node(comp, pns_decorator->nodes[1]);
1017 }
Damien429d7192013-10-04 19:53:11 +01001018 }
1019 }
1020
1021 // compile the body (funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +00001022 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001023 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +00001024 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +01001025 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Damiend99b0522013-12-21 18:17:45 +00001026 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) {
Damien6cdd3af2013-10-05 18:08:26 +01001027 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +01001028 } else {
1029 // shouldn't happen
1030 assert(0);
1031 }
1032
1033 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +01001034 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001035 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001036 }
1037
1038 // store func/class object into name
Damien Georgeb9791222014-01-23 00:34:21 +00001039 EMIT_ARG(store_id, body_name);
Damien429d7192013-10-04 19:53:11 +01001040}
1041
Damiend99b0522013-12-21 18:17:45 +00001042void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01001043 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01001044 // store function object into function name
Damien Georgeb9791222014-01-23 00:34:21 +00001045 EMIT_ARG(store_id, fname);
Damien429d7192013-10-04 19:53:11 +01001046}
1047
Damiend99b0522013-12-21 18:17:45 +00001048void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
1049 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001050 EMIT_ARG(delete_id, MP_PARSE_NODE_LEAF_ARG(pn));
Damiend99b0522013-12-21 18:17:45 +00001051 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
1052 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001053
1054 compile_node(comp, pns->nodes[0]); // base of the power node
1055
Damiend99b0522013-12-21 18:17:45 +00001056 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1057 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1058 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
1059 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001060 for (int i = 0; i < n - 1; i++) {
1061 compile_node(comp, pns1->nodes[i]);
1062 }
Damiend99b0522013-12-21 18:17:45 +00001063 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
1064 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +01001065 }
Damiend99b0522013-12-21 18:17:45 +00001066 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
Damien429d7192013-10-04 19:53:11 +01001067 // SyntaxError: can't delete a function call
1068 assert(0);
Damiend99b0522013-12-21 18:17:45 +00001069 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +01001070 compile_node(comp, pns1->nodes[0]);
1071 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +00001072 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
1073 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien Georgeb9791222014-01-23 00:34:21 +00001074 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001075 } else {
1076 // shouldn't happen
1077 assert(0);
1078 }
1079 } else {
1080 // shouldn't happen
1081 assert(0);
1082 }
1083
Damiend99b0522013-12-21 18:17:45 +00001084 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001085 // SyntaxError, cannot delete
1086 assert(0);
1087 }
Damiend99b0522013-12-21 18:17:45 +00001088 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
1089 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
1090 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp)) {
1091 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001092 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
1093
Damiend99b0522013-12-21 18:17:45 +00001094 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1095 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1096 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01001097 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00001098 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01001099 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00001100 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01001101 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +00001102 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +01001103 c_del_stmt(comp, pns->nodes[0]);
1104 for (int i = 0; i < n; i++) {
1105 c_del_stmt(comp, pns1->nodes[i]);
1106 }
Damiend99b0522013-12-21 18:17:45 +00001107 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01001108 // TODO not implemented; can't del comprehension?
1109 assert(0);
1110 } else {
1111 // sequence with 2 items
1112 goto sequence_with_2_items;
1113 }
1114 } else {
1115 // sequence with 2 items
1116 sequence_with_2_items:
1117 c_del_stmt(comp, pns->nodes[0]);
1118 c_del_stmt(comp, pns->nodes[1]);
1119 }
1120 } else {
1121 // tuple with 1 element
1122 c_del_stmt(comp, pn);
1123 }
1124 } else {
1125 // not implemented
1126 assert(0);
1127 }
1128}
1129
Damiend99b0522013-12-21 18:17:45 +00001130void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001131 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
1132}
1133
Damiend99b0522013-12-21 18:17:45 +00001134void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001135 if (comp->break_label == 0) {
1136 printf("ERROR: cannot break from here\n");
1137 }
Damien Georgecbddb272014-02-01 20:08:18 +00001138 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001139}
1140
Damiend99b0522013-12-21 18:17:45 +00001141void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001142 if (comp->continue_label == 0) {
1143 printf("ERROR: cannot continue from here\n");
1144 }
Damien Georgecbddb272014-02-01 20:08:18 +00001145 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +01001146}
1147
Damiend99b0522013-12-21 18:17:45 +00001148void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +01001149 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
Damien Georgef41fdd02014-03-03 23:19:11 +00001150 compile_syntax_error(comp, "'return' outside function");
Damien5ac1b2e2013-10-18 19:58:12 +01001151 return;
1152 }
Damiend99b0522013-12-21 18:17:45 +00001153 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001154 // no argument to 'return', so return None
Damien Georgeb9791222014-01-23 00:34:21 +00001155 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damiend99b0522013-12-21 18:17:45 +00001156 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +01001157 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +00001158 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
1159 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 +01001160
Damienb05d7072013-10-05 13:37:10 +01001161 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001162 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1163 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
1164 EMIT(return_value);
Damien Georgeb9791222014-01-23 00:34:21 +00001165 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001166 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
1167 } else {
1168 compile_node(comp, pns->nodes[0]);
1169 }
1170 EMIT(return_value);
1171}
1172
Damiend99b0522013-12-21 18:17:45 +00001173void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001174 compile_node(comp, pns->nodes[0]);
1175 EMIT(pop_top);
1176}
1177
Damiend99b0522013-12-21 18:17:45 +00001178void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1179 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001180 // raise
Damien Georgeb9791222014-01-23 00:34:21 +00001181 EMIT_ARG(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001182 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001183 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001184 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001185 compile_node(comp, pns->nodes[0]);
1186 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001187 EMIT_ARG(raise_varargs, 2);
Damien429d7192013-10-04 19:53:11 +01001188 } else {
1189 // raise x
1190 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001191 EMIT_ARG(raise_varargs, 1);
Damien429d7192013-10-04 19:53:11 +01001192 }
1193}
1194
1195// q1 holds the base, q2 the full name
1196// eg a -> q1=q2=a
1197// a.b.c -> q1=a, q2=a.b.c
Damiend99b0522013-12-21 18:17:45 +00001198void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
Damien429d7192013-10-04 19:53:11 +01001199 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001200 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1201 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001202 // a name of the form x as y; unwrap it
Damiend99b0522013-12-21 18:17:45 +00001203 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001204 pn = pns->nodes[0];
1205 is_as = true;
1206 }
Damiend99b0522013-12-21 18:17:45 +00001207 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001208 // just a simple name
Damiend99b0522013-12-21 18:17:45 +00001209 *q2 = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001210 if (!is_as) {
1211 *q1 = *q2;
1212 }
Damien Georgeb9791222014-01-23 00:34:21 +00001213 EMIT_ARG(import_name, *q2);
Damiend99b0522013-12-21 18:17:45 +00001214 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
1215 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
1216 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dotted_name) {
Damien429d7192013-10-04 19:53:11 +01001217 // a name of the form a.b.c
1218 if (!is_as) {
Damiend99b0522013-12-21 18:17:45 +00001219 *q1 = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001220 }
Damiend99b0522013-12-21 18:17:45 +00001221 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001222 int len = n - 1;
1223 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00001224 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001225 }
Damien George55baff42014-01-21 21:40:13 +00001226 byte *q_ptr;
1227 byte *str_dest = qstr_build_start(len, &q_ptr);
Damien429d7192013-10-04 19:53:11 +01001228 for (int i = 0; i < n; i++) {
1229 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001230 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001231 }
Damien George55baff42014-01-21 21:40:13 +00001232 uint str_src_len;
1233 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00001234 memcpy(str_dest, str_src, str_src_len);
1235 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001236 }
Damien George55baff42014-01-21 21:40:13 +00001237 *q2 = qstr_build_end(q_ptr);
Damien Georgeb9791222014-01-23 00:34:21 +00001238 EMIT_ARG(import_name, *q2);
Damien429d7192013-10-04 19:53:11 +01001239 if (is_as) {
1240 for (int i = 1; i < n; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001241 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001242 }
1243 }
1244 } else {
1245 // TODO not implemented
Paul Sokolovskya1aba362014-02-20 13:21:31 +02001246 // This covers relative imports starting with dot(s) like "from .foo import"
Damien429d7192013-10-04 19:53:11 +01001247 assert(0);
1248 }
1249 } else {
1250 // TODO not implemented
Paul Sokolovskya1aba362014-02-20 13:21:31 +02001251 // This covers relative imports with dots only like "from .. import"
Damien429d7192013-10-04 19:53:11 +01001252 assert(0);
1253 }
1254}
1255
Damiend99b0522013-12-21 18:17:45 +00001256void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien Georgeb9791222014-01-23 00:34:21 +00001257 EMIT_ARG(load_const_small_int, 0); // ??
1258 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01001259 qstr q1, q2;
1260 do_import_name(comp, pn, &q1, &q2);
Damien Georgeb9791222014-01-23 00:34:21 +00001261 EMIT_ARG(store_id, q1);
Damien429d7192013-10-04 19:53:11 +01001262}
1263
Damiend99b0522013-12-21 18:17:45 +00001264void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001265 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1266}
1267
Damiend99b0522013-12-21 18:17:45 +00001268void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1269 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001270 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001271
1272 // build the "fromlist" tuple
1273#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001274 EMIT_ARG(load_const_verbatim_str, "('*',)");
Damiendb4c3612013-12-10 17:27:24 +00001275#else
Damien Georgeb9791222014-01-23 00:34:21 +00001276 EMIT_ARG(load_const_str, QSTR_FROM_STR_STATIC("*"), false);
1277 EMIT_ARG(build_tuple, 1);
Damiendb4c3612013-12-10 17:27:24 +00001278#endif
1279
1280 // do the import
Damien429d7192013-10-04 19:53:11 +01001281 qstr dummy_q, id1;
1282 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1283 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001284
Damien429d7192013-10-04 19:53:11 +01001285 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001286 EMIT_ARG(load_const_small_int, 0); // level 0 for __import__
Damiendb4c3612013-12-10 17:27:24 +00001287
1288 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001289 mp_parse_node_t *pn_nodes;
Damien429d7192013-10-04 19:53:11 +01001290 int n = list_get(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001291#if MICROPY_EMIT_CPYTHON
Damien02f89412013-12-12 15:13:36 +00001292 {
1293 vstr_t *vstr = vstr_new();
1294 vstr_printf(vstr, "(");
1295 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001296 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1297 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1298 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien02f89412013-12-12 15:13:36 +00001299 if (i > 0) {
1300 vstr_printf(vstr, ", ");
1301 }
1302 vstr_printf(vstr, "'");
Damien George55baff42014-01-21 21:40:13 +00001303 uint len;
1304 const byte *str = qstr_data(id2, &len);
1305 vstr_add_strn(vstr, (const char*)str, len);
Damien02f89412013-12-12 15:13:36 +00001306 vstr_printf(vstr, "'");
Damien429d7192013-10-04 19:53:11 +01001307 }
Damien02f89412013-12-12 15:13:36 +00001308 if (n == 1) {
1309 vstr_printf(vstr, ",");
1310 }
1311 vstr_printf(vstr, ")");
Damien Georgeb9791222014-01-23 00:34:21 +00001312 EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
Damien02f89412013-12-12 15:13:36 +00001313 vstr_free(vstr);
Damien429d7192013-10-04 19:53:11 +01001314 }
Damiendb4c3612013-12-10 17:27:24 +00001315#else
1316 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001317 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1318 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1319 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001320 EMIT_ARG(load_const_str, id2, false);
Damiendb4c3612013-12-10 17:27:24 +00001321 }
Damien Georgeb9791222014-01-23 00:34:21 +00001322 EMIT_ARG(build_tuple, n);
Damiendb4c3612013-12-10 17:27:24 +00001323#endif
1324
1325 // do the import
Damien429d7192013-10-04 19:53:11 +01001326 qstr dummy_q, id1;
1327 do_import_name(comp, pns->nodes[0], &dummy_q, &id1);
1328 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001329 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1330 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1331 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001332 EMIT_ARG(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001333 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien Georgeb9791222014-01-23 00:34:21 +00001334 EMIT_ARG(store_id, id2);
Damien429d7192013-10-04 19:53:11 +01001335 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001336 EMIT_ARG(store_id, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001337 }
1338 }
1339 EMIT(pop_top);
1340 }
1341}
1342
Damiend99b0522013-12-21 18:17:45 +00001343void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001344 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001345 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1346 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001347 } else {
Damiend99b0522013-12-21 18:17:45 +00001348 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1349 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001350 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001351 scope_declare_global(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001352 }
Damien429d7192013-10-04 19:53:11 +01001353 }
1354 }
1355}
1356
Damiend99b0522013-12-21 18:17:45 +00001357void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien415eb6f2013-10-05 12:19:06 +01001358 if (comp->pass == PASS_1) {
Damiend99b0522013-12-21 18:17:45 +00001359 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
1360 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien415eb6f2013-10-05 12:19:06 +01001361 } else {
Damiend99b0522013-12-21 18:17:45 +00001362 pns = (mp_parse_node_struct_t*)pns->nodes[0];
1363 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien415eb6f2013-10-05 12:19:06 +01001364 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00001365 scope_declare_nonlocal(comp->scope_cur, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien415eb6f2013-10-05 12:19:06 +01001366 }
Damien429d7192013-10-04 19:53:11 +01001367 }
1368 }
1369}
1370
Damiend99b0522013-12-21 18:17:45 +00001371void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001372 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001373 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien Georgeb9791222014-01-23 00:34:21 +00001374 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 +00001375 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001376 // assertion message
1377 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001378 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01001379 }
Damien Georgeb9791222014-01-23 00:34:21 +00001380 EMIT_ARG(raise_varargs, 1);
1381 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001382}
1383
Damiend99b0522013-12-21 18:17:45 +00001384void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001385 // TODO proper and/or short circuiting
1386
Damienb05d7072013-10-05 13:37:10 +01001387 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001388
Damienb05d7072013-10-05 13:37:10 +01001389 int l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001390 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1391
1392 compile_node(comp, pns->nodes[1]); // if block
Damiend99b0522013-12-21 18:17:45 +00001393 //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 +01001394 // jump over elif/else blocks if they exist
Damien415eb6f2013-10-05 12:19:06 +01001395 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001396 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001397 }
1398 //}
Damien Georgeb9791222014-01-23 00:34:21 +00001399 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001400
Damiend99b0522013-12-21 18:17:45 +00001401 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001402 // compile elif blocks
1403
Damiend99b0522013-12-21 18:17:45 +00001404 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pns->nodes[2];
Damien429d7192013-10-04 19:53:11 +01001405
Damiend99b0522013-12-21 18:17:45 +00001406 if (MP_PARSE_NODE_STRUCT_KIND(pns_elif) == PN_if_stmt_elif_list) {
Damien429d7192013-10-04 19:53:11 +01001407 // multiple elif blocks
1408
Damiend99b0522013-12-21 18:17:45 +00001409 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_elif);
Damien429d7192013-10-04 19:53:11 +01001410 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001411 mp_parse_node_struct_t *pns_elif2 = (mp_parse_node_struct_t*)pns_elif->nodes[i];
Damienb05d7072013-10-05 13:37:10 +01001412 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001413 c_if_cond(comp, pns_elif2->nodes[0], false, l_fail); // elif condition
1414
1415 compile_node(comp, pns_elif2->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001416 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001417 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001418 }
Damien Georgeb9791222014-01-23 00:34:21 +00001419 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001420 }
1421
1422 } else {
1423 // a single elif block
1424
Damienb05d7072013-10-05 13:37:10 +01001425 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001426 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1427
1428 compile_node(comp, pns_elif->nodes[1]); // elif block
Damien415eb6f2013-10-05 12:19:06 +01001429 if (!EMIT(last_emit_was_return_value)) { // simple optimisation to align with CPython
Damien Georgeb9791222014-01-23 00:34:21 +00001430 EMIT_ARG(jump, l_end);
Damien429d7192013-10-04 19:53:11 +01001431 }
Damien Georgeb9791222014-01-23 00:34:21 +00001432 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001433 }
1434 }
1435
1436 // compile else block
1437 compile_node(comp, pns->nodes[3]); // can be null
1438
Damien Georgeb9791222014-01-23 00:34:21 +00001439 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001440}
1441
Damien Georgecbddb272014-02-01 20:08:18 +00001442#define START_BREAK_CONTINUE_BLOCK \
1443 int old_break_label = comp->break_label; \
1444 int old_continue_label = comp->continue_label; \
1445 int break_label = comp_next_label(comp); \
1446 int continue_label = comp_next_label(comp); \
1447 comp->break_label = break_label; \
1448 comp->continue_label = continue_label; \
1449 comp->break_continue_except_level = comp->cur_except_level;
1450
1451#define END_BREAK_CONTINUE_BLOCK \
1452 comp->break_label = old_break_label; \
1453 comp->continue_label = old_continue_label; \
1454 comp->break_continue_except_level = comp->cur_except_level;
1455
Damiend99b0522013-12-21 18:17:45 +00001456void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgecbddb272014-02-01 20:08:18 +00001457 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001458
Damience89a212013-10-15 22:25:17 +01001459 // compared to CPython, we have an optimised version of while loops
1460#if MICROPY_EMIT_CPYTHON
1461 int done_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001462 EMIT_ARG(setup_loop, break_label);
1463 EMIT_ARG(label_assign, continue_label);
Damien429d7192013-10-04 19:53:11 +01001464 c_if_cond(comp, pns->nodes[0], false, done_label); // condition
1465 compile_node(comp, pns->nodes[1]); // body
Damien415eb6f2013-10-05 12:19:06 +01001466 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00001467 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001468 }
Damien Georgeb9791222014-01-23 00:34:21 +00001469 EMIT_ARG(label_assign, done_label);
Damien429d7192013-10-04 19:53:11 +01001470 // CPython does not emit POP_BLOCK if the condition was a constant; don't undertand why
1471 // this is a small hack to agree with CPython
1472 if (!node_is_const_true(pns->nodes[0])) {
1473 EMIT(pop_block);
1474 }
Damience89a212013-10-15 22:25:17 +01001475#else
1476 int top_label = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001477 EMIT_ARG(jump, continue_label);
1478 EMIT_ARG(label_assign, top_label);
Damience89a212013-10-15 22:25:17 +01001479 compile_node(comp, pns->nodes[1]); // body
Damien Georgeb9791222014-01-23 00:34:21 +00001480 EMIT_ARG(label_assign, continue_label);
Damience89a212013-10-15 22:25:17 +01001481 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1482#endif
1483
1484 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001485 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001486
1487 compile_node(comp, pns->nodes[2]); // else
1488
Damien Georgeb9791222014-01-23 00:34:21 +00001489 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001490}
1491
Damienf72fd0e2013-11-06 20:20:49 +00001492// TODO preload end and step onto stack if they are not constants
1493// TODO check if step is negative and do opposite test
Damiend99b0522013-12-21 18:17:45 +00001494void 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 +00001495 START_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001496
1497 int top_label = comp_next_label(comp);
Damien George600ae732014-01-21 23:48:04 +00001498 int entry_label = comp_next_label(comp);
Damienf72fd0e2013-11-06 20:20:49 +00001499
1500 // compile: var = start
1501 compile_node(comp, pn_start);
1502 c_assign(comp, pn_var, ASSIGN_STORE);
1503
Damien Georgeb9791222014-01-23 00:34:21 +00001504 EMIT_ARG(jump, entry_label);
1505 EMIT_ARG(label_assign, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001506
Damienf3822fc2013-11-09 20:12:03 +00001507 // compile body
1508 compile_node(comp, pn_body);
1509
Damien Georgeb9791222014-01-23 00:34:21 +00001510 EMIT_ARG(label_assign, continue_label);
Damien George600ae732014-01-21 23:48:04 +00001511
Damienf72fd0e2013-11-06 20:20:49 +00001512 // compile: var += step
1513 c_assign(comp, pn_var, ASSIGN_AUG_LOAD);
1514 compile_node(comp, pn_step);
Damien Georgeb9791222014-01-23 00:34:21 +00001515 EMIT_ARG(binary_op, RT_BINARY_OP_INPLACE_ADD);
Damienf72fd0e2013-11-06 20:20:49 +00001516 c_assign(comp, pn_var, ASSIGN_AUG_STORE);
1517
Damien Georgeb9791222014-01-23 00:34:21 +00001518 EMIT_ARG(label_assign, entry_label);
Damienf72fd0e2013-11-06 20:20:49 +00001519
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001520 // compile: if var <cond> end: goto top
Damienf72fd0e2013-11-06 20:20:49 +00001521 compile_node(comp, pn_var);
1522 compile_node(comp, pn_end);
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02001523 assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
1524 if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
Damien George9aa2a522014-02-01 23:04:09 +00001525 EMIT_ARG(binary_op, RT_BINARY_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001526 } else {
Damien George9aa2a522014-02-01 23:04:09 +00001527 EMIT_ARG(binary_op, RT_BINARY_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001528 }
Damien Georgeb9791222014-01-23 00:34:21 +00001529 EMIT_ARG(pop_jump_if_true, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001530
1531 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001532 END_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001533
1534 compile_node(comp, pn_else);
1535
Damien Georgeb9791222014-01-23 00:34:21 +00001536 EMIT_ARG(label_assign, break_label);
Damienf72fd0e2013-11-06 20:20:49 +00001537}
1538
Damiend99b0522013-12-21 18:17:45 +00001539void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001540#if !MICROPY_EMIT_CPYTHON
1541 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1542 // this is actually slower, but uses no heap memory
1543 // for viper it will be much, much faster
Damiend99b0522013-12-21 18:17:45 +00001544 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)) {
1545 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001546 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1547 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1548 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
1549 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
Damiend99b0522013-12-21 18:17:45 +00001550 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1551 mp_parse_node_t *args;
Damienf72fd0e2013-11-06 20:20:49 +00001552 int n_args = list_get(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001553 mp_parse_node_t pn_range_start;
1554 mp_parse_node_t pn_range_end;
1555 mp_parse_node_t pn_range_step;
1556 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001557 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001558 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001559 if (n_args == 1) {
Damiend99b0522013-12-21 18:17:45 +00001560 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
Damienf72fd0e2013-11-06 20:20:49 +00001561 pn_range_end = args[0];
Damiend99b0522013-12-21 18:17:45 +00001562 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001563 } else if (n_args == 2) {
1564 pn_range_start = args[0];
1565 pn_range_end = args[1];
Damiend99b0522013-12-21 18:17:45 +00001566 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
Damienf72fd0e2013-11-06 20:20:49 +00001567 } else {
1568 pn_range_start = args[0];
1569 pn_range_end = args[1];
1570 pn_range_step = args[2];
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001571 // We need to know sign of step. This is possible only if it's constant
1572 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
1573 optimize = false;
1574 }
Damienf72fd0e2013-11-06 20:20:49 +00001575 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001576 }
1577 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001578 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1579 return;
1580 }
1581 }
1582 }
1583#endif
1584
Damien Georgecbddb272014-02-01 20:08:18 +00001585 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001586
Damienb05d7072013-10-05 13:37:10 +01001587 int pop_label = comp_next_label(comp);
1588 int end_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001589
Damience89a212013-10-15 22:25:17 +01001590 // I don't think our implementation needs SETUP_LOOP/POP_BLOCK for for-statements
1591#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00001592 EMIT_ARG(setup_loop, end_label);
Damience89a212013-10-15 22:25:17 +01001593#endif
1594
Damien429d7192013-10-04 19:53:11 +01001595 compile_node(comp, pns->nodes[1]); // iterator
1596 EMIT(get_iter);
Damien Georgecbddb272014-02-01 20:08:18 +00001597 EMIT_ARG(label_assign, continue_label);
Damien Georgeb9791222014-01-23 00:34:21 +00001598 EMIT_ARG(for_iter, pop_label);
Damien429d7192013-10-04 19:53:11 +01001599 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1600 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001601 if (!EMIT(last_emit_was_return_value)) {
Damien Georgecbddb272014-02-01 20:08:18 +00001602 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001603 }
Damien Georgeb9791222014-01-23 00:34:21 +00001604 EMIT_ARG(label_assign, pop_label);
Damien429d7192013-10-04 19:53:11 +01001605 EMIT(for_iter_end);
1606
1607 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001608 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001609
Damience89a212013-10-15 22:25:17 +01001610#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01001611 EMIT(pop_block);
Damience89a212013-10-15 22:25:17 +01001612#endif
Damien429d7192013-10-04 19:53:11 +01001613
1614 compile_node(comp, pns->nodes[3]); // else (not tested)
1615
Damien Georgeb9791222014-01-23 00:34:21 +00001616 EMIT_ARG(label_assign, break_label);
1617 EMIT_ARG(label_assign, end_label);
Damien429d7192013-10-04 19:53:11 +01001618}
1619
Damiend99b0522013-12-21 18:17:45 +00001620void 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 +01001621 // this function is a bit of a hack at the moment
1622 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1623
1624 // setup code
1625 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001626 int l1 = comp_next_label(comp);
1627 int success_label = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001628
Damien Georgeb9791222014-01-23 00:34:21 +00001629 EMIT_ARG(setup_except, l1);
Damien Georgecbddb272014-02-01 20:08:18 +00001630 comp->cur_except_level += 1;
1631
Damien429d7192013-10-04 19:53:11 +01001632 compile_node(comp, pn_body); // body
1633 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001634 EMIT_ARG(jump, success_label);
1635 EMIT_ARG(label_assign, l1);
Damienb05d7072013-10-05 13:37:10 +01001636 int l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001637
1638 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001639 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1640 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001641
1642 qstr qstr_exception_local = 0;
Damienb05d7072013-10-05 13:37:10 +01001643 int end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001644
Damiend99b0522013-12-21 18:17:45 +00001645 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001646 // this is a catch all exception handler
1647 if (i + 1 != n_except) {
Damien Georgef41fdd02014-03-03 23:19:11 +00001648 compile_syntax_error(comp, "default 'except:' must be last");
Damien429d7192013-10-04 19:53:11 +01001649 return;
1650 }
1651 } else {
1652 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001653 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1654 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1655 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1656 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001657 // handler binds the exception to a local
1658 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001659 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001660 }
1661 }
1662 EMIT(dup_top);
1663 compile_node(comp, pns_exception_expr);
Damien George9aa2a522014-02-01 23:04:09 +00001664 EMIT_ARG(binary_op, RT_BINARY_OP_EXCEPTION_MATCH);
Damien Georgeb9791222014-01-23 00:34:21 +00001665 EMIT_ARG(pop_jump_if_false, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001666 }
1667
1668 EMIT(pop_top);
1669
1670 if (qstr_exception_local == 0) {
1671 EMIT(pop_top);
1672 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00001673 EMIT_ARG(store_id, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001674 }
1675
1676 EMIT(pop_top);
1677
Damiene2880aa2013-12-20 14:22:59 +00001678 int l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001679 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001680 l3 = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001681 EMIT_ARG(setup_finally, l3);
Damien Georgecbddb272014-02-01 20:08:18 +00001682 comp->cur_except_level += 1;
Damien429d7192013-10-04 19:53:11 +01001683 }
1684 compile_node(comp, pns_except->nodes[1]);
1685 if (qstr_exception_local != 0) {
1686 EMIT(pop_block);
1687 }
1688 EMIT(pop_except);
1689 if (qstr_exception_local != 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001690 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1691 EMIT_ARG(label_assign, l3);
1692 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1693 EMIT_ARG(store_id, qstr_exception_local);
1694 EMIT_ARG(delete_id, qstr_exception_local);
Damien Georgecbddb272014-02-01 20:08:18 +00001695
1696 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001697 EMIT(end_finally);
1698 }
Damien Georgeb9791222014-01-23 00:34:21 +00001699 EMIT_ARG(jump, l2);
1700 EMIT_ARG(label_assign, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001701 }
1702
Damien Georgecbddb272014-02-01 20:08:18 +00001703 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001704 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001705
Damien Georgeb9791222014-01-23 00:34:21 +00001706 EMIT_ARG(label_assign, success_label);
Damien429d7192013-10-04 19:53:11 +01001707 compile_node(comp, pn_else); // else block, can be null
Damien Georgeb9791222014-01-23 00:34:21 +00001708 EMIT_ARG(label_assign, l2);
1709 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001710}
1711
Damiend99b0522013-12-21 18:17:45 +00001712void 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 +01001713 // don't understand how the stack works with exceptions, so we force it to return to the correct value
1714 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001715 int l_finally_block = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001716
Damien Georgeb9791222014-01-23 00:34:21 +00001717 EMIT_ARG(setup_finally, l_finally_block);
Damien Georgecbddb272014-02-01 20:08:18 +00001718 comp->cur_except_level += 1;
1719
Damien429d7192013-10-04 19:53:11 +01001720 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001721 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien429d7192013-10-04 19:53:11 +01001722 compile_node(comp, pn_body);
1723 } else {
1724 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1725 }
1726 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001727 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1728 EMIT_ARG(label_assign, l_finally_block);
Damien429d7192013-10-04 19:53:11 +01001729 compile_node(comp, pn_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001730
1731 comp->cur_except_level -= 1;
Damien429d7192013-10-04 19:53:11 +01001732 EMIT(end_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001733
Damien Georgeb9791222014-01-23 00:34:21 +00001734 EMIT_ARG(set_stack_size, stack_size);
Damien429d7192013-10-04 19:53:11 +01001735}
1736
Damiend99b0522013-12-21 18:17:45 +00001737void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1738 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
1739 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1740 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001741 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001742 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1743 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001744 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001745 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001746 int n_except = list_get(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001747 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001748 // no finally
1749 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1750 } else {
1751 // have finally
Damiend99b0522013-12-21 18:17:45 +00001752 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 +01001753 }
1754 } else {
1755 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001756 mp_parse_node_t *pn_excepts;
Damien429d7192013-10-04 19:53:11 +01001757 int n_except = list_get(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001758 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001759 }
1760 } else {
1761 // shouldn't happen
1762 assert(0);
1763 }
1764}
1765
Damiend99b0522013-12-21 18:17:45 +00001766void 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 +01001767 if (n == 0) {
1768 // no more pre-bits, compile the body of the with
1769 compile_node(comp, body);
1770 } else {
Damienb05d7072013-10-05 13:37:10 +01001771 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001772 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001773 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001774 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001775 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001776 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001777 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1778 } else {
1779 // this pre-bit is just an expression
1780 compile_node(comp, nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001781 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001782 EMIT(pop_top);
1783 }
1784 // compile additional pre-bits and the body
1785 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1786 // finish this with block
1787 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001788 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1789 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001790 EMIT(with_cleanup);
1791 EMIT(end_finally);
1792 }
1793}
1794
Damiend99b0522013-12-21 18:17:45 +00001795void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001796 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001797 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01001798 int n = list_get(&pns->nodes[0], PN_with_stmt_list, &nodes);
1799 assert(n > 0);
1800
1801 // compile in a nested fashion
1802 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1803}
1804
Damiend99b0522013-12-21 18:17:45 +00001805void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1806 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001807 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1808 // for REPL, evaluate then print the expression
Damien Georgeb9791222014-01-23 00:34:21 +00001809 EMIT_ARG(load_id, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001810 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001811 EMIT_ARG(call_function, 1, 0, false, false);
Damien5ac1b2e2013-10-18 19:58:12 +01001812 EMIT(pop_top);
1813
Damien429d7192013-10-04 19:53:11 +01001814 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001815 // for non-REPL, evaluate then discard the expression
Damiend99b0522013-12-21 18:17:45 +00001816 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001817 // do nothing with a lonely constant
1818 } else {
1819 compile_node(comp, pns->nodes[0]); // just an expression
1820 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1821 }
Damien429d7192013-10-04 19:53:11 +01001822 }
1823 } else {
Damiend99b0522013-12-21 18:17:45 +00001824 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1825 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001826 if (kind == PN_expr_stmt_augassign) {
1827 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1828 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001829 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien George7e5fb242014-02-01 22:18:47 +00001830 rt_binary_op_t op;
Damiend99b0522013-12-21 18:17:45 +00001831 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
Damien George7e5fb242014-02-01 22:18:47 +00001832 case MP_TOKEN_DEL_PIPE_EQUAL: op = RT_BINARY_OP_INPLACE_OR; break;
1833 case MP_TOKEN_DEL_CARET_EQUAL: op = RT_BINARY_OP_INPLACE_XOR; break;
1834 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = RT_BINARY_OP_INPLACE_AND; break;
1835 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = RT_BINARY_OP_INPLACE_LSHIFT; break;
1836 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = RT_BINARY_OP_INPLACE_RSHIFT; break;
1837 case MP_TOKEN_DEL_PLUS_EQUAL: op = RT_BINARY_OP_INPLACE_ADD; break;
1838 case MP_TOKEN_DEL_MINUS_EQUAL: op = RT_BINARY_OP_INPLACE_SUBTRACT; break;
1839 case MP_TOKEN_DEL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_MULTIPLY; break;
1840 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
1841 case MP_TOKEN_DEL_SLASH_EQUAL: op = RT_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
1842 case MP_TOKEN_DEL_PERCENT_EQUAL: op = RT_BINARY_OP_INPLACE_MODULO; break;
1843 case MP_TOKEN_DEL_DBL_STAR_EQUAL: op = RT_BINARY_OP_INPLACE_POWER; break;
1844 default: assert(0); op = RT_BINARY_OP_INPLACE_OR; // shouldn't happen
Damien429d7192013-10-04 19:53:11 +01001845 }
Damien George7e5fb242014-02-01 22:18:47 +00001846 EMIT_ARG(binary_op, op);
Damien429d7192013-10-04 19:53:11 +01001847 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1848 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001849 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
1850 compile_node(comp, ((mp_parse_node_struct_t*)pns1->nodes[rhs])->nodes[0]); // rhs
Damien429d7192013-10-04 19:53:11 +01001851 // following CPython, we store left-most first
1852 if (rhs > 0) {
1853 EMIT(dup_top);
1854 }
1855 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1856 for (int i = 0; i < rhs; i++) {
1857 if (i + 1 < rhs) {
1858 EMIT(dup_top);
1859 }
Damiend99b0522013-12-21 18:17:45 +00001860 c_assign(comp, ((mp_parse_node_struct_t*)pns1->nodes[i])->nodes[0], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001861 }
1862 } else if (kind == PN_expr_stmt_assign) {
Damiend99b0522013-12-21 18:17:45 +00001863 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1864 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1865 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 2
1866 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien429d7192013-10-04 19:53:11 +01001867 // optimisation for a, b = c, d; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001868 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1869 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001870 compile_node(comp, pns10->nodes[0]); // rhs
1871 compile_node(comp, pns10->nodes[1]); // rhs
1872 EMIT(rot_two);
1873 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1874 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damiend99b0522013-12-21 18:17:45 +00001875 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_testlist_star_expr)
1876 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
1877 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns1->nodes[0]) == 3
1878 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien429d7192013-10-04 19:53:11 +01001879 // optimisation for a, b, c = d, e, f; to match CPython's optimisation
Damiend99b0522013-12-21 18:17:45 +00001880 mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
1881 mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001882 compile_node(comp, pns10->nodes[0]); // rhs
1883 compile_node(comp, pns10->nodes[1]); // rhs
1884 compile_node(comp, pns10->nodes[2]); // rhs
1885 EMIT(rot_three);
1886 EMIT(rot_two);
1887 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1888 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1889 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1890 } else {
1891 compile_node(comp, pns1->nodes[0]); // rhs
1892 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1893 }
1894 } else {
1895 // shouldn't happen
1896 assert(0);
1897 }
1898 }
1899}
1900
Damiend99b0522013-12-21 18:17:45 +00001901void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, rt_binary_op_t binary_op) {
1902 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001903 compile_node(comp, pns->nodes[0]);
1904 for (int i = 1; i < num_nodes; i += 1) {
1905 compile_node(comp, pns->nodes[i]);
Damien Georgeb9791222014-01-23 00:34:21 +00001906 EMIT_ARG(binary_op, binary_op);
Damien429d7192013-10-04 19:53:11 +01001907 }
1908}
1909
Damiend99b0522013-12-21 18:17:45 +00001910void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
1911 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
1912 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001913
1914 int stack_size = EMIT(get_stack_size);
Damienb05d7072013-10-05 13:37:10 +01001915 int l_fail = comp_next_label(comp);
1916 int l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001917 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
1918 compile_node(comp, pns->nodes[0]); // success value
Damien Georgeb9791222014-01-23 00:34:21 +00001919 EMIT_ARG(jump, l_end);
1920 EMIT_ARG(label_assign, l_fail);
1921 EMIT_ARG(set_stack_size, stack_size); // force stack size reset
Damien429d7192013-10-04 19:53:11 +01001922 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
Damien Georgeb9791222014-01-23 00:34:21 +00001923 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001924}
1925
Damiend99b0522013-12-21 18:17:45 +00001926void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001927 // TODO default params etc for lambda; possibly just use funcdef code
Damiend99b0522013-12-21 18:17:45 +00001928 //mp_parse_node_t pn_params = pns->nodes[0];
1929 //mp_parse_node_t pn_body = pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01001930
1931 if (comp->pass == PASS_1) {
1932 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00001933 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 +01001934 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00001935 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01001936 }
1937
1938 // get the scope for this lambda
1939 scope_t *this_scope = (scope_t*)pns->nodes[2];
1940
1941 // make the lambda
1942 close_over_variables_etc(comp, this_scope, 0, 0);
1943}
1944
Damiend99b0522013-12-21 18:17:45 +00001945void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001946 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001947 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001948 for (int i = 0; i < n; i += 1) {
1949 compile_node(comp, pns->nodes[i]);
1950 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001951 EMIT_ARG(jump_if_true_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001952 }
1953 }
Damien Georgeb9791222014-01-23 00:34:21 +00001954 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001955}
1956
Damiend99b0522013-12-21 18:17:45 +00001957void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienb05d7072013-10-05 13:37:10 +01001958 int l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00001959 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001960 for (int i = 0; i < n; i += 1) {
1961 compile_node(comp, pns->nodes[i]);
1962 if (i + 1 < n) {
Damien Georgeb9791222014-01-23 00:34:21 +00001963 EMIT_ARG(jump_if_false_or_pop, l_end);
Damien429d7192013-10-04 19:53:11 +01001964 }
1965 }
Damien Georgeb9791222014-01-23 00:34:21 +00001966 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001967}
1968
Damiend99b0522013-12-21 18:17:45 +00001969void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001970 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001971 EMIT_ARG(unary_op, RT_UNARY_OP_NOT);
Damien429d7192013-10-04 19:53:11 +01001972}
1973
Damiend99b0522013-12-21 18:17:45 +00001974void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001975 int stack_size = EMIT(get_stack_size);
Damiend99b0522013-12-21 18:17:45 +00001976 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001977 compile_node(comp, pns->nodes[0]);
1978 bool multi = (num_nodes > 3);
1979 int l_fail = 0;
1980 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01001981 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001982 }
1983 for (int i = 1; i + 1 < num_nodes; i += 2) {
1984 compile_node(comp, pns->nodes[i + 1]);
1985 if (i + 2 < num_nodes) {
1986 EMIT(dup_top);
1987 EMIT(rot_three);
1988 }
Damien George7e5fb242014-02-01 22:18:47 +00001989 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
1990 rt_binary_op_t op;
1991 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
Damien George9aa2a522014-02-01 23:04:09 +00001992 case MP_TOKEN_OP_LESS: op = RT_BINARY_OP_LESS; break;
1993 case MP_TOKEN_OP_MORE: op = RT_BINARY_OP_MORE; break;
1994 case MP_TOKEN_OP_DBL_EQUAL: op = RT_BINARY_OP_EQUAL; break;
1995 case MP_TOKEN_OP_LESS_EQUAL: op = RT_BINARY_OP_LESS_EQUAL; break;
1996 case MP_TOKEN_OP_MORE_EQUAL: op = RT_BINARY_OP_MORE_EQUAL; break;
1997 case MP_TOKEN_OP_NOT_EQUAL: op = RT_BINARY_OP_NOT_EQUAL; break;
1998 case MP_TOKEN_KW_IN: op = RT_BINARY_OP_IN; break;
1999 default: assert(0); op = RT_BINARY_OP_LESS; // shouldn't happen
Damien George7e5fb242014-02-01 22:18:47 +00002000 }
2001 EMIT_ARG(binary_op, op);
Damiend99b0522013-12-21 18:17:45 +00002002 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])) {
2003 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
2004 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01002005 if (kind == PN_comp_op_not_in) {
Damien George9aa2a522014-02-01 23:04:09 +00002006 EMIT_ARG(binary_op, RT_BINARY_OP_NOT_IN);
Damien429d7192013-10-04 19:53:11 +01002007 } else if (kind == PN_comp_op_is) {
Damiend99b0522013-12-21 18:17:45 +00002008 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien George9aa2a522014-02-01 23:04:09 +00002009 EMIT_ARG(binary_op, RT_BINARY_OP_IS);
Damien429d7192013-10-04 19:53:11 +01002010 } else {
Damien George9aa2a522014-02-01 23:04:09 +00002011 EMIT_ARG(binary_op, RT_BINARY_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01002012 }
2013 } else {
2014 // shouldn't happen
2015 assert(0);
2016 }
2017 } else {
2018 // shouldn't happen
2019 assert(0);
2020 }
2021 if (i + 2 < num_nodes) {
Damien Georgeb9791222014-01-23 00:34:21 +00002022 EMIT_ARG(jump_if_false_or_pop, l_fail);
Damien429d7192013-10-04 19:53:11 +01002023 }
2024 }
2025 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01002026 int l_end = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002027 EMIT_ARG(jump, l_end);
2028 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01002029 EMIT(rot_two);
2030 EMIT(pop_top);
Damien Georgeb9791222014-01-23 00:34:21 +00002031 EMIT_ARG(label_assign, l_end);
2032 EMIT_ARG(set_stack_size, stack_size + 1); // force stack size
Damien429d7192013-10-04 19:53:11 +01002033 }
2034}
2035
Damiend99b0522013-12-21 18:17:45 +00002036void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002037 // TODO
2038 assert(0);
2039 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002040 //EMIT_ARG(unary_op, "UNARY_STAR");
Damien429d7192013-10-04 19:53:11 +01002041}
2042
Damiend99b0522013-12-21 18:17:45 +00002043void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002044 c_binary_op(comp, pns, RT_BINARY_OP_OR);
2045}
2046
Damiend99b0522013-12-21 18:17:45 +00002047void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002048 c_binary_op(comp, pns, RT_BINARY_OP_XOR);
2049}
2050
Damiend99b0522013-12-21 18:17:45 +00002051void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002052 c_binary_op(comp, pns, RT_BINARY_OP_AND);
2053}
2054
Damiend99b0522013-12-21 18:17:45 +00002055void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2056 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002057 compile_node(comp, pns->nodes[0]);
2058 for (int i = 1; i + 1 < num_nodes; i += 2) {
2059 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002060 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002061 EMIT_ARG(binary_op, RT_BINARY_OP_LSHIFT);
Damiend99b0522013-12-21 18:17:45 +00002062 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002063 EMIT_ARG(binary_op, RT_BINARY_OP_RSHIFT);
Damien429d7192013-10-04 19:53:11 +01002064 } else {
2065 // shouldn't happen
2066 assert(0);
2067 }
2068 }
2069}
2070
Damiend99b0522013-12-21 18:17:45 +00002071void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2072 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002073 compile_node(comp, pns->nodes[0]);
2074 for (int i = 1; i + 1 < num_nodes; i += 2) {
2075 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002076 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002077 EMIT_ARG(binary_op, RT_BINARY_OP_ADD);
Damiend99b0522013-12-21 18:17:45 +00002078 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002079 EMIT_ARG(binary_op, RT_BINARY_OP_SUBTRACT);
Damien429d7192013-10-04 19:53:11 +01002080 } else {
2081 // shouldn't happen
2082 assert(0);
2083 }
2084 }
2085}
2086
Damiend99b0522013-12-21 18:17:45 +00002087void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2088 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002089 compile_node(comp, pns->nodes[0]);
2090 for (int i = 1; i + 1 < num_nodes; i += 2) {
2091 compile_node(comp, pns->nodes[i + 1]);
Damiend99b0522013-12-21 18:17:45 +00002092 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002093 EMIT_ARG(binary_op, RT_BINARY_OP_MULTIPLY);
Damiend99b0522013-12-21 18:17:45 +00002094 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002095 EMIT_ARG(binary_op, RT_BINARY_OP_FLOOR_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002096 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002097 EMIT_ARG(binary_op, RT_BINARY_OP_TRUE_DIVIDE);
Damiend99b0522013-12-21 18:17:45 +00002098 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002099 EMIT_ARG(binary_op, RT_BINARY_OP_MODULO);
Damien429d7192013-10-04 19:53:11 +01002100 } else {
2101 // shouldn't happen
2102 assert(0);
2103 }
2104 }
2105}
2106
Damiend99b0522013-12-21 18:17:45 +00002107void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002108 compile_node(comp, pns->nodes[1]);
Damiend99b0522013-12-21 18:17:45 +00002109 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002110 EMIT_ARG(unary_op, RT_UNARY_OP_POSITIVE);
Damiend99b0522013-12-21 18:17:45 +00002111 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002112 EMIT_ARG(unary_op, RT_UNARY_OP_NEGATIVE);
Damiend99b0522013-12-21 18:17:45 +00002113 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002114 EMIT_ARG(unary_op, RT_UNARY_OP_INVERT);
Damien429d7192013-10-04 19:53:11 +01002115 } else {
2116 // shouldn't happen
2117 assert(0);
2118 }
2119}
2120
Damien George35e2a4e2014-02-05 00:51:47 +00002121void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
2122 // this is to handle special super() call
2123 comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
2124
2125 compile_generic_all_nodes(comp, pns);
2126}
2127
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002128STATIC 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 +01002129 // function to call is on top of stack
2130
Damien George35e2a4e2014-02-05 00:51:47 +00002131#if !MICROPY_EMIT_CPYTHON
2132 // this is to handle special super() call
Damien Georgebbcd49a2014-02-06 20:30:16 +00002133 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 +00002134 EMIT_ARG(load_id, MP_QSTR___class__);
2135 // get first argument to function
2136 bool found = false;
2137 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
2138 if (comp->scope_cur->id_info[i].param) {
2139 EMIT_ARG(load_fast, MP_QSTR_, comp->scope_cur->id_info[i].local_num);
2140 found = true;
2141 break;
2142 }
2143 }
2144 if (!found) {
2145 printf("TypeError: super() call cannot find self\n");
2146 return;
2147 }
2148 EMIT_ARG(call_function, 2, 0, false, false);
2149 return;
2150 }
2151#endif
2152
Damien429d7192013-10-04 19:53:11 +01002153 int old_n_arg_keyword = comp->n_arg_keyword;
2154 bool old_have_star_arg = comp->have_star_arg;
2155 bool old_have_dbl_star_arg = comp->have_dbl_star_arg;
2156 comp->n_arg_keyword = 0;
2157 comp->have_star_arg = false;
2158 comp->have_dbl_star_arg = false;
2159
Damien Georgebbcd49a2014-02-06 20:30:16 +00002160 compile_node(comp, pn_arglist); // arguments to function call; can be null
Damien429d7192013-10-04 19:53:11 +01002161
2162 // compute number of positional arguments
Damien Georgebbcd49a2014-02-06 20:30:16 +00002163 int n_positional = n_positional_extra + list_len(pn_arglist, PN_arglist) - comp->n_arg_keyword;
Damien429d7192013-10-04 19:53:11 +01002164 if (comp->have_star_arg) {
2165 n_positional -= 1;
2166 }
2167 if (comp->have_dbl_star_arg) {
2168 n_positional -= 1;
2169 }
2170
2171 if (is_method_call) {
Damien Georgeb9791222014-01-23 00:34:21 +00002172 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 +01002173 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002174 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 +01002175 }
2176
2177 comp->n_arg_keyword = old_n_arg_keyword;
2178 comp->have_star_arg = old_have_star_arg;
2179 comp->have_dbl_star_arg = old_have_dbl_star_arg;
2180}
2181
Damiend99b0522013-12-21 18:17:45 +00002182void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
2183 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002184 for (int i = 0; i < num_nodes; i++) {
Damiend99b0522013-12-21 18:17:45 +00002185 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 +01002186 // optimisation for method calls a.f(...), following PyPy
Damiend99b0522013-12-21 18:17:45 +00002187 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
2188 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
Damien Georgeb9791222014-01-23 00:34:21 +00002189 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
Damien Georgebbcd49a2014-02-06 20:30:16 +00002190 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
Damien429d7192013-10-04 19:53:11 +01002191 i += 1;
2192 } else {
2193 compile_node(comp, pns->nodes[i]);
2194 }
Damien George35e2a4e2014-02-05 00:51:47 +00002195 comp->func_arg_is_super = false;
Damien429d7192013-10-04 19:53:11 +01002196 }
2197}
2198
Damiend99b0522013-12-21 18:17:45 +00002199void compile_power_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002200 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002201 EMIT_ARG(binary_op, RT_BINARY_OP_POWER);
Damien429d7192013-10-04 19:53:11 +01002202}
2203
Damiend99b0522013-12-21 18:17:45 +00002204void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002205 // a list of strings
Damien63321742013-12-10 17:41:49 +00002206
2207 // check type of list (string or bytes) and count total number of bytes
Damiend99b0522013-12-21 18:17:45 +00002208 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien63321742013-12-10 17:41:49 +00002209 int n_bytes = 0;
Damiend99b0522013-12-21 18:17:45 +00002210 int string_kind = MP_PARSE_NODE_NULL;
Damien429d7192013-10-04 19:53:11 +01002211 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002212 assert(MP_PARSE_NODE_IS_LEAF(pns->nodes[i]));
2213 int pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
2214 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
Damien63321742013-12-10 17:41:49 +00002215 if (i == 0) {
2216 string_kind = pn_kind;
2217 } else if (pn_kind != string_kind) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002218 compile_syntax_error(comp, "cannot mix bytes and nonbytes literals");
Damien63321742013-12-10 17:41:49 +00002219 return;
2220 }
Damien George55baff42014-01-21 21:40:13 +00002221 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01002222 }
Damien63321742013-12-10 17:41:49 +00002223
Damien63321742013-12-10 17:41:49 +00002224 // concatenate string/bytes
Damien George55baff42014-01-21 21:40:13 +00002225 byte *q_ptr;
2226 byte *s_dest = qstr_build_start(n_bytes, &q_ptr);
Damien63321742013-12-10 17:41:49 +00002227 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00002228 uint s_len;
2229 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00002230 memcpy(s_dest, s, s_len);
2231 s_dest += s_len;
Damien63321742013-12-10 17:41:49 +00002232 }
Damien George55baff42014-01-21 21:40:13 +00002233 qstr q = qstr_build_end(q_ptr);
Damien63321742013-12-10 17:41:49 +00002234
Damien Georgeb9791222014-01-23 00:34:21 +00002235 EMIT_ARG(load_const_str, q, string_kind == MP_PARSE_NODE_BYTES);
Damien429d7192013-10-04 19:53:11 +01002236}
2237
2238// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damiend99b0522013-12-21 18:17:45 +00002239void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2240 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2241 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2242 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002243
2244 if (comp->pass == PASS_1) {
2245 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002246 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 +01002247 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002248 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002249 }
2250
2251 // get the scope for this comprehension
2252 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2253
2254 // compile the comprehension
2255 close_over_variables_etc(comp, this_scope, 0, 0);
2256
2257 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2258 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002259 EMIT_ARG(call_function, 1, 0, false, false);
Damien429d7192013-10-04 19:53:11 +01002260}
2261
Damiend99b0522013-12-21 18:17:45 +00002262void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2263 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002264 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002265 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
2266 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2267 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2268 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2269 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2270 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2271 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002272 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002273 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002274 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002275 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002276 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002277 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002278 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002279 // generator expression
2280 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2281 } else {
2282 // tuple with 2 items
2283 goto tuple_with_2_items;
2284 }
2285 } else {
2286 // tuple with 2 items
2287 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002288 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002289 }
2290 } else {
2291 // parenthesis around a single item, is just that item
2292 compile_node(comp, pns->nodes[0]);
2293 }
2294}
2295
Damiend99b0522013-12-21 18:17:45 +00002296void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2297 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002298 // empty list
Damien Georgeb9791222014-01-23 00:34:21 +00002299 EMIT_ARG(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002300 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2301 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2302 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2303 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2304 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002305 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002306 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002307 compile_node(comp, pns2->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002308 EMIT_ARG(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002309 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002310 // list of many items
2311 compile_node(comp, pns2->nodes[0]);
2312 compile_generic_all_nodes(comp, pns3);
Damien Georgeb9791222014-01-23 00:34:21 +00002313 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
Damiend99b0522013-12-21 18:17:45 +00002314 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002315 // list comprehension
2316 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2317 } else {
2318 // list with 2 items
2319 goto list_with_2_items;
2320 }
2321 } else {
2322 // list with 2 items
2323 list_with_2_items:
2324 compile_node(comp, pns2->nodes[0]);
2325 compile_node(comp, pns2->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00002326 EMIT_ARG(build_list, 2);
Damien429d7192013-10-04 19:53:11 +01002327 }
2328 } else {
2329 // list with 1 item
2330 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002331 EMIT_ARG(build_list, 1);
Damien429d7192013-10-04 19:53:11 +01002332 }
2333}
2334
Damiend99b0522013-12-21 18:17:45 +00002335void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
2336 mp_parse_node_t pn = pns->nodes[0];
2337 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002338 // empty dict
Damien Georgeb9791222014-01-23 00:34:21 +00002339 EMIT_ARG(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002340 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2341 pns = (mp_parse_node_struct_t*)pn;
2342 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002343 // dict with one element
Damien Georgeb9791222014-01-23 00:34:21 +00002344 EMIT_ARG(build_map, 1);
Damien429d7192013-10-04 19:53:11 +01002345 compile_node(comp, pn);
2346 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002347 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2348 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2349 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2350 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002351 // dict/set with multiple elements
2352
2353 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002354 mp_parse_node_t *nodes;
Damien429d7192013-10-04 19:53:11 +01002355 int n = list_get(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
2356
2357 // first element sets whether it's a dict or set
2358 bool is_dict;
Damiend99b0522013-12-21 18:17:45 +00002359 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002360 // a dictionary
Damien Georgeb9791222014-01-23 00:34:21 +00002361 EMIT_ARG(build_map, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002362 compile_node(comp, pns->nodes[0]);
2363 EMIT(store_map);
2364 is_dict = true;
2365 } else {
2366 // a set
2367 compile_node(comp, pns->nodes[0]); // 1st value of set
2368 is_dict = false;
2369 }
2370
2371 // process rest of elements
2372 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00002373 mp_parse_node_t pn = nodes[i];
2374 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dictorsetmaker_item);
Damien429d7192013-10-04 19:53:11 +01002375 compile_node(comp, pn);
2376 if (is_dict) {
2377 if (!is_key_value) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002378 compile_syntax_error(comp, "?expecting key:value for dictiona");
Damien429d7192013-10-04 19:53:11 +01002379 return;
2380 }
2381 EMIT(store_map);
2382 } else {
2383 if (is_key_value) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002384 compile_syntax_error(comp, "?expecting just a value for s");
Damien429d7192013-10-04 19:53:11 +01002385 return;
2386 }
2387 }
2388 }
2389
2390 // if it's a set, build it
2391 if (!is_dict) {
Damien Georgeb9791222014-01-23 00:34:21 +00002392 EMIT_ARG(build_set, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002393 }
Damiend99b0522013-12-21 18:17:45 +00002394 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002395 // dict/set comprehension
Damiend99b0522013-12-21 18:17:45 +00002396 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002397 // a dictionary comprehension
2398 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2399 } else {
2400 // a set comprehension
2401 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2402 }
2403 } else {
2404 // shouldn't happen
2405 assert(0);
2406 }
2407 } else {
2408 // set with one element
2409 goto set_with_one_element;
2410 }
2411 } else {
2412 // set with one element
2413 set_with_one_element:
2414 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002415 EMIT_ARG(build_set, 1);
Damien429d7192013-10-04 19:53:11 +01002416 }
2417}
2418
Damiend99b0522013-12-21 18:17:45 +00002419void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgebbcd49a2014-02-06 20:30:16 +00002420 compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
Damien429d7192013-10-04 19:53:11 +01002421}
2422
Damiend99b0522013-12-21 18:17:45 +00002423void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002424 // object who's index we want is on top of stack
2425 compile_node(comp, pns->nodes[0]); // the index
Damien Georgeb9791222014-01-23 00:34:21 +00002426 EMIT_ARG(binary_op, RT_BINARY_OP_SUBSCR);
Damien429d7192013-10-04 19:53:11 +01002427}
2428
Damiend99b0522013-12-21 18:17:45 +00002429void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002430 // object who's attribute we want is on top of stack
Damien Georgeb9791222014-01-23 00:34:21 +00002431 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002432}
2433
Damiend99b0522013-12-21 18:17:45 +00002434void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
2435 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2436 mp_parse_node_t pn = pns->nodes[0];
2437 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002438 // [?:]
Damien Georgeb9791222014-01-23 00:34:21 +00002439 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
2440 EMIT_ARG(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002441 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2442 pns = (mp_parse_node_struct_t*)pn;
2443 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
Damien Georgeb9791222014-01-23 00:34:21 +00002444 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002445 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002446 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002447 // [?::]
Damien Georgeb9791222014-01-23 00:34:21 +00002448 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002449 } else {
2450 // [?::x]
2451 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002452 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002453 }
Damiend99b0522013-12-21 18:17:45 +00002454 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002455 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002456 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2457 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2458 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2459 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002460 // [?:x:]
Damien Georgeb9791222014-01-23 00:34:21 +00002461 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002462 } else {
2463 // [?:x:x]
2464 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002465 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002466 }
2467 } else {
2468 // [?:x]
2469 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002470 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002471 }
2472 } else {
2473 // [?:x]
2474 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002475 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002476 }
2477}
2478
Damiend99b0522013-12-21 18:17:45 +00002479void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002480 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002481 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2482 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002483}
2484
Damiend99b0522013-12-21 18:17:45 +00002485void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgeb9791222014-01-23 00:34:21 +00002486 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002487 compile_subscript_3_helper(comp, pns);
2488}
2489
Damiend99b0522013-12-21 18:17:45 +00002490void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002491 // if this is called then we are compiling a dict key:value pair
2492 compile_node(comp, pns->nodes[1]); // value
2493 compile_node(comp, pns->nodes[0]); // key
2494}
2495
Damiend99b0522013-12-21 18:17:45 +00002496void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002497 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002498 // store class object into class name
Damien Georgeb9791222014-01-23 00:34:21 +00002499 EMIT_ARG(store_id, cname);
Damien429d7192013-10-04 19:53:11 +01002500}
2501
Damiend99b0522013-12-21 18:17:45 +00002502void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002503 if (comp->have_star_arg) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002504 compile_syntax_error(comp, "?can't have multiple *x");
Damien429d7192013-10-04 19:53:11 +01002505 return;
2506 }
2507 comp->have_star_arg = true;
2508 compile_node(comp, pns->nodes[0]);
2509}
2510
Damiend99b0522013-12-21 18:17:45 +00002511void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002512 if (comp->have_dbl_star_arg) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002513 compile_syntax_error(comp, "?can't have multiple **x");
Damien429d7192013-10-04 19:53:11 +01002514 return;
2515 }
2516 comp->have_dbl_star_arg = true;
2517 compile_node(comp, pns->nodes[0]);
2518}
2519
Damiend99b0522013-12-21 18:17:45 +00002520void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
2521 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2522 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2523 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
2524 if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002525 compile_syntax_error(comp, "?lhs of keyword argument must be an id");
Damien429d7192013-10-04 19:53:11 +01002526 return;
2527 }
Damien Georgeb9791222014-01-23 00:34:21 +00002528 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002529 compile_node(comp, pns2->nodes[0]);
2530 comp->n_arg_keyword += 1;
Damiend99b0522013-12-21 18:17:45 +00002531 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002532 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2533 } else {
2534 // shouldn't happen
2535 assert(0);
2536 }
2537}
2538
Damiend99b0522013-12-21 18:17:45 +00002539void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002540 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002541 compile_syntax_error(comp, "'yield' outside function");
Damien429d7192013-10-04 19:53:11 +01002542 return;
2543 }
Damiend99b0522013-12-21 18:17:45 +00002544 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00002545 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002546 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002547 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2548 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002549 compile_node(comp, pns->nodes[0]);
2550 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002551 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002552 EMIT(yield_from);
2553 } else {
2554 compile_node(comp, pns->nodes[0]);
2555 EMIT(yield_value);
2556 }
2557}
2558
Damiend99b0522013-12-21 18:17:45 +00002559typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002560STATIC compile_function_t compile_function[] = {
Damien429d7192013-10-04 19:53:11 +01002561 NULL,
2562#define nc NULL
2563#define c(f) compile_##f
Damien George1dc76af2014-02-26 16:57:08 +00002564#define DEF_RULE(rule, comp, kind, ...) comp,
Damien429d7192013-10-04 19:53:11 +01002565#include "grammar.h"
2566#undef nc
2567#undef c
2568#undef DEF_RULE
2569};
2570
Damiend99b0522013-12-21 18:17:45 +00002571void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2572 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002573 // pass
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02002574 } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
2575 machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
2576 EMIT_ARG(load_const_small_int, arg);
Damiend99b0522013-12-21 18:17:45 +00002577 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02002578 machine_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +00002579 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002580 case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
Damien Georgeb9791222014-01-23 00:34:21 +00002581 case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
2582 case MP_PARSE_NODE_DECIMAL: EMIT_ARG(load_const_dec, arg); break;
2583 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg, false); break;
2584 case MP_PARSE_NODE_BYTES: EMIT_ARG(load_const_str, arg, true); break;
Damiend99b0522013-12-21 18:17:45 +00002585 case MP_PARSE_NODE_TOKEN:
2586 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002587 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002588 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002589 // do nothing
2590 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002591 EMIT_ARG(load_const_tok, arg);
Damien91d387d2013-10-09 15:09:52 +01002592 }
2593 break;
Damien429d7192013-10-04 19:53:11 +01002594 default: assert(0);
2595 }
2596 } else {
Damiend99b0522013-12-21 18:17:45 +00002597 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien Georgeb9791222014-01-23 00:34:21 +00002598 EMIT_ARG(set_line_number, pns->source_line);
Damiend99b0522013-12-21 18:17:45 +00002599 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien429d7192013-10-04 19:53:11 +01002600 if (f == NULL) {
Damiend99b0522013-12-21 18:17:45 +00002601 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
Damien Georgecbd2f742014-01-19 11:48:48 +00002602#if MICROPY_DEBUG_PRINTERS
2603 mp_parse_node_print(pn, 0);
2604#endif
Damien429d7192013-10-04 19:53:11 +01002605 assert(0);
2606 } else {
2607 f(comp, pns);
2608 }
2609 }
2610}
2611
Damiend99b0522013-12-21 18:17:45 +00002612void 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 +01002613 // TODO verify that *k and **k are last etc
Damien429d7192013-10-04 19:53:11 +01002614 qstr param_name = 0;
Damiend99b0522013-12-21 18:17:45 +00002615 mp_parse_node_t pn_annotation = MP_PARSE_NODE_NULL;
2616 if (MP_PARSE_NODE_IS_ID(pn)) {
2617 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01002618 if (comp->have_bare_star) {
2619 // comes after a bare star, so doesn't count as a parameter
2620 } else {
2621 comp->scope_cur->num_params += 1;
2622 }
Damienb14de212013-10-06 00:28:28 +01002623 } else {
Damiend99b0522013-12-21 18:17:45 +00002624 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2625 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2626 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2627 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002628 //int node_index = 1; unused
2629 if (allow_annotations) {
Damiend99b0522013-12-21 18:17:45 +00002630 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002631 // this parameter has an annotation
2632 pn_annotation = pns->nodes[1];
2633 }
2634 //node_index = 2; unused
2635 }
2636 /* this is obsolete now that num dict/default params are calculated in compile_funcdef_param
Damiend99b0522013-12-21 18:17:45 +00002637 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[node_index])) {
Damienb14de212013-10-06 00:28:28 +01002638 // this parameter has a default value
2639 if (comp->have_bare_star) {
2640 comp->scope_cur->num_dict_params += 1;
2641 } else {
2642 comp->scope_cur->num_default_params += 1;
2643 }
2644 }
2645 */
2646 if (comp->have_bare_star) {
2647 // comes after a bare star, so doesn't count as a parameter
2648 } else {
2649 comp->scope_cur->num_params += 1;
2650 }
Damiend99b0522013-12-21 18:17:45 +00002651 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2652 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002653 // bare star
2654 // TODO see http://www.python.org/dev/peps/pep-3102/
2655 comp->have_bare_star = true;
2656 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002657 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002658 // named star
Damien George8725f8f2014-02-15 19:33:11 +00002659 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002660 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2661 } else if (allow_annotations && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
Damienb14de212013-10-06 00:28:28 +01002662 // named star with annotation
Damien George8725f8f2014-02-15 19:33:11 +00002663 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002664 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2665 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002666 pn_annotation = pns->nodes[1];
2667 } else {
2668 // shouldn't happen
2669 assert(0);
2670 }
Damiend99b0522013-12-21 18:17:45 +00002671 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star) {
2672 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2673 if (allow_annotations && !MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damienb14de212013-10-06 00:28:28 +01002674 // this parameter has an annotation
2675 pn_annotation = pns->nodes[1];
2676 }
Damien George8725f8f2014-02-15 19:33:11 +00002677 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002678 } else {
Damienb14de212013-10-06 00:28:28 +01002679 // TODO anything to implement?
Damien429d7192013-10-04 19:53:11 +01002680 assert(0);
2681 }
Damien429d7192013-10-04 19:53:11 +01002682 }
2683
2684 if (param_name != 0) {
Damiend99b0522013-12-21 18:17:45 +00002685 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien429d7192013-10-04 19:53:11 +01002686 // TODO this parameter has an annotation
2687 }
2688 bool added;
2689 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2690 if (!added) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002691 compile_syntax_error(comp, "?same name used for parameter");
Damien429d7192013-10-04 19:53:11 +01002692 return;
2693 }
2694 id_info->param = true;
2695 id_info->kind = ID_INFO_KIND_LOCAL;
2696 }
2697}
2698
Damiend99b0522013-12-21 18:17:45 +00002699void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002700 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star, true);
2701}
2702
Damiend99b0522013-12-21 18:17:45 +00002703void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002704 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star, false);
2705}
2706
Damiend99b0522013-12-21 18:17:45 +00002707void 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 +01002708 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002709 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002710 // no more nested if/for; compile inner expression
2711 compile_node(comp, pn_inner_expr);
2712 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002713 EMIT_ARG(list_append, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002714 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002715 EMIT_ARG(map_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002716 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002717 EMIT_ARG(set_add, for_depth + 2);
Damien429d7192013-10-04 19:53:11 +01002718 } else {
2719 EMIT(yield_value);
2720 EMIT(pop_top);
2721 }
Damiend99b0522013-12-21 18:17:45 +00002722 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
Damien429d7192013-10-04 19:53:11 +01002723 // if condition
Damiend99b0522013-12-21 18:17:45 +00002724 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002725 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2726 pn_iter = pns_comp_if->nodes[1];
2727 goto tail_recursion;
Damiend99b0522013-12-21 18:17:45 +00002728 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)) {
Damien429d7192013-10-04 19:53:11 +01002729 // for loop
Damiend99b0522013-12-21 18:17:45 +00002730 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002731 compile_node(comp, pns_comp_for2->nodes[1]);
Damienb05d7072013-10-05 13:37:10 +01002732 int l_end2 = comp_next_label(comp);
2733 int l_top2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002734 EMIT(get_iter);
Damien Georgeb9791222014-01-23 00:34:21 +00002735 EMIT_ARG(label_assign, l_top2);
2736 EMIT_ARG(for_iter, l_end2);
Damien429d7192013-10-04 19:53:11 +01002737 c_assign(comp, pns_comp_for2->nodes[0], ASSIGN_STORE);
2738 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 +00002739 EMIT_ARG(jump, l_top2);
2740 EMIT_ARG(label_assign, l_end2);
Damien429d7192013-10-04 19:53:11 +01002741 EMIT(for_iter_end);
2742 } else {
2743 // shouldn't happen
2744 assert(0);
2745 }
2746}
2747
Damiend99b0522013-12-21 18:17:45 +00002748void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien429d7192013-10-04 19:53:11 +01002749 // see http://www.python.org/dev/peps/pep-0257/
2750
2751 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002752 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002753 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002754 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002755 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002756 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2757 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002758 for (int i = 0; i < num_nodes; i++) {
2759 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002760 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 +00002761 // not a newline, so this is the first statement; finish search
2762 break;
2763 }
2764 }
2765 // 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 +00002766 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002767 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002768 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002769 } else {
2770 return;
2771 }
2772
2773 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002774 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
2775 mp_parse_node_struct_t* pns = (mp_parse_node_struct_t*)pn;
2776 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[0])) {
2777 int kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]);
2778 if (kind == MP_PARSE_NODE_STRING) {
Damien429d7192013-10-04 19:53:11 +01002779 compile_node(comp, pns->nodes[0]); // a doc string
2780 // store doc string
Damien Georgeb9791222014-01-23 00:34:21 +00002781 EMIT_ARG(store_id, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002782 }
2783 }
2784 }
2785}
2786
2787void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2788 comp->pass = pass;
2789 comp->scope_cur = scope;
Damienb05d7072013-10-05 13:37:10 +01002790 comp->next_label = 1;
Damien Georgeb9791222014-01-23 00:34:21 +00002791 EMIT_ARG(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002792
2793 if (comp->pass == PASS_1) {
2794 scope->stack_size = 0;
2795 }
2796
Damien5ac1b2e2013-10-18 19:58:12 +01002797#if MICROPY_EMIT_CPYTHON
Damien429d7192013-10-04 19:53:11 +01002798 if (comp->pass == PASS_3) {
Damien429d7192013-10-04 19:53:11 +01002799 scope_print_info(scope);
2800 }
Damien5ac1b2e2013-10-18 19:58:12 +01002801#endif
Damien429d7192013-10-04 19:53:11 +01002802
2803 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002804 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2805 assert(scope->kind == SCOPE_MODULE);
2806 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2807 compile_node(comp, pns->nodes[0]); // compile the expression
2808 EMIT(return_value);
2809 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002810 if (!comp->is_repl) {
2811 check_for_doc_string(comp, scope->pn);
2812 }
Damien429d7192013-10-04 19:53:11 +01002813 compile_node(comp, scope->pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002814 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002815 EMIT(return_value);
2816 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002817 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2818 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2819 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002820
2821 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002822 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002823 if (comp->pass == PASS_1) {
2824 comp->have_bare_star = false;
2825 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
2826 }
2827
Paul Sokolovsky2f0b0262014-02-10 02:04:26 +02002828 // pns->nodes[2] is return/whole function annotation
Damien429d7192013-10-04 19:53:11 +01002829
2830 compile_node(comp, pns->nodes[3]); // 3 is function body
2831 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002832 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00002833 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002834 EMIT(return_value);
2835 }
2836 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00002837 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2838 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2839 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01002840
2841 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002842 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien429d7192013-10-04 19:53:11 +01002843 if (comp->pass == PASS_1) {
2844 comp->have_bare_star = false;
2845 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
2846 }
2847
2848 compile_node(comp, pns->nodes[1]); // 1 is lambda body
2849 EMIT(return_value);
2850 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
2851 // a bit of a hack at the moment
2852
Damiend99b0522013-12-21 18:17:45 +00002853 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2854 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2855 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2856 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2857 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002858
Damien George55baff42014-01-21 21:40:13 +00002859 qstr qstr_arg = QSTR_FROM_STR_STATIC(".0");
Damien429d7192013-10-04 19:53:11 +01002860 if (comp->pass == PASS_1) {
2861 bool added;
2862 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
2863 assert(added);
2864 id_info->kind = ID_INFO_KIND_LOCAL;
2865 scope->num_params = 1;
2866 }
2867
2868 if (scope->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002869 EMIT_ARG(build_list, 0);
Damien429d7192013-10-04 19:53:11 +01002870 } else if (scope->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002871 EMIT_ARG(build_map, 0);
Damien429d7192013-10-04 19:53:11 +01002872 } else if (scope->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00002873 EMIT_ARG(build_set, 0);
Damien429d7192013-10-04 19:53:11 +01002874 }
2875
Damienb05d7072013-10-05 13:37:10 +01002876 int l_end = comp_next_label(comp);
2877 int l_top = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002878 EMIT_ARG(load_id, qstr_arg);
2879 EMIT_ARG(label_assign, l_top);
2880 EMIT_ARG(for_iter, l_end);
Damien429d7192013-10-04 19:53:11 +01002881 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2882 compile_scope_comp_iter(comp, pns_comp_for->nodes[2], pns->nodes[0], l_top, 0);
Damien Georgeb9791222014-01-23 00:34:21 +00002883 EMIT_ARG(jump, l_top);
2884 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002885 EMIT(for_iter_end);
2886
2887 if (scope->kind == SCOPE_GEN_EXPR) {
Damien Georgeb9791222014-01-23 00:34:21 +00002888 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002889 }
2890 EMIT(return_value);
2891 } else {
2892 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00002893 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2894 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2895 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01002896
2897 if (comp->pass == PASS_1) {
2898 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002899 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01002900 assert(added);
2901 id_info->kind = ID_INFO_KIND_LOCAL;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002902 id_info = scope_find_or_add_id(scope, MP_QSTR___locals__, &added);
Damien429d7192013-10-04 19:53:11 +01002903 assert(added);
2904 id_info->kind = ID_INFO_KIND_LOCAL;
2905 id_info->param = true;
2906 scope->num_params = 1; // __locals__ is the parameter
2907 }
2908
Damien Georgeb9791222014-01-23 00:34:21 +00002909 EMIT_ARG(load_id, MP_QSTR___locals__);
Damien429d7192013-10-04 19:53:11 +01002910 EMIT(store_locals);
Damien Georgeb9791222014-01-23 00:34:21 +00002911 EMIT_ARG(load_id, MP_QSTR___name__);
2912 EMIT_ARG(store_id, MP_QSTR___module__);
2913 EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
2914 EMIT_ARG(store_id, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01002915
2916 check_for_doc_string(comp, pns->nodes[2]);
2917 compile_node(comp, pns->nodes[2]); // 2 is class body
2918
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00002919 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01002920 assert(id != NULL);
2921 if (id->kind == ID_INFO_KIND_LOCAL) {
Damien Georgeb9791222014-01-23 00:34:21 +00002922 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002923 } else {
Damien George6baf76e2013-12-30 22:32:17 +00002924#if MICROPY_EMIT_CPYTHON
Damien Georgeb9791222014-01-23 00:34:21 +00002925 EMIT_ARG(load_closure, MP_QSTR___class__, 0); // XXX check this is the correct local num
Damien George6baf76e2013-12-30 22:32:17 +00002926#else
Damien George35e2a4e2014-02-05 00:51:47 +00002927 EMIT_ARG(load_fast, MP_QSTR___class__, id->local_num);
Damien George6baf76e2013-12-30 22:32:17 +00002928#endif
Damien429d7192013-10-04 19:53:11 +01002929 }
2930 EMIT(return_value);
2931 }
2932
Damien415eb6f2013-10-05 12:19:06 +01002933 EMIT(end_pass);
Damien826005c2013-10-05 23:17:28 +01002934}
2935
2936void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2937 comp->pass = pass;
2938 comp->scope_cur = scope;
2939 comp->next_label = 1;
2940
2941 if (scope->kind != SCOPE_FUNCTION) {
2942 printf("Error: inline assembler must be a function\n");
2943 return;
2944 }
2945
Damiena2f2f7d2013-10-06 00:14:13 +01002946 if (comp->pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00002947 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur);
Damiena2f2f7d2013-10-06 00:14:13 +01002948 }
2949
Damien826005c2013-10-05 23:17:28 +01002950 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00002951 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2952 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2953 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01002954
Damiend99b0522013-12-21 18:17:45 +00002955 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01002956
Damiena2f2f7d2013-10-06 00:14:13 +01002957 // parameters are in pns->nodes[1]
2958 if (comp->pass == PASS_2) {
Damiend99b0522013-12-21 18:17:45 +00002959 mp_parse_node_t *pn_params;
Damiena2f2f7d2013-10-06 00:14:13 +01002960 int n_params = list_get(&pns->nodes[1], PN_typedargslist, &pn_params);
Damien Georgeb9791222014-01-23 00:34:21 +00002961 scope->num_params = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
Damiena2f2f7d2013-10-06 00:14:13 +01002962 }
2963
Damiend99b0522013-12-21 18:17:45 +00002964 assert(MP_PARSE_NODE_IS_NULL(pns->nodes[2])); // type
Damien826005c2013-10-05 23:17:28 +01002965
Damiend99b0522013-12-21 18:17:45 +00002966 mp_parse_node_t pn_body = pns->nodes[3]; // body
2967 mp_parse_node_t *nodes;
Damien826005c2013-10-05 23:17:28 +01002968 int num = list_get(&pn_body, PN_suite_block_stmts, &nodes);
2969
Damien Georgecbd2f742014-01-19 11:48:48 +00002970 /*
Damien826005c2013-10-05 23:17:28 +01002971 if (comp->pass == PASS_3) {
2972 //printf("----\n");
2973 scope_print_info(scope);
2974 }
Damien Georgecbd2f742014-01-19 11:48:48 +00002975 */
Damien826005c2013-10-05 23:17:28 +01002976
2977 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00002978 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
2979 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
2980 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_expr_stmt);
2981 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
2982 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[1]));
2983 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
2984 assert(MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_power);
2985 assert(MP_PARSE_NODE_IS_ID(pns2->nodes[0]));
2986 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren));
2987 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
2988 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
2989 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
2990 mp_parse_node_t *pn_arg;
Damien826005c2013-10-05 23:17:28 +01002991 int n_args = list_get(&pns2->nodes[0], PN_arglist, &pn_arg);
2992
2993 // emit instructions
2994 if (strcmp(qstr_str(op), "label") == 0) {
Damiend99b0522013-12-21 18:17:45 +00002995 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien Georgef41fdd02014-03-03 23:19:11 +00002996 compile_syntax_error(comp, "inline assembler 'label' requires 1 argument");
Damien826005c2013-10-05 23:17:28 +01002997 return;
2998 }
2999 int lab = comp_next_label(comp);
3000 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00003001 EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]));
Damien826005c2013-10-05 23:17:28 +01003002 }
3003 } else {
3004 if (pass > PASS_1) {
Damien Georgeb9791222014-01-23 00:34:21 +00003005 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
Damien826005c2013-10-05 23:17:28 +01003006 }
3007 }
3008 }
3009
3010 if (comp->pass > PASS_1) {
3011 EMIT_INLINE_ASM(end_pass);
Damienb05d7072013-10-05 13:37:10 +01003012 }
Damien429d7192013-10-04 19:53:11 +01003013}
3014
3015void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
3016 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00003017 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01003018 scope->num_locals = 0;
3019 for (int i = 0; i < scope->id_info_len; i++) {
3020 id_info_t *id = &scope->id_info[i];
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003021 if (scope->kind == SCOPE_CLASS && id->qstr == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01003022 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
3023 continue;
3024 }
3025 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
3026 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
3027 }
Damien9ecbcff2013-12-11 00:41:43 +00003028 // note: params always count for 1 local, even if they are a cell
Damien429d7192013-10-04 19:53:11 +01003029 if (id->param || id->kind == ID_INFO_KIND_LOCAL) {
3030 id->local_num = scope->num_locals;
3031 scope->num_locals += 1;
Damien9ecbcff2013-12-11 00:41:43 +00003032 }
3033 }
3034
3035 // compute the index of cell vars (freevars[idx] in CPython)
Damien George6baf76e2013-12-30 22:32:17 +00003036#if MICROPY_EMIT_CPYTHON
3037 int num_cell = 0;
3038#endif
Damien9ecbcff2013-12-11 00:41:43 +00003039 for (int i = 0; i < scope->id_info_len; i++) {
3040 id_info_t *id = &scope->id_info[i];
Damien George6baf76e2013-12-30 22:32:17 +00003041#if MICROPY_EMIT_CPYTHON
3042 // in CPython the cells are numbered starting from 0
Damien9ecbcff2013-12-11 00:41:43 +00003043 if (id->kind == ID_INFO_KIND_CELL) {
Damien George6baf76e2013-12-30 22:32:17 +00003044 id->local_num = num_cell;
3045 num_cell += 1;
Damien9ecbcff2013-12-11 00:41:43 +00003046 }
Damien George6baf76e2013-12-30 22:32:17 +00003047#else
3048 // in Micro Python the cells come right after the fast locals
3049 // parameters are not counted here, since they remain at the start
3050 // of the locals, even if they are cell vars
3051 if (!id->param && id->kind == ID_INFO_KIND_CELL) {
3052 id->local_num = scope->num_locals;
3053 scope->num_locals += 1;
3054 }
3055#endif
Damien9ecbcff2013-12-11 00:41:43 +00003056 }
Damien9ecbcff2013-12-11 00:41:43 +00003057
3058 // compute the index of free vars (freevars[idx] in CPython)
3059 // make sure they are in the order of the parent scope
3060 if (scope->parent != NULL) {
3061 int num_free = 0;
3062 for (int i = 0; i < scope->parent->id_info_len; i++) {
3063 id_info_t *id = &scope->parent->id_info[i];
3064 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3065 for (int j = 0; j < scope->id_info_len; j++) {
3066 id_info_t *id2 = &scope->id_info[j];
3067 if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George6baf76e2013-12-30 22:32:17 +00003068 assert(!id2->param); // free vars should not be params
3069#if MICROPY_EMIT_CPYTHON
3070 // in CPython the frees are numbered after the cells
3071 id2->local_num = num_cell + num_free;
3072#else
3073 // in Micro Python the frees come first, before the params
3074 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00003075#endif
3076 num_free += 1;
3077 }
3078 }
3079 }
Damien429d7192013-10-04 19:53:11 +01003080 }
Damien George6baf76e2013-12-30 22:32:17 +00003081#if !MICROPY_EMIT_CPYTHON
3082 // in Micro Python shift all other locals after the free locals
3083 if (num_free > 0) {
3084 for (int i = 0; i < scope->id_info_len; i++) {
3085 id_info_t *id = &scope->id_info[i];
3086 if (id->param || id->kind != ID_INFO_KIND_FREE) {
3087 id->local_num += num_free;
3088 }
3089 }
3090 scope->num_params += num_free; // free vars are counted as params for passing them into the function
3091 scope->num_locals += num_free;
3092 }
3093#endif
Damien429d7192013-10-04 19:53:11 +01003094 }
3095
Damien George8725f8f2014-02-15 19:33:11 +00003096 // compute scope_flags
3097 //scope->scope_flags = 0; since we set some things in parameters
Damien429d7192013-10-04 19:53:11 +01003098 if (scope->kind != SCOPE_MODULE) {
Damien George8725f8f2014-02-15 19:33:11 +00003099 scope->scope_flags |= MP_SCOPE_FLAG_NEWLOCALS;
Damien429d7192013-10-04 19:53:11 +01003100 }
3101 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) {
3102 assert(scope->parent != NULL);
Damien George8725f8f2014-02-15 19:33:11 +00003103 scope->scope_flags |= MP_SCOPE_FLAG_OPTIMISED;
Damien429d7192013-10-04 19:53:11 +01003104
3105 // TODO possibly other ways it can be nested
Damien George08d07552014-01-29 18:58:52 +00003106 // Note that we don't actually use this information at the moment (for CPython compat only)
3107 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 +00003108 scope->scope_flags |= MP_SCOPE_FLAG_NESTED;
Damien429d7192013-10-04 19:53:11 +01003109 }
3110 }
3111 int num_free = 0;
3112 for (int i = 0; i < scope->id_info_len; i++) {
3113 id_info_t *id = &scope->id_info[i];
3114 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3115 num_free += 1;
3116 }
3117 }
3118 if (num_free == 0) {
Damien George8725f8f2014-02-15 19:33:11 +00003119 scope->scope_flags |= MP_SCOPE_FLAG_NOFREE;
Damien429d7192013-10-04 19:53:11 +01003120 }
3121}
3122
Damien George08335002014-01-18 23:24:36 +00003123mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
Damien429d7192013-10-04 19:53:11 +01003124 compiler_t *comp = m_new(compiler_t, 1);
3125
Damien Georgecbd2f742014-01-19 11:48:48 +00003126 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003127 comp->is_repl = is_repl;
3128 comp->had_error = false;
3129
Damien429d7192013-10-04 19:53:11 +01003130 comp->break_label = 0;
3131 comp->continue_label = 0;
Damien Georgecbddb272014-02-01 20:08:18 +00003132 comp->break_continue_except_level = 0;
3133 comp->cur_except_level = 0;
3134
Damien George35e2a4e2014-02-05 00:51:47 +00003135 comp->func_arg_is_super = false;
3136
Damien429d7192013-10-04 19:53:11 +01003137 comp->scope_head = NULL;
3138 comp->scope_cur = NULL;
3139
Damien826005c2013-10-05 23:17:28 +01003140 // optimise constants
Damien429d7192013-10-04 19:53:11 +01003141 pn = fold_constants(pn);
Damien826005c2013-10-05 23:17:28 +01003142
3143 // set the outer scope
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003144 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE);
Damien429d7192013-10-04 19:53:11 +01003145
Damien826005c2013-10-05 23:17:28 +01003146 // compile pass 1
Damien George35e2a4e2014-02-05 00:51:47 +00003147 comp->emit = emit_pass1_new();
Damien826005c2013-10-05 23:17:28 +01003148 comp->emit_method_table = &emit_pass1_method_table;
3149 comp->emit_inline_asm = NULL;
3150 comp->emit_inline_asm_method_table = NULL;
3151 uint max_num_labels = 0;
Damien5ac1b2e2013-10-18 19:58:12 +01003152 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003153 if (false) {
Damien3ef4abb2013-10-12 16:53:13 +01003154#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003155 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
Damien826005c2013-10-05 23:17:28 +01003156 compile_scope_inline_asm(comp, s, PASS_1);
Damienc025ebb2013-10-12 14:30:21 +01003157#endif
Damien826005c2013-10-05 23:17:28 +01003158 } else {
3159 compile_scope(comp, s, PASS_1);
3160 }
3161
3162 // update maximim number of labels needed
3163 if (comp->next_label > max_num_labels) {
3164 max_num_labels = comp->next_label;
3165 }
Damien429d7192013-10-04 19:53:11 +01003166 }
3167
Damien826005c2013-10-05 23:17:28 +01003168 // compute some things related to scope and identifiers
Damien5ac1b2e2013-10-18 19:58:12 +01003169 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damien429d7192013-10-04 19:53:11 +01003170 compile_scope_compute_things(comp, s);
3171 }
3172
Damien826005c2013-10-05 23:17:28 +01003173 // finish with pass 1
Damien6cdd3af2013-10-05 18:08:26 +01003174 emit_pass1_free(comp->emit);
3175
Damien826005c2013-10-05 23:17:28 +01003176 // compile pass 2 and 3
Damien3ef4abb2013-10-12 16:53:13 +01003177#if !MICROPY_EMIT_CPYTHON
Damien6cdd3af2013-10-05 18:08:26 +01003178 emit_t *emit_bc = NULL;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003179#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003180 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003181#endif
Damien3ef4abb2013-10-12 16:53:13 +01003182#if MICROPY_EMIT_INLINE_THUMB
Damien826005c2013-10-05 23:17:28 +01003183 emit_inline_asm_t *emit_inline_thumb = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003184#endif
Damien Georgee67ed5d2014-01-04 13:55:24 +00003185#endif // !MICROPY_EMIT_CPYTHON
Damien5ac1b2e2013-10-18 19:58:12 +01003186 for (scope_t *s = comp->scope_head; s != NULL && !comp->had_error; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003187 if (false) {
3188 // dummy
3189
Damien3ef4abb2013-10-12 16:53:13 +01003190#if MICROPY_EMIT_INLINE_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003191 } else if (s->emit_options == EMIT_OPT_ASM_THUMB) {
3192 // inline assembly for thumb
Damien826005c2013-10-05 23:17:28 +01003193 if (emit_inline_thumb == NULL) {
3194 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
3195 }
3196 comp->emit = NULL;
3197 comp->emit_method_table = NULL;
3198 comp->emit_inline_asm = emit_inline_thumb;
3199 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
3200 compile_scope_inline_asm(comp, s, PASS_2);
3201 compile_scope_inline_asm(comp, s, PASS_3);
Damienc025ebb2013-10-12 14:30:21 +01003202#endif
3203
Damien826005c2013-10-05 23:17:28 +01003204 } else {
Damienc025ebb2013-10-12 14:30:21 +01003205
3206 // choose the emit type
3207
Damien3ef4abb2013-10-12 16:53:13 +01003208#if MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003209 comp->emit = emit_cpython_new(max_num_labels);
3210 comp->emit_method_table = &emit_cpython_method_table;
3211#else
Damien826005c2013-10-05 23:17:28 +01003212 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003213
3214#if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003215 case EMIT_OPT_NATIVE_PYTHON:
Damien3410be82013-10-07 23:09:10 +01003216 case EMIT_OPT_VIPER:
Damien3ef4abb2013-10-12 16:53:13 +01003217#if MICROPY_EMIT_X64
Damiendc833822013-10-06 01:01:01 +01003218 if (emit_native == NULL) {
Damien13ed3a62013-10-08 09:05:10 +01003219 emit_native = emit_native_x64_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003220 }
Damien13ed3a62013-10-08 09:05:10 +01003221 comp->emit_method_table = &emit_native_x64_method_table;
Damien3ef4abb2013-10-12 16:53:13 +01003222#elif MICROPY_EMIT_THUMB
Damienc025ebb2013-10-12 14:30:21 +01003223 if (emit_native == NULL) {
3224 emit_native = emit_native_thumb_new(max_num_labels);
3225 }
3226 comp->emit_method_table = &emit_native_thumb_method_table;
3227#endif
3228 comp->emit = emit_native;
Damien3410be82013-10-07 23:09:10 +01003229 comp->emit_method_table->set_native_types(comp->emit, s->emit_options == EMIT_OPT_VIPER);
Damien7af3d192013-10-07 00:02:49 +01003230 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003231#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003232
Damien826005c2013-10-05 23:17:28 +01003233 default:
3234 if (emit_bc == NULL) {
Damien Georgecbd2f742014-01-19 11:48:48 +00003235 emit_bc = emit_bc_new(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003236 }
3237 comp->emit = emit_bc;
3238 comp->emit_method_table = &emit_bc_method_table;
3239 break;
3240 }
Damien Georgee67ed5d2014-01-04 13:55:24 +00003241#endif // !MICROPY_EMIT_CPYTHON
Damienc025ebb2013-10-12 14:30:21 +01003242
3243 // compile pass 2 and pass 3
Damien826005c2013-10-05 23:17:28 +01003244 compile_scope(comp, s, PASS_2);
3245 compile_scope(comp, s, PASS_3);
Damien6cdd3af2013-10-05 18:08:26 +01003246 }
Damien429d7192013-10-04 19:53:11 +01003247 }
3248
Damien George41d02b62014-01-24 22:42:28 +00003249 // free the emitters
3250#if !MICROPY_EMIT_CPYTHON
3251 if (emit_bc != NULL) {
3252 emit_bc_free(emit_bc);
Paul Sokolovskyf46d87a2014-01-24 16:20:11 +02003253 }
Damien George41d02b62014-01-24 22:42:28 +00003254#if MICROPY_EMIT_NATIVE
3255 if (emit_native != NULL) {
3256#if MICROPY_EMIT_X64
3257 emit_native_x64_free(emit_native);
3258#elif MICROPY_EMIT_THUMB
3259 emit_native_thumb_free(emit_native);
3260#endif
3261 }
3262#endif
3263#if MICROPY_EMIT_INLINE_THUMB
3264 if (emit_inline_thumb != NULL) {
3265 emit_inline_thumb_free(emit_inline_thumb);
3266 }
3267#endif
3268#endif // !MICROPY_EMIT_CPYTHON
3269
3270 // free the scopes
Paul Sokolovskyfd313582014-01-23 23:05:47 +02003271 uint unique_code_id = module_scope->unique_code_id;
3272 for (scope_t *s = module_scope; s;) {
3273 scope_t *next = s->next;
3274 scope_free(s);
3275 s = next;
3276 }
Damien5ac1b2e2013-10-18 19:58:12 +01003277
Damien George41d02b62014-01-24 22:42:28 +00003278 // free the compiler
3279 bool had_error = comp->had_error;
3280 m_del_obj(compiler_t, comp);
3281
Damien George1fb03172014-01-03 14:22:03 +00003282 if (had_error) {
3283 // TODO return a proper error message
3284 return mp_const_none;
3285 } else {
3286#if MICROPY_EMIT_CPYTHON
3287 // can't create code, so just return true
Damien George41d02b62014-01-24 22:42:28 +00003288 (void)unique_code_id; // to suppress warning that unique_code_id is unused
Damien George1fb03172014-01-03 14:22:03 +00003289 return mp_const_true;
3290#else
3291 // return function that executes the outer module
Paul Sokolovsky90750022014-02-01 15:05:04 +02003292 return rt_make_function_from_id(unique_code_id, MP_OBJ_NULL);
Damien George1fb03172014-01-03 14:22:03 +00003293#endif
3294 }
Damien429d7192013-10-04 19:53:11 +01003295}