compile.c 141 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
32
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

33
34
35
36
37
38
#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
39
40
41
42

// TODO need to mangle __attr names

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

52
#define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE
53
54
55
56

#if NEED_METHOD_TABLE

// we need a method table to do the lookup for the emitter functions
57
58
#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
59
60
#define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.fast(comp->emit, qst, local_num))
#define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst))
61
62
#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
63

64
65
66
67
68
69
70
71
72
73
#else

// if we only have the bytecode emitter enabled then we can do a direct call to the functions
#define EMIT(fun) (mp_emit_bc_##fun(comp->emit))
#define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__))
#define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_fast(comp->emit, qst, local_num))
#define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst))

#endif

74
// elements in this struct are ordered to make it compact
Damien's avatar
Damien committed
75
typedef struct _compiler_t {
76
    qstr source_file;
77

78
79
80
    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
81
82
83
    uint8_t have_star;

    // try to keep compiler clean from nlr
84
85
    mp_obj_t compile_error; // set to an exception object if there's an error
    mp_uint_t compile_error_line; // set to best guess of line of error
Damien's avatar
Damien committed
86

87
    uint next_label;
88

89
90
91
    uint16_t num_dict_params;
    uint16_t num_default_params;

92
93
    uint16_t break_label; // highest bit set indicates we are breaking out of a for loop
    uint16_t continue_label;
94
    uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
95
    uint16_t break_continue_except_level;
Damien's avatar
Damien committed
96
97
98
99

    scope_t *scope_head;
    scope_t *scope_cur;

100
    emit_t *emit;                                   // current emitter
101
    #if NEED_METHOD_TABLE
102
    const emit_method_table_t *emit_method_table;   // current emit method table
103
    #endif
104

105
    #if MICROPY_EMIT_INLINE_THUMB
106
107
    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
108
    #endif
Damien's avatar
Damien committed
109
110
} compiler_t;

111
112
113
114
STATIC void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) {
    // if the line of the error is unknown then try to update it from the pn
    if (comp->compile_error_line == 0 && MP_PARSE_NODE_IS_STRUCT(pn)) {
        comp->compile_error_line = (mp_uint_t)((mp_parse_node_struct_t*)pn)->source_line;
115
    }
116
117
118
}

STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
119
120
121
122
123
    // only register the error if there has been no other error
    if (comp->compile_error == MP_OBJ_NULL) {
        comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
        compile_error_set_line(comp, pn);
    }
124
125
}

126
#if MICROPY_COMP_MODULE_CONST
127
STATIC const mp_map_elem_t mp_constants_table[] = {
128
129
130
    #if MICROPY_PY_UCTYPES
    { MP_OBJ_NEW_QSTR(MP_QSTR_uctypes), (mp_obj_t)&mp_module_uctypes },
    #endif
131
    // Extra constants as defined by a port
132
    MICROPY_PORT_CONSTANTS
133
};
134
135
STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table);
#endif
136

137
138
139
140
// 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
141
#if MICROPY_COMP_CONST
142
143
144
145
146
147
148
149
150
    } 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)) {
151
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien's avatar
Damien committed
152

153
154
        // fold some parse nodes before folding their arguments
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
155
#if MICROPY_COMP_CONST
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
            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;
                            }
179
                            mp_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

                            // 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
199
            case PN_string:
200
            case PN_bytes:
201
            case PN_const_object:
202
                return pn;
203
204
205
206
        }

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

211
        // try to fold this parse node
212
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
213
214
215
216
217
218
219
220
221
222
            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
223
224
                    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]);
225
226
227
228
229
230
231
                    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
232
233
                    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]);
234
235
236
237
                    pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 & arg1);
                }
                break;

Damien's avatar
Damien committed
238
            case PN_shift_expr:
239
                if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
240
241
                    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]);
242
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
243
                        // int << int
244
                        if (!(arg1 >= (mp_int_t)BITS_PER_WORD || arg0 > (MP_SMALL_INT_MAX >> arg1) || arg0 < (MP_SMALL_INT_MIN >> arg1))) {
245
246
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
                        }
247
248
                    } else {
                        assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)); // should be
249
                        // int >> int
250
                        if (arg1 >= (mp_int_t)BITS_PER_WORD) {
251
252
253
254
                            // Shifting to big amounts is underfined behavior
                            // in C and is CPU-dependent; propagate sign bit.
                            arg1 = BITS_PER_WORD - 1;
                        }
255
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien's avatar
Damien committed
256
257
258
259
260
                    }
                }
                break;

            case PN_arith_expr:
261
                // overflow checking here relies on SMALL_INT being strictly smaller than mp_int_t
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_PLUS)) {
266
                        // int + int
267
                        arg0 += arg1;
268
269
                    } else {
                        assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)); // should be
270
                        // int - int
271
                        arg0 -= arg1;
272
                    }
273
                    if (MP_SMALL_INT_FITS(arg0)) {
274
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0);
Damien's avatar
Damien committed
275
276
277
278
279
                    }
                }
                break;

            case PN_term:
280
                if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
281
282
                    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]);
283
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
284
                        // int * int
285
286
                        if (!mp_small_int_mul_overflow(arg0, arg1)) {
                            arg0 *= arg1;
287
                            if (MP_SMALL_INT_FITS(arg0)) {
288
289
290
                                pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0);
                            }
                        }
291
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
292
293
                        // int / int
                        // pass
294
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
295
                        // int%int
296
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_modulo(arg0, arg1));
297
298
                    } else {
                        assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)); // should be
299
                        if (arg1 != 0) {
300
                            // int // int
301
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_floor_divide(arg0, arg1));
302
                        }
Damien's avatar
Damien committed
303
304
305
306
307
                    }
                }
                break;

            case PN_factor_2:
308
                if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
309
                    mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
310
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
311
                        // +int
312
313
                        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)) {
314
                        // -int
315
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, -arg);
316
317
                    } else {
                        assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)); // should be
318
                        // ~int
319
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien's avatar
Damien committed
320
321
322
323
324
                    }
                }
                break;

            case PN_power:
325
                if (0) {
326
#if MICROPY_COMP_MODULE_CONST
327
328
329
                } 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
330
                    mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
331
332
333
334
335
336
337
338
                    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) {
339
                            mp_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
340
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, val);
341
342
                        }
                    }
343
#endif
Damien's avatar
Damien committed
344
345
346
347
348
349
350
351
                }
                break;
        }
    }

    return pn;
}

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

356
STATIC uint comp_next_label(compiler_t *comp) {
357
358
359
    return comp->next_label++;
}

360
361
362
363
364
365
366
367
368
369
370
371
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;
}

372
STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
373
    scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options);
Damien's avatar
Damien committed
374
375
376
377
378
379
380
381
382
383
384
385
386
387
    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;
}

388
389
390
typedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn);

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

402
STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
403
    int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien's avatar
Damien committed
404
405
    for (int i = 0; i < num_nodes; i++) {
        compile_node(comp, pns->nodes[i]);
406
407
408
409
410
        if (comp->compile_error != MP_OBJ_NULL) {
            // add line info for the error in case it didn't have a line number
            compile_error_set_line(comp, pns->nodes[i]);
            return;
        }
Damien's avatar
Damien committed
411
412
413
    }
}

414
415
416
417
STATIC void compile_load_id(compiler_t *comp, qstr qst) {
    if (comp->pass == MP_PASS_SCOPE) {
        mp_emit_common_get_id_for_load(comp->scope_cur, qst);
    } else {
418
        #if NEED_METHOD_TABLE
419
        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst);
420
421
422
        #else
        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_load_id_ops, comp->scope_cur, qst);
        #endif
423
424
425
426
427
428
429
    }
}

STATIC void compile_store_id(compiler_t *comp, qstr qst) {
    if (comp->pass == MP_PASS_SCOPE) {
        mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
    } else {
430
        #if NEED_METHOD_TABLE
431
        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst);
432
433
434
        #else
        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_store_id_ops, comp->scope_cur, qst);
        #endif
435
436
437
438
439
440
441
    }
}

STATIC void compile_delete_id(compiler_t *comp, qstr qst) {
    if (comp->pass == MP_PASS_SCOPE) {
        mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
    } else {
442
        #if NEED_METHOD_TABLE
443
        mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst);
444
445
446
        #else
        mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_delete_id_ops, comp->scope_cur, qst);
        #endif
447
448
449
    }
}

450
STATIC void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
451
    int total = 0;
452
    if (!MP_PARSE_NODE_IS_NULL(pn)) {
453
454
455
456
        compile_node(comp, pn);
        total += 1;
    }
    if (pns_list != NULL) {
457
        int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
458
459
460
461
462
        for (int i = 0; i < n; i++) {
            compile_node(comp, pns_list->nodes[i]);
        }
        total += n;
    }
463
    EMIT_ARG(build_tuple, total);
464
}
Damien's avatar
Damien committed
465

466
STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien's avatar
Damien committed
467
    // a simple tuple expression
468
    c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien's avatar
Damien committed
469
470
}

471
STATIC bool node_is_const_false(mp_parse_node_t pn) {
472
473
    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
474
475
}

476
STATIC bool node_is_const_true(mp_parse_node_t pn) {
477
478
    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
479
480
}

481
STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
482
483
    if (node_is_const_false(pn)) {
        if (jump_if == false) {
484
            EMIT_ARG(jump, label);
485
486
487
488
        }
        return;
    } else if (node_is_const_true(pn)) {
        if (jump_if == true) {
489
            EMIT_ARG(jump, label);
490
491
        }
        return;
492
493
494
495
    } 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) {
496
            if (jump_if == false) {
497
            and_or_logic1:;
498
                uint label2 = comp_next_label(comp);
499
                for (int i = 0; i < n - 1; i++) {
500
                    c_if_cond(comp, pns->nodes[i], !jump_if, label2);
501
                }
502
                c_if_cond(comp, pns->nodes[n - 1], jump_if, label);
503
                EMIT_ARG(label_assign, label2);
504
            } else {
505
            and_or_logic2:
506
                for (int i = 0; i < n; i++) {
507
                    c_if_cond(comp, pns->nodes[i], jump_if, label);
508
509
510
                }
            }
            return;
511
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
512
            if (jump_if == false) {
513
                goto and_or_logic2;
514
            } else {
515
                goto and_or_logic1;
516
            }
517
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
518
519
            c_if_cond(comp, pns->nodes[0], !jump_if, label);
            return;
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
        } 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;
537
538
539
540
541
        }
    }

    // nothing special, fall back to default compiling for node and jump
    compile_node(comp, pn);
542
    EMIT_ARG(pop_jump_if, jump_if, label);
Damien's avatar
Damien committed
543
544
545
}

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

548
STATIC void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien's avatar
Damien committed
549
550
551
552
    if (assign_kind != ASSIGN_AUG_STORE) {
        compile_node(comp, pns->nodes[0]);
    }

553
554
555
556
    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
557
558
559
560
561
            if (assign_kind != ASSIGN_AUG_STORE) {
                for (int i = 0; i < n - 1; i++) {
                    compile_node(comp, pns1->nodes[i]);
                }
            }
562
563
            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
564
        }
565
        if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien's avatar
Damien committed
566
567
568
569
570
571
572
            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);
573
                    EMIT(load_subscr);
Damien's avatar
Damien committed
574
575
576
577
                } else {
                    EMIT(store_subscr);
                }
            }
578
579
        } 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
580
581
            if (assign_kind == ASSIGN_AUG_LOAD) {
                EMIT(dup_top);
582
                EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien's avatar
Damien committed
583
584
585
586
            } else {
                if (assign_kind == ASSIGN_AUG_STORE) {
                    EMIT(rot_two);
                }
587
                EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien's avatar
Damien committed
588
589
            }
        } else {
590
            goto cannot_assign;
Damien's avatar
Damien committed
591
592
        }
    } else {
593
        goto cannot_assign;
Damien's avatar
Damien committed
594
595
    }

596
    if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
597
        goto cannot_assign;
Damien's avatar
Damien committed
598
    }
599
600
601
602
603

    return;

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

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

    // look for star expression
611
    uint have_star_index = -1;
612
613
614
615
    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;
    }
616
    for (uint i = 0; i < num_tail; i++) {
617
        if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {
618
            if (have_star_index == (uint)-1) {
619
620
                EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1);
                have_star_index = num_head + i;
Damien's avatar
Damien committed
621
            } else {
622
                compile_syntax_error(comp, nodes_tail[i], "multiple *x in assignment");
Damien's avatar
Damien committed
623
624
625
626
                return;
            }
        }
    }
627
    if (have_star_index == (uint)-1) {
628
        EMIT_ARG(unpack_sequence, num_head + num_tail);
Damien's avatar
Damien committed
629
    }
630
631
632
    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
633
        } else {
634
635
636
            c_assign(comp, node_head, ASSIGN_STORE);
        }
    }
637
    for (uint i = 0; i < num_tail; i++) {
638
639
640
641
        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
642
643
644
645
646
        }
    }
}

// assigns top of stack to pn
647
STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien's avatar
Damien committed
648
    tail_recursion:
649
650
    assert(!MP_PARSE_NODE_IS_NULL(pn));
    if (MP_PARSE_NODE_IS_LEAF(pn)) {
651
        if (MP_PARSE_NODE_IS_ID(pn)) {
652
            qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien's avatar
Damien committed
653
654
655
            switch (assign_kind) {
                case ASSIGN_STORE:
                case ASSIGN_AUG_STORE:
656
                    compile_store_id(comp, arg);
Damien's avatar
Damien committed
657
658
                    break;
                case ASSIGN_AUG_LOAD:
659
                default:
660
                    compile_load_id(comp, arg);
Damien's avatar
Damien committed
661
662
663
                    break;
            }
        } else {
664
            compile_syntax_error(comp, pn, "can't assign to literal");
Damien's avatar
Damien committed
665
666
667
            return;
        }
    } else {
668
        // pn must be a struct
669
670
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien's avatar
Damien committed
671
672
673
674
675
676
677
678
679
680
681
            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;
                }
682
                c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien's avatar
Damien committed
683
684
685
686
                break;

            case PN_atom_paren:
                // lhs is something in parenthesis
687
                if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien's avatar
Damien committed
688
                    // empty tuple
689
                    goto cannot_assign;
690
                } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
691
692
693
                    if (assign_kind != ASSIGN_STORE) {
                        goto bad_aug;
                    }
694
                    pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien's avatar
Damien committed
695
696
697
698
699
700
701
702
703
704
705
706
707
                    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;
                }
708
                if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien's avatar
Damien committed
709
                    // empty list, assignment allowed
710
                    c_assign_tuple(comp, MP_PARSE_NODE_NULL, 0, NULL);
711
712
                } 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
713
714
715
                    goto testlist_comp;
                } else {
                    // brackets around 1 item
716
                    c_assign_tuple(comp, pns->nodes[0], 0, NULL);
Damien's avatar
Damien committed
717
718
719
720
                }
                break;

            default:
721
                goto cannot_assign;
Damien's avatar
Damien committed
722
723
724
725
726
        }
        return;

        testlist_comp:
        // lhs is a sequence
727
728
729
        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
730
                // sequence of one item, with trailing comma
731
                assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
732
                c_assign_tuple(comp, pns->nodes[0], 0, NULL);
733
            } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien's avatar
Damien committed
734
                // sequence of many items
735
736
                uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
                c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes);
737
            } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
738
                // TODO can we ever get here? can it be compiled?
739
                goto cannot_assign;
Damien's avatar
Damien committed
740
741
742
743
744
745
746
            } else {
                // sequence with 2 items
                goto sequence_with_2_items;
            }
        } else {
            // sequence with 2 items
            sequence_with_2_items:
747
            c_assign_tuple(comp, MP_PARSE_NODE_NULL, 2, pns->nodes);
Damien's avatar
Damien committed
748
749
750
751
752
        }
        return;
    }
    return;

753
754
755
756
    cannot_assign:
    compile_syntax_error(comp, pn, "can't assign to expression");
    return;

Damien's avatar
Damien committed
757
    bad_aug:
758
    compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
Damien's avatar
Damien committed
759
760
}

761
// stuff for lambda and comprehensions and generators:
762
763
764
//  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)
765
STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
766
767
768
    assert(n_pos_defaults >= 0);
    assert(n_kw_defaults >= 0);

Damien's avatar
Damien committed
769
    // make closed over variables, if any
770
    // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien's avatar
Damien committed
771
772
    int nfree = 0;
    if (comp->scope_cur->kind != SCOPE_MODULE) {
773
774
775
776
777
        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];
778
                    if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
Damien George's avatar
Damien George committed
779
                        // in Micro Python we load closures using LOAD_FAST
780
                        EMIT_LOAD_FAST(id->qst, id->local_num);
781
782
783
                        nfree += 1;
                    }
                }
Damien's avatar
Damien committed
784
785
786
787
788
789
            }
        }
    }

    // make the function/closure
    if (nfree == 0) {
790
        EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);
Damien's avatar
Damien committed
791
    } else {
792
        EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);
Damien's avatar
Damien committed
793
794
795
    }
}

796
STATIC void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
797
    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
798
799
        comp->have_star = true;
        /* don't need to distinguish bare from named star
800
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
801
802
        if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
            // bare star
803
804
        } else {
            // named star
805
        }
806
        */
807
808

    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)) {
809
        // named double star
810
811
812
813
814
815
816
817
818
819
820
821
822
        // TODO do we need to do anything with this?

    } else {
        mp_parse_node_t pn_id;
        mp_parse_node_t pn_colon;
        mp_parse_node_t pn_equal;
        if (MP_PARSE_NODE_IS_ID(pn)) {
            // this parameter is just an id

            pn_id = pn;
            pn_colon = MP_PARSE_NODE_NULL;
            pn_equal = MP_PARSE_NODE_NULL;

823
        } else {
824
825
            // this parameter has a colon and/or equal specifier

826
827
            assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)); // should be

828
829
830
831
832
833
834
835
836
837
            mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
            pn_id = pns->nodes[0];
            pn_colon = pns->nodes[1];
            pn_equal = pns->nodes[2];
        }

        if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
            // this parameter does not have a default value

            // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
838
            if (!comp->have_star && comp->num_default_params != 0) {
839
                compile_syntax_error(comp, pn, "non-default argument follows default argument");
840
841
842
843
                return;
            }

        } else {
Damien's avatar
Damien committed
844
845
            // this parameter has a default value
            // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
846

847
            if (comp->have_star) {
848
849
850
                comp->num_dict_params += 1;
                // in Micro Python we put the default dict parameters into a dictionary using the bytecode
                if (comp->num_dict_params == 1) {
851
852
853
854
                    // in Micro Python we put the default positional parameters into a tuple using the bytecode
                    // we need to do this here before we start building the map for the default keywords
                    if (comp->num_default_params > 0) {
                        EMIT_ARG(build_tuple, comp->num_default_params);
855
856
                    } else {
                        EMIT(load_null); // sentinel indicating empty default positional args
857
                    }
858
859
860
                    // first default dict param, so make the map
                    EMIT_ARG(build_map, 0);
                }
861
862

                // compile value then key, then store it to the dict
863
                compile_node(comp, pn_equal);
864
                EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
865
                EMIT(store_map);
Damien's avatar
Damien committed
866
            } else {
867
868
                comp->num_default_params += 1;
                compile_node(comp, pn_equal);
Damien's avatar
Damien committed
869
870
            }
        }
871
872
873

        // TODO pn_colon not implemented
        (void)pn_colon;
Damien's avatar
Damien committed
874
875
876
877
878
    }
}

// leaves function object on stack
// returns function name
879
STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
880
    if (comp->pass == MP_PASS_SCOPE) {
Damien's avatar
Damien committed
881
        // create a new scope for this function
882
        scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien's avatar
Damien committed
883
        // store the function scope so the compiling function can use it at each pass
884
        pns->nodes[4] = (mp_parse_node_t)s;
Damien's avatar
Damien committed
885
886
887
    }

    // save variables (probably don't need to do this, since we can't have nested definitions..?)
888
    uint old_have_star = comp->have_star;
889
890
    uint old_num_dict_params = comp->num_dict_params;
    uint old_num_default_params = comp->num_default_params;
Damien's avatar
Damien committed
891
892

    // compile default parameters
893
    comp->have_star = false;
894
895
    comp->num_dict_params = 0;
    comp->num_default_params = 0;
Damien's avatar
Damien committed
896
    apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
897

898
    if (comp->compile_error != MP_OBJ_NULL) {
899
900
901
        return MP_QSTR_NULL;
    }

902
    // in Micro Python we put the default positional parameters into a tuple using the bytecode
903
904
    // the default keywords args may have already made the tuple; if not, do it now
    if (comp->num_default_params > 0 && comp->num_dict_params == 0) {
905
        EMIT_ARG(build_tuple, comp->num_default_params);
906
        EMIT(load_null); // sentinel indicating empty default keyword args
907
908
    }

Damien's avatar
Damien committed
909
910
911
912
    // get the scope for this function
    scope_t *fscope = (scope_t*)pns->nodes[4];

    // make the function
913
    close_over_variables_etc(comp, fscope, comp->num_default_params, comp->num_dict_params);
Damien's avatar
Damien committed
914
915

    // restore variables
916
    comp->have_star = old_have_star;
917
918
    comp->num_dict_params = old_num_dict_params;
    comp->num_default_params = old_num_default_params;
Damien's avatar
Damien committed
919
920
921
922
923
924
925

    // return its name (the 'f' in "def f(...):")
    return fscope->simple_name;
}

// leaves class object on stack
// returns class name
926
STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
927
    if (comp->pass == MP_PASS_SCOPE) {
Damien's avatar
Damien committed
928
        // create a new scope for this class
929
        scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien's avatar
Damien committed
930
        // store the class scope so the compiling function can use it at each pass
931
        pns->nodes[3] = (mp_parse_node_t)s;
Damien's avatar
Damien committed
932
933
934
935
936
937
938
939
940
941
942
    }

    EMIT(load_build_class);

    // scope for this class
    scope_t *cscope = (scope_t*)pns->nodes[3];

    // compile the class
    close_over_variables_etc(comp, cscope, 0, 0);

    // get its name
943
    EMIT_ARG(load_const_str, cscope->simple_name);
Damien's avatar
Damien committed
944
945

    // nodes[1] has parent classes, if any
946
947
948
949
950
    // empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling
    mp_parse_node_t parents = pns->nodes[1];
    if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
        parents = MP_PARSE_NODE_NULL;
    }
951
    comp->func_arg_is_super = false;
952
    compile_trailer_paren_helper(comp, parents, false, 2);
Damien's avatar
Damien committed
953
954
955
956
957

    // return its name (the 'C' in class C(...):")
    return cscope->simple_name;
}

958
// returns true if it was a built-in decorator (even if the built-in had an error)
959
STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
960
    if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
961
962
963
964
        return false;
    }

    if (name_len != 2) {
965
        compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator");
966
967
968
        return true;
    }

969
    qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
970
    if (attr ==