compile.c 132 KB
Newer Older
xbe's avatar
xbe committed
1
#include <stdbool.h>
Damien's avatar
Damien committed
2
3
4
5
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
6
#include <math.h>
Damien's avatar
Damien committed
7
8

#include "misc.h"
9
#include "mpconfig.h"
10
#include "qstr.h"
Damien's avatar
Damien committed
11
12
13
#include "lexer.h"
#include "parse.h"
#include "scope.h"
14
#include "runtime0.h"
Damien's avatar
Damien committed
15
#include "emit.h"
16
#include "emitglue.h"
17
18
19
#include "obj.h"
#include "compile.h"
#include "runtime.h"
20
#include "smallint.h"
Damien's avatar
Damien committed
21
22
23

// TODO need to mangle __attr names

24
25
#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_THUMB)

Damien's avatar
Damien committed
26
27
typedef enum {
    PN_none = 0,
28
#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
Damien's avatar
Damien committed
29
30
31
32
33
#include "grammar.h"
#undef DEF_RULE
    PN_maximum_number_of,
} pn_kind_t;

34
35
36
37
#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
38
39

typedef struct _compiler_t {
40
    qstr source_file;
41
42
43
44
    uint8_t is_repl;
    uint8_t pass; // holds enum type pass_kind_t
    uint8_t had_error; // try to keep compiler clean from nlr
    uint8_t func_arg_is_super; // used to compile special case of super() function call
Damien's avatar
Damien committed
45

46
    uint next_label;
47

48
49
    uint break_label;
    uint continue_label;
50
    int break_continue_except_level;
51
    uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
Damien's avatar
Damien committed
52

53
    uint16_t n_arg_keyword;
54
    uint8_t star_flags;
55
    uint8_t have_star;
56
57
    uint16_t num_dict_params;
    uint16_t num_default_params;
Damien's avatar
Damien committed
58
59
60
61

    scope_t *scope_head;
    scope_t *scope_cur;

62
63
    emit_t *emit;                                   // current emitter
    const emit_method_table_t *emit_method_table;   // current emit method table
64
65
66

    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
67
68
} compiler_t;

69
STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
70
    // TODO store the error message to a variable in compiler_t instead of printing it
71
72
73
74
75
    if (MP_PARSE_NODE_IS_STRUCT(pn)) {
        printf("  File \"%s\", line " UINT_FMT "\n", qstr_str(comp->source_file), (machine_uint_t)((mp_parse_node_struct_t*)pn)->source_line);
    } else {
        printf("  File \"%s\"\n", qstr_str(comp->source_file));
    }
76
77
78
79
    printf("SyntaxError: %s\n", msg);
    comp->had_error = true;
}

80
81
82
83
84
85
86
87
88
89
90
91
92
STATIC const mp_map_elem_t mp_constants_table[] = {
    // Extra constants as defined by a port
    MICROPY_EXTRA_CONSTANTS
};

STATIC const mp_map_t mp_constants_map = {
    .all_keys_are_qstrs = 1,
    .table_is_fixed_array = 1,
    .used = sizeof(mp_constants_table) / sizeof(mp_map_elem_t),
    .alloc = sizeof(mp_constants_table) / sizeof(mp_map_elem_t),
    .table = (mp_map_elem_t*)mp_constants_table,
};

93
94
95
96
mp_parse_node_t fold_constants(mp_parse_node_t pn) {
    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);
Damien's avatar
Damien committed
97
98
99
100
101
102

        // fold arguments first
        for (int i = 0; i < n; i++) {
            pns->nodes[i] = fold_constants(pns->nodes[i]);
        }

103
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien's avatar
Damien committed
104
            case PN_shift_expr:
105
                if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
106
107
                    int arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
                    int arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
108
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
109
#if MICROPY_EMIT_CPYTHON
110
                        // can overflow; enabled only to compare with CPython
111
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 << arg1);
112
#endif
113
114
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
Damien's avatar
Damien committed
115
116
117
118
119
120
121
122
                    } else {
                        // shouldn't happen
                        assert(0);
                    }
                }
                break;

            case PN_arith_expr:
123
                // overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
124
                if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
125
126
                    machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
                    machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
127
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
128
                        arg0 += arg1;
129
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_MINUS)) {
130
                        arg0 -= arg1;
Damien's avatar
Damien committed
131
132
133
                    } else {
                        // shouldn't happen
                        assert(0);
134
                    }
135
136
                    if (MP_PARSE_FITS_SMALL_INT(arg0)) {
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0);
Damien's avatar
Damien committed
137
138
139
140
141
                    }
                }
                break;

            case PN_term:
142
                if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
143
144
                    machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
                    machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
145
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
146
147
148
149
150
151
                        if (!mp_small_int_mul_overflow(arg0, arg1)) {
                            arg0 *= arg1;
                            if (MP_PARSE_FITS_SMALL_INT(arg0)) {
                                pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0);
                            }
                        }
152
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_SLASH)) {
Damien's avatar
Damien committed
153
                        ; // pass
154
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PERCENT)) {
155
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_modulo(arg0, arg1));
156
                    } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_SLASH)) {
157
                        if (arg1 != 0) {
158
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, mp_small_int_floor_divide(arg0, arg1));
159
                        }
Damien's avatar
Damien committed
160
161
162
163
164
165
166
167
                    } else {
                        // shouldn't happen
                        assert(0);
                    }
                }
                break;

            case PN_factor_2:
168
                if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
169
                    machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
170
171
172
173
174
175
                    if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
                        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)) {
                        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)) {
                        pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ~arg);
Damien's avatar
Damien committed
176
177
178
179
180
181
182
183
                    } else {
                        // shouldn't happen
                        assert(0);
                    }
                }
                break;

            case PN_power:
184
185
186
187
188
                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])) {
                    // int**x
                    // can overflow; enabled only to compare with CPython
189
190
                    mp_parse_node_struct_t* pns2 = (mp_parse_node_struct_t*)pns->nodes[2];
                    if (MP_PARSE_NODE_IS_SMALL_INT(pns2->nodes[0])) {
191
                        int power = MP_PARSE_NODE_LEAF_SMALL_INT(pns2->nodes[0]);
Damien's avatar
Damien committed
192
193
                        if (power >= 0) {
                            int ans = 1;
194
                            int base = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
Damien's avatar
Damien committed
195
196
197
                            for (; power > 0; power--) {
                                ans *= base;
                            }
198
                            pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, ans);
Damien's avatar
Damien committed
199
200
                        }
                    }
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#endif
                } 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) {
                            machine_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
                            if (MP_PARSE_FITS_SMALL_INT(val)) {
                                pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, val);
                            }
                        }
                    }
Damien's avatar
Damien committed
220
221
222
223
224
225
226
227
                }
                break;
        }
    }

    return pn;
}

228
STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
229
STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien's avatar
Damien committed
230

231
STATIC uint comp_next_label(compiler_t *comp) {
232
233
234
    return comp->next_label++;
}

235
236
237
238
239
240
241
242
243
244
245
246
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;
}

247
STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
248
    scope_t *scope = scope_new(kind, pn, comp->source_file, mp_emit_glue_get_unique_code_id(), emit_options);
Damien's avatar
Damien committed
249
250
251
252
253
254
255
256
257
258
259
260
261
262
    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;
}

263
STATIC int list_len(mp_parse_node_t pn, int pn_kind) {
264
    if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
265
        return 0;
266
    } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien's avatar
Damien committed
267
268
        return 1;
    } else {
269
270
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien's avatar
Damien committed
271
272
            return 1;
        } else {
273
            return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien's avatar
Damien committed
274
275
276
277
        }
    }
}

278
STATIC void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, int pn_list_kind, void (*f)(compiler_t*, mp_parse_node_t)) {
279
280
281
    if (MP_PARSE_NODE_IS_STRUCT(pn) && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn) == pn_list_kind) {
        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
282
283
284
        for (int i = 0; i < num_nodes; i++) {
            f(comp, pns->nodes[i]);
        }
285
    } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
286
287
288
289
        f(comp, pn);
    }
}

290
STATIC int list_get(mp_parse_node_t *pn, int pn_kind, mp_parse_node_t **nodes) {
291
    if (MP_PARSE_NODE_IS_NULL(*pn)) {
Damien's avatar
Damien committed
292
293
        *nodes = NULL;
        return 0;
294
    } else if (MP_PARSE_NODE_IS_LEAF(*pn)) {
Damien's avatar
Damien committed
295
296
297
        *nodes = pn;
        return 1;
    } else {
298
299
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)(*pn);
        if (MP_PARSE_NODE_STRUCT_KIND(pns) != pn_kind) {
Damien's avatar
Damien committed
300
301
302
303
            *nodes = pn;
            return 1;
        } else {
            *nodes = pns->nodes;
304
            return MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien's avatar
Damien committed
305
306
307
308
        }
    }
}

309
void compile_do_nothing(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien's avatar
Damien committed
310
311
}

312
313
void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
    int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien's avatar
Damien committed
314
315
316
317
318
    for (int i = 0; i < num_nodes; i++) {
        compile_node(comp, pns->nodes[i]);
    }
}

319
#if MICROPY_EMIT_CPYTHON
320
STATIC bool cpython_c_tuple_is_const(mp_parse_node_t pn) {
321
    if (!MP_PARSE_NODE_IS_LEAF(pn)) {
Damien's avatar
Damien committed
322
323
        return false;
    }
324
    if (MP_PARSE_NODE_IS_ID(pn)) {
Damien's avatar
Damien committed
325
326
327
328
329
        return false;
    }
    return true;
}

330
STATIC void cpython_c_print_quoted_str(vstr_t *vstr, qstr qstr, bool bytes) {
331
332
    uint len;
    const byte *str = qstr_data(qstr, &len);
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
    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, "'");
    }
}

370
STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
371
    assert(MP_PARSE_NODE_IS_LEAF(pn));
372
373
374
375
376
    if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
        vstr_printf(vstr, INT_FMT, MP_PARSE_NODE_LEAF_SMALL_INT(pn));
        return;
    }

377
378
379
380
381
382
383
384
    int arg = MP_PARSE_NODE_LEAF_ARG(pn);
    switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
        case MP_PARSE_NODE_ID: assert(0);
        case MP_PARSE_NODE_INTEGER: vstr_printf(vstr, "%s", qstr_str(arg)); break;
        case MP_PARSE_NODE_DECIMAL: vstr_printf(vstr, "%s", qstr_str(arg)); break;
        case MP_PARSE_NODE_STRING: cpython_c_print_quoted_str(vstr, arg, false); break;
        case MP_PARSE_NODE_BYTES: cpython_c_print_quoted_str(vstr, arg, true); break;
        case MP_PARSE_NODE_TOKEN:
Damien's avatar
Damien committed
385
            switch (arg) {
386
387
388
                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;
389
                default: assert(0); // shouldn't happen
Damien's avatar
Damien committed
390
391
392
393
394
395
            }
            break;
        default: assert(0);
    }
}

396
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
397
398
    int n = 0;
    if (pns_list != NULL) {
399
        n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien's avatar
Damien committed
400
401
402
    }
    int total = n;
    bool is_const = true;
403
    if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
404
        total += 1;
405
        if (!cpython_c_tuple_is_const(pn)) {
Damien's avatar
Damien committed
406
407
408
409
            is_const = false;
        }
    }
    for (int i = 0; i < n; i++) {
410
        if (!cpython_c_tuple_is_const(pns_list->nodes[i])) {
Damien's avatar
Damien committed
411
412
413
414
415
416
            is_const = false;
            break;
        }
    }
    if (total > 0 && is_const) {
        bool need_comma = false;
417
418
        vstr_t *vstr = vstr_new();
        vstr_printf(vstr, "(");
419
        if (!MP_PARSE_NODE_IS_NULL(pn)) {
420
            cpython_c_tuple_emit_const(comp, pn, vstr);
Damien's avatar
Damien committed
421
422
423
424
            need_comma = true;
        }
        for (int i = 0; i < n; i++) {
            if (need_comma) {
425
                vstr_printf(vstr, ", ");
Damien's avatar
Damien committed
426
            }
427
            cpython_c_tuple_emit_const(comp, pns_list->nodes[i], vstr);
Damien's avatar
Damien committed
428
429
430
            need_comma = true;
        }
        if (total == 1) {
431
            vstr_printf(vstr, ",)");
Damien's avatar
Damien committed
432
        } else {
433
            vstr_printf(vstr, ")");
Damien's avatar
Damien committed
434
        }
435
        EMIT_ARG(load_const_verbatim_str, vstr_str(vstr));
436
        vstr_free(vstr);
Damien's avatar
Damien committed
437
    } else {
438
        if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
439
440
441
442
443
            compile_node(comp, pn);
        }
        for (int i = 0; i < n; i++) {
            compile_node(comp, pns_list->nodes[i]);
        }
444
        EMIT_ARG(build_tuple, total);
Damien's avatar
Damien committed
445
446
    }
}
447
448
449
#endif

// funnelling all tuple creations through this function is purely so we can optionally agree with CPython
450
void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
451
#if MICROPY_EMIT_CPYTHON
452
453
454
    cpython_c_tuple(comp, pn, pns_list);
#else
    int total = 0;
455
    if (!MP_PARSE_NODE_IS_NULL(pn)) {
456
457
458
459
        compile_node(comp, pn);
        total += 1;
    }
    if (pns_list != NULL) {
460
        int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
461
462
463
464
465
        for (int i = 0; i < n; i++) {
            compile_node(comp, pns_list->nodes[i]);
        }
        total += n;
    }
466
    EMIT_ARG(build_tuple, total);
467
468
#endif
}
Damien's avatar
Damien committed
469

470
void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien's avatar
Damien committed
471
    // a simple tuple expression
472
    c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien's avatar
Damien committed
473
474
}

475
STATIC bool node_is_const_false(mp_parse_node_t pn) {
476
    return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE);
477
    // untested: || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
Damien's avatar
Damien committed
478
479
}

480
STATIC bool node_is_const_true(mp_parse_node_t pn) {
481
    return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE) || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 1);
Damien's avatar
Damien committed
482
483
}

484
#if MICROPY_EMIT_CPYTHON
485
// the is_nested variable is purely to match with CPython, which doesn't fully optimise not's
486
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
487
488
    if (node_is_const_false(pn)) {
        if (jump_if == false) {
489
            EMIT_ARG(jump, label);
Damien's avatar
Damien committed
490
491
492
493
        }
        return;
    } else if (node_is_const_true(pn)) {
        if (jump_if == true) {
494
            EMIT_ARG(jump, label);
Damien's avatar
Damien committed
495
496
        }
        return;
497
498
499
500
    } 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
501
            if (jump_if == false) {
502
                uint label2 = comp_next_label(comp);
Damien's avatar
Damien committed
503
                for (int i = 0; i < n - 1; i++) {
504
                    cpython_c_if_cond(comp, pns->nodes[i], true, label2, true);
Damien's avatar
Damien committed
505
                }
506
                cpython_c_if_cond(comp, pns->nodes[n - 1], false, label, true);
507
                EMIT_ARG(label_assign, label2);
Damien's avatar
Damien committed
508
509
            } else {
                for (int i = 0; i < n; i++) {
510
                    cpython_c_if_cond(comp, pns->nodes[i], true, label, true);
Damien's avatar
Damien committed
511
512
513
                }
            }
            return;
514
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien's avatar
Damien committed
515
516
            if (jump_if == false) {
                for (int i = 0; i < n; i++) {
517
                    cpython_c_if_cond(comp, pns->nodes[i], false, label, true);
Damien's avatar
Damien committed
518
519
                }
            } else {
520
                uint label2 = comp_next_label(comp);
Damien's avatar
Damien committed
521
                for (int i = 0; i < n - 1; i++) {
522
                    cpython_c_if_cond(comp, pns->nodes[i], false, label2, true);
Damien's avatar
Damien committed
523
                }
524
                cpython_c_if_cond(comp, pns->nodes[n - 1], true, label, true);
525
                EMIT_ARG(label_assign, label2);
Damien's avatar
Damien committed
526
527
            }
            return;
528
        } else if (!is_nested && MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
529
            cpython_c_if_cond(comp, pns->nodes[0], !jump_if, label, true);
Damien's avatar
Damien committed
530
531
532
533
534
535
536
            return;
        }
    }

    // nothing special, fall back to default compiling for node and jump
    compile_node(comp, pn);
    if (jump_if == false) {
537
        EMIT_ARG(pop_jump_if_false, label);
Damien's avatar
Damien committed
538
    } else {
539
        EMIT_ARG(pop_jump_if_true, label);
Damien's avatar
Damien committed
540
541
    }
}
542
#endif
Damien's avatar
Damien committed
543

544
STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
545
#if MICROPY_EMIT_CPYTHON
546
547
548
549
    cpython_c_if_cond(comp, pn, jump_if, label, false);
#else
    if (node_is_const_false(pn)) {
        if (jump_if == false) {
550
            EMIT_ARG(jump, label);
551
552
553
554
        }
        return;
    } else if (node_is_const_true(pn)) {
        if (jump_if == true) {
555
            EMIT_ARG(jump, label);
556
557
        }
        return;
558
559
560
561
    } 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) {
562
            if (jump_if == false) {
563
                uint label2 = comp_next_label(comp);
564
565
566
567
                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);
568
                EMIT_ARG(label_assign, label2);
569
570
571
572
573
574
            } else {
                for (int i = 0; i < n; i++) {
                    c_if_cond(comp, pns->nodes[i], true, label);
                }
            }
            return;
575
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
576
577
578
579
580
            if (jump_if == false) {
                for (int i = 0; i < n; i++) {
                    c_if_cond(comp, pns->nodes[i], false, label);
                }
            } else {
581
                uint label2 = comp_next_label(comp);
582
583
584
585
                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);
586
                EMIT_ARG(label_assign, label2);
587
588
            }
            return;
589
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
590
591
592
593
594
595
596
597
            c_if_cond(comp, pns->nodes[0], !jump_if, label);
            return;
        }
    }

    // nothing special, fall back to default compiling for node and jump
    compile_node(comp, pn);
    if (jump_if == false) {
598
        EMIT_ARG(pop_jump_if_false, label);
599
    } else {
600
        EMIT_ARG(pop_jump_if_true, label);
601
602
    }
#endif
Damien's avatar
Damien committed
603
604
605
}

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

608
void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien's avatar
Damien committed
609
610
611
612
    if (assign_kind != ASSIGN_AUG_STORE) {
        compile_node(comp, pns->nodes[0]);
    }

613
614
615
616
    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
617
618
619
620
621
            if (assign_kind != ASSIGN_AUG_STORE) {
                for (int i = 0; i < n - 1; i++) {
                    compile_node(comp, pns1->nodes[i]);
                }
            }
622
623
            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
624
        }
625
        if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
626
            goto cannot_assign;
627
        } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien's avatar
Damien committed
628
629
630
631
632
633
634
            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);
Damien George's avatar
Damien George committed
635
                    EMIT_ARG(binary_op, MP_BINARY_OP_SUBSCR);
Damien's avatar
Damien committed
636
637
638
639
                } else {
                    EMIT(store_subscr);
                }
            }
640
641
        } 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
642
643
            if (assign_kind == ASSIGN_AUG_LOAD) {
                EMIT(dup_top);
644
                EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien's avatar
Damien committed
645
646
647
648
            } else {
                if (assign_kind == ASSIGN_AUG_STORE) {
                    EMIT(rot_two);
                }
649
                EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien's avatar
Damien committed
650
651
            }
        } else {
652
            goto cannot_assign;
Damien's avatar
Damien committed
653
654
        }
    } else {
655
        goto cannot_assign;
Damien's avatar
Damien committed
656
657
    }

658
    if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
659
        goto cannot_assign;
Damien's avatar
Damien committed
660
    }
661
662
663
664
665

    return;

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

668
669
670
671
672
// we need to allow for a caller passing in 1 initial node (node_head) followed by an array of nodes (nodes_tail)
void c_assign_tuple(compiler_t *comp, mp_parse_node_t node_head, uint num_tail, mp_parse_node_t *nodes_tail) {
    uint num_head = (node_head == MP_PARSE_NODE_NULL) ? 0 : 1;

    // look for star expression
Damien's avatar
Damien committed
673
    int have_star_index = -1;
674
675
676
677
678
679
    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;
    }
    for (int i = 0; i < num_tail; i++) {
        if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {
Damien's avatar
Damien committed
680
            if (have_star_index < 0) {
681
682
                EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1);
                have_star_index = num_head + i;
Damien's avatar
Damien committed
683
            } else {
684
                compile_syntax_error(comp, nodes_tail[i], "two starred expressions in assignment");
Damien's avatar
Damien committed
685
686
687
688
689
                return;
            }
        }
    }
    if (have_star_index < 0) {
690
        EMIT_ARG(unpack_sequence, num_head + num_tail);
Damien's avatar
Damien committed
691
    }
692
693
694
    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
695
        } else {
696
697
698
699
700
701
702
703
            c_assign(comp, node_head, ASSIGN_STORE);
        }
    }
    for (int i = 0; i < num_tail; i++) {
        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
704
705
706
707
708
        }
    }
}

// assigns top of stack to pn
709
void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien's avatar
Damien committed
710
    tail_recursion:
711
    if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien's avatar
Damien committed
712
        assert(0);
713
714
715
    } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
        if (MP_PARSE_NODE_IS_ID(pn)) {
            int arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien's avatar
Damien committed
716
717
718
            switch (assign_kind) {
                case ASSIGN_STORE:
                case ASSIGN_AUG_STORE:
719
                    EMIT_ARG(store_id, arg);
Damien's avatar
Damien committed
720
721
                    break;
                case ASSIGN_AUG_LOAD:
722
                    EMIT_ARG(load_id, arg);
Damien's avatar
Damien committed
723
724
725
                    break;
            }
        } else {
726
            compile_syntax_error(comp, pn, "can't assign to literal");
Damien's avatar
Damien committed
727
728
729
            return;
        }
    } else {
730
731
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
        switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Damien's avatar
Damien committed
732
733
734
735
736
737
738
739
740
741
742
            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;
                }
743
                c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien's avatar
Damien committed
744
745
746
747
                break;

            case PN_atom_paren:
                // lhs is something in parenthesis
748
                if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien's avatar
Damien committed
749
                    // empty tuple
750
                    compile_syntax_error(comp, pn, "can't assign to ()");
Damien's avatar
Damien committed
751
                    return;
752
753
                } 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
754
755
756
757
758
759
760
761
762
763
764
765
766
                    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;
                }
767
                if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien's avatar
Damien committed
768
                    // empty list, assignment allowed
769
                    c_assign_tuple(comp, MP_PARSE_NODE_NULL, 0, NULL);
770
771
                } 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
772
773
774
                    goto testlist_comp;
                } else {
                    // brackets around 1 item
775
                    c_assign_tuple(comp, pns->nodes[0], 0, NULL);
Damien's avatar
Damien committed
776
777
778
779
                }
                break;

            default:
780
781
                compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
                return;
Damien's avatar
Damien committed
782
783
784
785
786
        }
        return;

        testlist_comp:
        // lhs is a sequence
787
788
789
        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
790
                // sequence of one item, with trailing comma
791
                assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
792
                c_assign_tuple(comp, pns->nodes[0], 0, NULL);
793
            } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien's avatar
Damien committed
794
                // sequence of many items
795
796
                uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
                c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes);
797
            } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
798
799
800
                // TODO can we ever get here? can it be compiled?
                compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
                return;
Damien's avatar
Damien committed
801
802
803
804
805
806
807
            } else {
                // sequence with 2 items
                goto sequence_with_2_items;
            }
        } else {
            // sequence with 2 items
            sequence_with_2_items:
808
            c_assign_tuple(comp, MP_PARSE_NODE_NULL, 2, pns->nodes);
Damien's avatar
Damien committed
809
810
811
812
813
814
        }
        return;
    }
    return;

    bad_aug:
815
    compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
Damien's avatar
Damien committed
816
817
818
}

// stuff for lambda and comprehensions and generators
819
820
821
822
// 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)
823
824
825
826
void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
    assert(n_pos_defaults >= 0);
    assert(n_kw_defaults >= 0);

Damien's avatar
Damien committed
827
    // make closed over variables, if any
828
    // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien's avatar
Damien committed
829
830
    int nfree = 0;
    if (comp->scope_cur->kind != SCOPE_MODULE) {
831
832
833
834
835
836
        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];
                    if (id2->kind == ID_INFO_KIND_FREE && id->qstr == id2->qstr) {
Damien George's avatar
Damien George committed
837
#if MICROPY_EMIT_CPYTHON
838
                        EMIT_ARG(load_closure, id->qstr, id->local_num);
Damien George's avatar
Damien George committed
839
840
#else
                        // in Micro Python we load closures using LOAD_FAST
841
                        EMIT_ARG(load_fast, id->qstr, id->flags, id->local_num);
Damien George's avatar
Damien George committed
842
#endif
843
844
845
                        nfree += 1;
                    }
                }
Damien's avatar
Damien committed
846
847
848
849
850
851
            }
        }
    }

    // make the function/closure
    if (nfree == 0) {
852
        EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);
Damien's avatar
Damien committed
853
    } else {
854
        EMIT_ARG(build_tuple, nfree);
855
        EMIT_ARG(make_closure, this_scope, n_pos_defaults, n_kw_defaults);
Damien's avatar
Damien committed
856
857
858
    }
}

859
void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
860
    if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
861
862
        comp->have_star = true;
        /* don't need to distinguish bare from named star
863
        mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
864
865
        if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
            // bare star
866
867
        } else {
            // named star
868
        }
869
        */
870
871

    } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)) {
872
        // named double star
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
        // 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;

        } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
            // this parameter has a colon and/or equal specifier

            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];

        } else {
895
            // XXX what to do here?
896
897
898
899
900
901
902
903
            assert(0);
            return;
        }

        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)
904
            if (!comp->have_star && comp->num_default_params != 0) {
905
                compile_syntax_error(comp, pn, "non-default argument follows default argument");
906
907
908
909
                return;
            }

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

913
            if (comp->have_star) {
914
                comp->num_dict_params += 1;
915
#if !MICROPY_EMIT_CPYTHON
916
917
918
919
920
                // in Micro Python we put the default dict parameters into a dictionary using the bytecode
                if (comp->num_dict_params == 1) {
                    // first default dict param, so make the map
                    EMIT_ARG(build_map, 0);
                }
921
#endif
922
923
                EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pn_id));
                compile_node(comp, pn_equal);
924
#if !MICROPY_EMIT_CPYTHON
925
926
                // in Micro Python we put the default dict parameters into a dictionary using the bytecode
                EMIT(store_map);
927
#endif
Damien's avatar
Damien committed
928
            } else {
929
930
                comp->num_default_params += 1;
                compile_node(comp, pn_equal);
Damien's avatar
Damien committed
931
932
            }
        }
933
934
935

        // TODO pn_colon not implemented
        (void)pn_colon;
Damien's avatar
Damien committed
936
937
938
939
940
    }
}

// leaves function object on stack
// returns function name
941
qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien's avatar
Damien committed
942
943
    if (comp->pass == PASS_1) {
        // create a new scope for this function
944
        scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien's avatar
Damien committed
945
        // store the function scope so the compiling function can use it at each pass
946
        pns->nodes[4] = (mp_parse_node_t)s;
Damien's avatar
Damien committed
947
948
949
    }

    // save variables (probably don't need to do this, since we can't have nested definitions..?)
950
    uint old_have_star = comp->have_star;
951
952
    uint old_num_dict_params = comp->num_dict_params;
    uint old_num_default_params = comp->num_default_params;
Damien's avatar
Damien committed
953
954

    // compile default parameters
955
    comp->have_star = false;
956
957
    comp->num_dict_params = 0;
    comp->num_default_params = 0;
Damien's avatar
Damien committed
958
    apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
959
960
961
962
963

    if (comp->had_error) {
        return MP_QSTR_NULL;
    }

964
965
#if !MICROPY_EMIT_CPYTHON
    // in Micro Python we put the default positional parameters into a tuple using the bytecode
966
967
    if (comp->num_default_params > 0) {
        EMIT_ARG(build_tuple, comp->num_default_params);
968
969
970
    }
#endif

Damien's avatar
Damien committed
971
972
973
974
    // get the scope for this function
    scope_t *fscope = (scope_t*)pns->nodes[4];

    // make the function
975
    close_over_variables_etc(comp, fscope, comp->num_default_params, comp->num_dict_params);
Damien's avatar
Damien committed
976
977

    // restore variables
978
    comp->have_star = old_have_star;
979
980
    comp->num_dict_params = old_num_dict_params;
    comp->num_default_params = old_num_default_params;
Damien's avatar
Damien committed
981
982
983
984
985
986
987

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

// leaves class object on stack
// returns class name
988
qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien's avatar
Damien committed
989
990
    if (comp->pass == PASS_1) {
        // create a new scope for this class
991
        scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien's avatar
Damien committed
992
        // store the class scope so the compiling function can use it at each pass
993
        pns->nodes[3] = (mp_parse_node_t)s;
Damien's avatar
Damien committed
994
995
996
997
998
999
1000
1001
1002
1003
1004
    }

    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
1005
    EMIT_ARG(load_const_id, cscope->simple_name);
Damien's avatar
Damien committed
1006
1007

    // nodes[1] has parent classes, if any
1008
1009
1010
1011
1012
    // 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;
    }
1013
    comp->func_arg_is_super = false;
1014
    compile_trailer_paren_helper(comp, parents, false, 2);
Damien's avatar
Damien committed
1015
1016
1017
1018
1019

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

1020
// returns true if it was a built-in decorator (even if the built-in had an error)
1021
STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
1022
    if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
1023
1024
1025
1026
        return false;
    }

    if (name_len != 2) {
1027
        compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator");
1028
1029
1030
        return true;
    }

1031
    qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
1032
    if (attr == MP_QSTR_byte_code) {
1033
        *emit_options = MP_EMIT_OPT_BYTE_CODE;
1034
#if MICROPY_EMIT_NATIVE
1035
    } else if (attr == MP_QSTR_native) {
1036
        *emit_options = MP_EMIT_OPT_NATIVE_PYTHON;