compile.c 152 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * This file is part of the Micro Python project, http://micropython.org/
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013, 2014 Damien P. George
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

xbe's avatar
xbe committed
27
#include <stdbool.h>
Damien's avatar
Damien committed
28
29
30
31
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
32
#include <math.h>
Damien's avatar
Damien committed
33

34
35
36
37
38
39
#include "py/scope.h"
#include "py/emit.h"
#include "py/compile.h"
#include "py/smallint.h"
#include "py/runtime.h"
#include "py/builtin.h"
Damien's avatar
Damien committed
40
41
42
43

// TODO need to mangle __attr names

typedef enum {
44
#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
45
#include "py/grammar.h"
Damien's avatar
Damien committed
46
47
#undef DEF_RULE
    PN_maximum_number_of,
48
    PN_string, // special node for non-interned string
49
    PN_bytes, // special node for non-interned bytes
50
    PN_const_object, // special node for a constant, generic Python object
Damien's avatar
Damien committed
51
52
} pn_kind_t;

53
54
55
56
#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
Damien's avatar
Damien committed
57

58
// elements in this struct are ordered to make it compact
Damien's avatar
Damien committed
59
typedef struct _compiler_t {
60
    qstr source_file;
61

62
63
64
    uint8_t is_repl;
    uint8_t pass; // holds enum type pass_kind_t
    uint8_t func_arg_is_super; // used to compile special case of super() function call
65
66
67
68
69
    uint8_t have_star;

    // try to keep compiler clean from nlr
    // this is set to an exception object if we have a compile error
    mp_obj_t compile_error;
Damien's avatar
Damien committed
70

71
    uint next_label;
72

73
74
75
    uint16_t num_dict_params;
    uint16_t num_default_params;

76
77
    uint16_t break_label; // highest bit set indicates we are breaking out of a for loop
    uint16_t continue_label;
78
    uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
79
    uint16_t break_continue_except_level;
Damien's avatar
Damien committed
80
81
82
83

    scope_t *scope_head;
    scope_t *scope_cur;

84
85
    emit_t *emit;                                   // current emitter
    const emit_method_table_t *emit_method_table;   // current emit method table
86
87
88

    emit_inline_asm_t *emit_inline_asm;                                   // current emitter for inline asm
    const emit_inline_asm_method_table_t *emit_inline_asm_method_table;   // current emit method table for inline asm
Damien's avatar
Damien committed
89
90
} compiler_t;

91
STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
92
93
    mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
    // we don't have a 'block' name, so just pass the NULL qstr to indicate this
94
    if (MP_PARSE_NODE_IS_STRUCT(pn)) {
95
        mp_obj_exception_add_traceback(exc, comp->source_file, (mp_uint_t)((mp_parse_node_struct_t*)pn)->source_line, comp->scope_cur->simple_name);
96
    } else {
97
        // we don't have a line number, so just pass 0
98
        mp_obj_exception_add_traceback(exc, comp->source_file, 0, comp->scope_cur->simple_name);
99
    }
100
    comp->compile_error = exc;
101
102
}

103
#if MICROPY_COMP_MODULE_CONST
104
STATIC const mp_map_elem_t mp_constants_table[] = {
105
106
107
    #if MICROPY_PY_UCTYPES
    { MP_OBJ_NEW_QSTR(MP_QSTR_uctypes), (mp_obj_t)&mp_module_uctypes },
    #endif
108
    // Extra constants as defined by a port
109
    MICROPY_PORT_CONSTANTS
110
};
111
112
STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);
#endif
113

114
115
116
117
// this function is essentially a simple preprocessor
STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_map_t *consts) {
    if (0) {
        // dummy
118
#if MICROPY_COMP_CONST
119
120
121
122
123
124
125
126
127
    } else if (MP_PARSE_NODE_IS_ID(pn)) {
        // lookup identifier in table of dynamic constants
        qstr qst = MP_PARSE_NODE_LEAF_ARG(pn);
        mp_map_elem_t *elem = mp_map_lookup(consts, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
        if (elem != NULL) {
            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, MP_OBJ_SMALL_INT_VALUE(elem->value));
        }
#endif
    } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
128
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien's avatar
Damien committed
129

130
131
        // fold some parse nodes before folding their arguments
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
132
#if MICROPY_COMP_CONST
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
            case PN_expr_stmt:
                if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
                    mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
                    if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_expr_stmt_assign) {
                        if (MP_PARSE_NODE_IS_ID(pns->nodes[0])
                            && MP_PARSE_NODE_IS_STRUCT_KIND(pns1->nodes[0], PN_power)
                            && MP_PARSE_NODE_IS_ID(((mp_parse_node_struct_t*)pns1->nodes[0])->nodes[0])
                            && MP_PARSE_NODE_LEAF_ARG(((mp_parse_node_struct_t*)pns1->nodes[0])->nodes[0]) == MP_QSTR_const
                            && MP_PARSE_NODE_IS_STRUCT_KIND(((mp_parse_node_struct_t*)pns1->nodes[0])->nodes[1], PN_trailer_paren)
                            && MP_PARSE_NODE_IS_NULL(((mp_parse_node_struct_t*)pns1->nodes[0])->nodes[2])
                            ) {
                            // code to assign dynamic constants: id = const(value)

                            // get the id
                            qstr id_qstr = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);

                            // get the value
                            mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pns1->nodes[0])->nodes[1])->nodes[0];
                            pn_value = fold_constants(comp, pn_value, consts);
                            if (!MP_PARSE_NODE_IS_SMALL_INT(pn_value)) {
                                compile_syntax_error(comp, (mp_parse_node_t)pns, "constant must be an integer");
                                break;
                            }
156
                            mp_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

                            // store the value in the table of dynamic constants
                            mp_map_elem_t *elem = mp_map_lookup(consts, MP_OBJ_NEW_QSTR(id_qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
                            if (elem->value != MP_OBJ_NULL) {
                                compile_syntax_error(comp, (mp_parse_node_t)pns, "constant redefined");
                                break;
                            }
                            elem->value = MP_OBJ_NEW_SMALL_INT(value);

                            // replace const(value) with value
                            pns1->nodes[0] = pn_value;

                            // finished folding this assignment
                            return pn;
                        }
                    }
                }
                break;
#endif
176
            case PN_string:
177
            case PN_bytes:
178
            case PN_const_object:
179
                return pn;
180
181
182
183
        }

        // fold arguments
        int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien's avatar
Damien committed
184
        for (int i = 0; i < n; i++) {
185
            pns->nodes[i] = fold_constants(comp, pns->nodes[i], consts);
Damien's avatar
Damien committed
186
187
        }

188
        // try to fold this parse node
189
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
190
191
192
193
194
195
196
197
198
199
            case PN_atom_paren:
                if (n == 1 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0])) {
                    // (int)
                    pn = pns->nodes[0];
                }
                break;

            case PN_expr:
                if (n == 2 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
                    // int | int
200
201
                    mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
                    mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
202
203
204
205
206
207
208
                    pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 | arg1);
                }
                break;

            case PN_and_expr:
                if (n == 2 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
                    // int & int
209
210
                    mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
                    mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
211
212
213
214
                    pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 & arg1);
                }
                break;

Damien's avatar
Damien committed
215
            case PN_shift_expr:
216
                if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
217
218
                    mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
                    mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
219
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
220
                        // int << int
221
                        if (!(arg1 >= (mp_int_t)BITS_PER_WORD || arg0 > (MP_SMALL_INT_MAX >> arg1) || arg0 < (MP_SMALL_INT_MIN >> arg1))) {
222
223
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
                        }
224
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
225
                        // int >> int
226
                        if (arg1 >= (mp_int_t)BITS_PER_WORD) {
227
228
229
230
                            // Shifting to big amounts is underfined behavior
                            // in C and is CPU-dependent; propagate sign bit.
                            arg1 = BITS_PER_WORD - 1;
                        }
231
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien's avatar
Damien committed
232
233
234
235
236
237
238
239
                    } else {
                        // shouldn't happen
                        assert(0);
                    }
                }
                break;

            case PN_arith_expr:
240
                // overflow checking here relies on SMALL_INT being strictly smaller than mp_int_t
241
                if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
242
243
                    mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
                    mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
244
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
245
                        // int + int
246
                        arg0 += arg1;
247
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
248
                        // int - int
249
                        arg0 -= arg1;
Damien's avatar
Damien committed
250
251
252
                    } else {
                        // shouldn't happen
                        assert(0);
253
                    }
254
                    if (MP_SMALL_INT_FITS(arg0)) {
255
                        //printf("%ld + %ld\n", arg0, arg1);
256
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0);
Damien's avatar
Damien committed
257
258
259
260
261
                    }
                }
                break;

            case PN_term:
262
                if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
263
264
                    mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
                    mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
265
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
266
                        // int * int
267
268
                        if (!mp_small_int_mul_overflow(arg0, arg1)) {
                            arg0 *= arg1;
269
                            if (MP_SMALL_INT_FITS(arg0)) {
270
271
272
                                pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0);
                            }
                        }
273
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
274
275
                        // int / int
                        // pass
276
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
277
                        // int%int
278
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_modulo(arg0, arg1));
279
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
280
                        if (arg1 != 0) {
281
                            // int // int
282
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_floor_divide(arg0, arg1));
283
                        }
Damien's avatar
Damien committed
284
285
286
287
288
289
290
291
                    } else {
                        // shouldn't happen
                        assert(0);
                    }
                }
                break;

            case PN_factor_2:
292
                if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
293
                    mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
294
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
295
                        // +int
296
297
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
298
                        // -int
299
300
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)) {
301
                        // ~int
302
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien's avatar
Damien committed
303
304
305
306
307
308
309
310
                    } else {
                        // shouldn't happen
                        assert(0);
                    }
                }
                break;

            case PN_power:
311
312
313
                if (0) {
#if MICROPY_EMIT_CPYTHON
                } else 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])) {
314
                    // int ** x
315
                    // can overflow; enabled only to compare with CPython
316
317
                    mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
                    if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
318
                        int power = MP_PARSE_NODE_LEAF_SMALL_INT(pns2->nodes[0]);
Damien's avatar
Damien committed
319
320
                        if (power >= 0) {
                            int ans = 1;
321
                            int base = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
Damien's avatar
Damien committed
322
323
324
                            for (; power > 0; power--) {
                                ans *= base;
                            }
325
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien's avatar
Damien committed
326
327
                        }
                    }
328
#endif
329
#if MICROPY_COMP_MODULE_CONST
330
331
332
333
334
335
336
337
338
339
340
341
                } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_trailer_period) && MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
                    // id.id
                    // look it up in constant table, see if it can be replaced with an integer
                    mp_parse_node_struct_t* pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
                    assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
                    qstr q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
                    qstr q_attr = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);
                    mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&mp_constants_map, MP_OBJ_NEW_QSTR(q_base), MP_MAP_LOOKUP);
                    if (elem != NULL) {
                        mp_obj_t dest[2];
                        mp_load_method_maybe(elem->value, q_attr, dest);
                        if (MP_OBJ_IS_SMALL_INT(dest[0]) && dest[1] == NULL) {
342
                            mp_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
343
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, val);
344
345
                        }
                    }
346
#endif
Damien's avatar
Damien committed
347
348
349
350
351
352
353
354
                }
                break;
        }
    }

    return pn;
}

355
STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
356
STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind);
357
STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien's avatar
Damien committed
358

359
STATIC uint comp_next_label(compiler_t *comp) {
360
361
362
    return comp->next_label++;
}

363
364
365
366
367
368
369
370
371
372
373
374
STATIC void compile_increase_except_level(compiler_t *comp) {
    comp->cur_except_level += 1;
    if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {
        comp->scope_cur->exc_stack_size = comp->cur_except_level;
    }
}

STATIC void compile_decrease_except_level(compiler_t *comp) {
    assert(comp->cur_except_level > 0);
    comp->cur_except_level -= 1;
}

375
STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
376
    scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options);
Damien's avatar
Damien committed
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    scope->parent = comp->scope_cur;
    scope->next = NULL;
    if (comp->scope_head == NULL) {
        comp->scope_head = scope;
    } else {
        scope_t *s = comp->scope_head;
        while (s->next != NULL) {
            s = s->next;
        }
        s->next = scope;
    }
    return scope;
}

391
392
STATIC void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_list_kind, void (*f)(compiler_t*, mp_parse_node_t)) {
    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) {
393
394
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien's avatar
Damien committed
395
396
397
        for (int i = 0; i < num_nodes; i++) {
            f(comp, pns->nodes[i]);
        }
398
    } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
399
400
401
402
        f(comp, pn);
    }
}

403
STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
404
    int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien's avatar
Damien committed
405
406
407
408
409
    for (int i = 0; i < num_nodes; i++) {
        compile_node(comp, pns->nodes[i]);
    }
}

410
#if MICROPY_EMIT_CPYTHON
411
STATIC bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
412
413
414
    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_string)) {
        return true;
    }
415
416
417
    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_bytes)) {
        return true;
    }
418
419
420
    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_const_object)) {
        return true;
    }
421
    if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien's avatar
Damien committed
422
423
        return false;
    }
424
    if (MP_PARSE_NODE_IS_ID(pn)) {
Damien's avatar
Damien committed
425
426
427
428
429
        return false;
    }
    return true;
}

430
STATIC void cpython_c_print_quoted_str(vstr_t *vstr, const char *str, uint len, bool bytes) {
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
    bool has_single_quote = false;
    bool has_double_quote = false;
    for (int i = 0; i < len; i++) {
        if (str[i] == '\'') {
            has_single_quote = true;
        } else if (str[i] == '"') {
            has_double_quote = true;
        }
    }
    if (bytes) {
        vstr_printf(vstr, "b");
    }
    bool quote_single = false;
    if (has_single_quote && !has_double_quote) {
        vstr_printf(vstr, "\"");
    } else {
        quote_single = true;
        vstr_printf(vstr, "'");
    }
    for (int i = 0; i < len; i++) {
        if (str[i] == '\n') {
            vstr_printf(vstr, "\\n");
        } else if (str[i] == '\\') {
            vstr_printf(vstr, "\\\\");
        } else if (str[i] == '\'' && quote_single) {
            vstr_printf(vstr, "\\'");
        } else {
            vstr_printf(vstr, "%c", str[i]);
        }
    }
    if (has_single_quote && !has_double_quote) {
        vstr_printf(vstr, "\"");
    } else {
        vstr_printf(vstr, "'");
    }
}

468
STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
469
    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_string) || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_bytes)) {
470
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
471
        cpython_c_print_quoted_str(vstr, (const char*)pns->nodes[0], (mp_uint_t)pns->nodes[1], MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_bytes));
472
473
474
        return;
    }

475
476
477
478
479
480
    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_const_object)) {
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        mp_obj_print((mp_obj_t)pns->nodes[0], PRINT_REPR);
        return;
    }

481
    assert(MP_PARSE_NODE_IS_LEAF(pn));
482
483
484
485
486
    if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
        vstr_printf(vstr, INT_FMT, MP_PARSE_NODE_LEAF_SMALL_INT(pn));
        return;
    }

487
    mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
488
489
    switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
        case MP_PARSE_NODE_ID: assert(0);
490
491
        case MP_PARSE_NODE_STRING:
        case MP_PARSE_NODE_BYTES: {
492
            mp_uint_t len;
493
494
495
496
            const byte *str = qstr_data(arg, &len);
            cpython_c_print_quoted_str(vstr, (const char*)str, len, MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_BYTES);
            break;
        }
497
        case MP_PARSE_NODE_TOKEN:
Damien's avatar
Damien committed
498
            switch (arg) {
499
500
501
                case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
                case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
                case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
502
                default: assert(0); // shouldn't happen
Damien's avatar
Damien committed
503
504
505
506
507
508
            }
            break;
        default: assert(0);
    }
}

509
STATIC void cpython_c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien's avatar
Damien committed
510
511
    int n = 0;
    if (pns_list != NULL) {
512
        n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien's avatar
Damien committed
513
514
515
    }
    int total = n;
    bool is_const = true;
516
    if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
517
        total += 1;
518
        if (!cpython_c_tuple_is_const(pn)) {
Damien's avatar
Damien committed
519
520
521
522
            is_const = false;
        }
    }
    for (int i = 0; i < n; i++) {
523
        if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien's avatar
Damien committed
524
525
526
527
528
529
            is_const = false;
            break;
        }
    }
    if (total > 0 && is_const) {
        bool need_comma = false;
530
531
        vstr_t *vstr = vstr_new();
        vstr_printf(vstr, "(");
532
        if (!MP_PARSE_NODE_IS_NULL(pn)) {
533
            cpython_c_tuple_emit_const(comp, pn, vstr);
Damien's avatar
Damien committed
534
535
536
537
            need_comma = true;
        }
        for (int i = 0; i < n; i++) {
            if (need_comma) {
538
                vstr_printf(vstr, ", ");
Damien's avatar
Damien committed
539
            }
540
            cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien's avatar
Damien committed
541
542
543
            need_comma = true;
        }
        if (total == 1) {
544
            vstr_printf(vstr, ",)");
Damien's avatar
Damien committed
545
        } else {
546
            vstr_printf(vstr, ")");
Damien's avatar
Damien committed
547
        }
548
        EMIT_ARG(load_const_verbatim_strn, vstr_str(vstr), vstr_len(vstr));
549
        vstr_free(vstr);
Damien's avatar
Damien committed
550
    } else {
551
        if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
552
553
554
555
556
            compile_node(comp, pn);
        }
        for (int i = 0; i < n; i++) {
            compile_node(comp, pns_list->nodes[i]);
        }
557
        EMIT_ARG(build_tuple, total);
Damien's avatar
Damien committed
558
559
    }
}
560
561
562
#endif

// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
563
STATIC void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
564
#if MICROPY_EMIT_CPYTHON
565
566
567
    cpython_c_tuple(comp, pn, pns_list);
#else
    int total = 0;
568
    if (!MP_PARSE_NODE_IS_NULL(pn)) {
569
570
571
572
        compile_node(comp, pn);
        total += 1;
    }
    if (pns_list != NULL) {
573
        int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
574
575
576
577
578
        for (int i = 0; i < n; i++) {
            compile_node(comp, pns_list->nodes[i]);
        }
        total += n;
    }
579
    EMIT_ARG(build_tuple, total);
580
581
#endif
}
Damien's avatar
Damien committed
582

583
STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien's avatar
Damien committed
584
    // a simple tuple expression
585
    c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien's avatar
Damien committed
586
587
}

588
STATIC bool node_is_const_false(mp_parse_node_t pn) {
589
590
    return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE)
        || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
Damien's avatar
Damien committed
591
592
}

593
STATIC bool node_is_const_true(mp_parse_node_t pn) {
594
595
    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) != 0);
Damien's avatar
Damien committed
596
597
}

598
#if MICROPY_EMIT_CPYTHON
599
// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
600
STATIC void cpython_c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label, bool is_nested) {
Damien's avatar
Damien committed
601
602
    if (node_is_const_false(pn)) {
        if (jump_if == false) {
603
            EMIT_ARG(jump, label);
Damien's avatar
Damien committed
604
605
606
607
        }
        return;
    } else if (node_is_const_true(pn)) {
        if (jump_if == true) {
608
            EMIT_ARG(jump, label);
Damien's avatar
Damien committed
609
610
        }
        return;
611
612
613
614
    } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
        if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien's avatar
Damien committed
615
            if (jump_if == false) {
616
                uint label2 = comp_next_label(comp);
Damien's avatar
Damien committed
617
                for (int i = 0; i < n - 1; i++) {
618
                    cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien's avatar
Damien committed
619
                }
620
                cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
621
                EMIT_ARG(label_assign, label2);
Damien's avatar
Damien committed
622
623
            } else {
                for (int i = 0; i < n; i++) {
624
                    cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien's avatar
Damien committed
625
626
627
                }
            }
            return;
628
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien's avatar
Damien committed
629
630
            if (jump_if == false) {
                for (int i = 0; i < n; i++) {
631
                    cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien's avatar
Damien committed
632
633
                }
            } else {
634
                uint label2 = comp_next_label(comp);
Damien's avatar
Damien committed
635
                for (int i = 0; i < n - 1; i++) {
636
                    cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien's avatar
Damien committed
637
                }
638
                cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
639
                EMIT_ARG(label_assign, label2);
Damien's avatar
Damien committed
640
641
            }
            return;
642
        } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
643
            cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien's avatar
Damien committed
644
645
646
647
648
649
650
            return;
        }
    }

    // nothing special, fall back to default compiling for node and jump
    compile_node(comp, pn);
    if (jump_if == false) {
651
        EMIT_ARG(pop_jump_if_false, label);
Damien's avatar
Damien committed
652
    } else {
653
        EMIT_ARG(pop_jump_if_true, label);
Damien's avatar
Damien committed
654
655
    }
}
656
#endif
Damien's avatar
Damien committed
657

658
STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
659
#if MICROPY_EMIT_CPYTHON
660
661
662
663
    cpython_c_if_cond(comp, pn, jump_if, label, false);
#else
    if (node_is_const_false(pn)) {
        if (jump_if == false) {
664
            EMIT_ARG(jump, label);
665
666
667
668
        }
        return;
    } else if (node_is_const_true(pn)) {
        if (jump_if == true) {
669
            EMIT_ARG(jump, label);
670
671
        }
        return;
672
673
674
675
    } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
        if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
676
            if (jump_if == false) {
677
                uint label2 = comp_next_label(comp);
678
679
680
681
                for (int i = 0; i < n - 1; i++) {
                    c_if_cond(comp, pns->nodes[i], true, label2);
                }
                c_if_cond(comp, pns->nodes[n - 1], false, label);
682
                EMIT_ARG(label_assign, label2);
683
684
685
686
687
688
            } else {
                for (int i = 0; i < n; i++) {
                    c_if_cond(comp, pns->nodes[i], true, label);
                }
            }
            return;
689
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
690
691
692
693
694
            if (jump_if == false) {
                for (int i = 0; i < n; i++) {
                    c_if_cond(comp, pns->nodes[i], false, label);
                }
            } else {
695
                uint label2 = comp_next_label(comp);
696
697
698
699
                for (int i = 0; i < n - 1; i++) {
                    c_if_cond(comp, pns->nodes[i], false, label2);
                }
                c_if_cond(comp, pns->nodes[n - 1], true, label);
700
                EMIT_ARG(label_assign, label2);
701
702
            }
            return;
703
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
704
705
            c_if_cond(comp, pns->nodes[0], !jump_if, label);
            return;
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_atom_paren) {
            // cond is something in parenthesis
            if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
                // empty tuple, acts as false for the condition
                if (jump_if == false) {
                    EMIT_ARG(jump, label);
                }
            } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
                // non-empty tuple, acts as true for the condition
                if (jump_if == true) {
                    EMIT_ARG(jump, label);
                }
            } else {
                // parenthesis around 1 item, is just that item
                c_if_cond(comp, pns->nodes[0], jump_if, label);
            }
            return;
723
724
725
726
727
728
        }
    }

    // nothing special, fall back to default compiling for node and jump
    compile_node(comp, pn);
    if (jump_if == false) {
729
        EMIT_ARG(pop_jump_if_false, label);
730
    } else {
731
        EMIT_ARG(pop_jump_if_true, label);
732
733
    }
#endif
Damien's avatar
Damien committed
734
735
736
}

typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
737
STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien's avatar
Damien committed
738

739
STATIC void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien's avatar
Damien committed
740
741
742
743
    if (assign_kind != ASSIGN_AUG_STORE) {
        compile_node(comp, pns->nodes[0]);
    }

744
745
746
747
    if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
        mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
        if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
            int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien's avatar
Damien committed
748
749
750
751
752
            if (assign_kind != ASSIGN_AUG_STORE) {
                for (int i = 0; i < n - 1; i++) {
                    compile_node(comp, pns1->nodes[i]);
                }
            }
753
754
            assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
            pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien's avatar
Damien committed
755
        }
756
        if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
757
            goto cannot_assign;
758
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien's avatar
Damien committed
759
760
761
762
763
764
765
            if (assign_kind == ASSIGN_AUG_STORE) {
                EMIT(rot_three);
                EMIT(store_subscr);
            } else {
                compile_node(comp, pns1->nodes[0]);
                if (assign_kind == ASSIGN_AUG_LOAD) {
                    EMIT(dup_top_two);
766
                    EMIT(load_subscr);
Damien's avatar
Damien committed
767
768
769
770
                } else {
                    EMIT(store_subscr);
                }
            }
771
772
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
            assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien's avatar
Damien committed
773
774
            if (assign_kind == ASSIGN_AUG_LOAD) {
                EMIT(dup_top);
775
                EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien's avatar
Damien committed
776
777
778
779
            } else {
                if (assign_kind == ASSIGN_AUG_STORE) {
                    EMIT(rot_two);
                }
780
                EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien's avatar
Damien committed
781
782
            }
        } else {
783
            goto cannot_assign;
Damien's avatar
Damien committed
784
785
        }
    } else {
786
        goto cannot_assign;
Damien's avatar
Damien committed
787
788
    }

789
    if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
790
        goto cannot_assign;
Damien's avatar
Damien committed
791
    }
792
793
794
795
796

    return;

cannot_assign:
    compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
Damien's avatar
Damien committed
797
798
}

799
// we need to allow for a caller passing in 1 initial node (node_head) followed by an array of nodes (nodes_tail)
800
STATIC void c_assign_tuple(compiler_t *comp, mp_parse_node_t node_head, uint num_tail, mp_parse_node_t *nodes_tail) {
801
802
803
    uint num_head = (node_head == MP_PARSE_NODE_NULL) ? 0 : 1;

    // look for star expression
804
    uint have_star_index = -1;
805
806
807
808
    if (num_head != 0 && MP_PARSE_NODE_IS_STRUCT_KIND(node_head, PN_star_expr)) {
        EMIT_ARG(unpack_ex, 0, num_tail);
        have_star_index = 0;
    }
809
    for (uint i = 0; i < num_tail; i++) {
810
        if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {
811
            if (have_star_index == (uint)-1) {
812
813
                EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1);
                have_star_index = num_head + i;
Damien's avatar
Damien committed
814
            } else {
815
                compile_syntax_error(comp, nodes_tail[i], "multiple *x in assignment");
Damien's avatar
Damien committed
816
817
818
819
                return;
            }
        }
    }
820
    if (have_star_index == (uint)-1) {
821
        EMIT_ARG(unpack_sequence, num_head + num_tail);
Damien's avatar
Damien committed
822
    }
823
824
825
    if (num_head != 0) {
        if (0 == have_star_index) {
            c_assign(comp, ((mp_parse_node_struct_t*)node_head)->nodes[0], ASSIGN_STORE);
Damien's avatar
Damien committed
826
        } else {
827
828
829
            c_assign(comp, node_head, ASSIGN_STORE);
        }
    }
830
    for (uint i = 0; i < num_tail; i++) {
831
832
833
834
        if (num_head + i == have_star_index) {
            c_assign(comp, ((mp_parse_node_struct_t*)nodes_tail[i])->nodes[0], ASSIGN_STORE);
        } else {
            c_assign(comp, nodes_tail[i], ASSIGN_STORE);
Damien's avatar
Damien committed
835
836
837
838
839
        }
    }
}

// assigns top of stack to pn
840
STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien's avatar
Damien committed
841
    tail_recursion:
842
    if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
843
        assert(0);
844
845
    } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
        if (MP_PARSE_NODE_IS_ID(pn)) {
846
            qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien's avatar
Damien committed
847
848
849
            switch (assign_kind) {
                case ASSIGN_STORE:
                case ASSIGN_AUG_STORE:
850
                    EMIT_ARG(store_id, arg);
Damien's avatar
Damien committed
851
852
                    break;
                case ASSIGN_AUG_LOAD:
853
                default:
854
                    EMIT_ARG(load_id, arg);
Damien's avatar
Damien committed
855
856
857
                    break;
            }
        } else {
858
            compile_syntax_error(comp, pn, "can't assign to literal");
Damien's avatar
Damien committed
859
860
861
            return;
        }
    } else {
862
863
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien's avatar
Damien committed
864
865
866
867
868
869
870
871
872
873
874
            case PN_power:
                // lhs is an index or attribute
                c_assign_power(comp, pns, assign_kind);
                break;

            case PN_testlist_star_expr:
            case PN_exprlist:
                // lhs is a tuple
                if (assign_kind != ASSIGN_STORE) {
                    goto bad_aug;
                }
875
                c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien's avatar
Damien committed
876
877
878
879
                break;

            case PN_atom_paren:
                // lhs is something in parenthesis
880
                if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien's avatar
Damien committed
881
                    // empty tuple
882
                    goto cannot_assign;
883
884
                } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
                    pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien's avatar
Damien committed
885
886
887
888
889
890
891
892
893
894
895
896
897
                    goto testlist_comp;
                } else {
                    // parenthesis around 1 item, is just that item
                    pn = pns->nodes[0];
                    goto tail_recursion;
                }
                break;

            case PN_atom_bracket:
                // lhs is something in brackets
                if (assign_kind != ASSIGN_STORE) {
                    goto bad_aug;
                }
898
                if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien's avatar
Damien committed
899
                    // empty list, assignment allowed
900
                    c_assign_tuple(comp, MP_PARSE_NODE_NULL, 0, NULL);
901
902
                } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
                    pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien's avatar
Damien committed
903
904
905
                    goto testlist_comp;
                } else {
                    // brackets around 1 item
906
                    c_assign_tuple(comp, pns->nodes[0], 0, NULL);
Damien's avatar
Damien committed
907
908
909
910
                }
                break;

            default:
911
                goto cannot_assign;
Damien's avatar
Damien committed
912
913
914
915
916
        }
        return;

        testlist_comp:
        // lhs is a sequence
917
918
919
        if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
            mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
            if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien's avatar
Damien committed
920
                // sequence of one item, with trailing comma
921
                assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
922
                c_assign_tuple(comp, pns->nodes[0], 0, NULL);
923
            } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien's avatar
Damien committed
924
                // sequence of many items
925
926
                uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
                c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes);
927
            } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
928
                // TODO can we ever get here? can it be compiled?
929
                goto cannot_assign;
Damien's avatar
Damien committed
930
931
932
933
934
935
936
            } else {
                // sequence with 2 items
                goto sequence_with_2_items;
            }
        } else {
            // sequence with 2 items
            sequence_with_2_items:
937
            c_assign_tuple(comp, MP_PARSE_NODE_NULL, 2, pns->nodes);
Damien's avatar
Damien committed
938
939
940
941
942
        }
        return;
    }
    return;

943
944
945
946
    cannot_assign:
    compile_syntax_error(comp, pn, "can't assign to expression");
    return;

Damien's avatar
Damien committed
947
    bad_aug:
948
    compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
Damien's avatar
Damien committed
949
950
951
}

// stuff for lambda and comprehensions and generators
952
953
954
955
// if we are not in CPython compatibility mode then:
//  if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults
//  if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults
//  if both exist, the tuple is above the dictionary (ie the first pop gets the tuple)
956
STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
957
958
959
    assert(n_pos_defaults >= 0);
    assert(n_kw_defaults >= 0);

Damien's avatar
Damien committed
960
    // make closed over variables, if any
961
    // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien's avatar
Damien committed
962
963
    int nfree = 0;
    if (comp->scope_cur->kind != SCOPE_MODULE) {
964
965
966
967
968
        for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
            id_info_t *id = &comp->scope_cur->id_info[i];
            if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
                for (int j = 0; j < this_scope->id_info_len; j++) {
                    id_info_t *id2 = &this_scope->id_info[j];
969
                    if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
Damien George's avatar
Damien George committed
970
#if MICROPY_EMIT_CPYTHON
971
                        EMIT_ARG(load_closure, id->qst, id->local_num);
Damien George's avatar
Damien George committed
972
973
#else
                        // in Micro Python we load closures using LOAD_FAST
974
                        EMIT_ARG(load_fast, id->qst, id->local_num);
Damien George's avatar
Damien George committed
975
#endif
976
977