LCOV - code coverage report
Current view: top level - py - compile.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.19.1-724-gfb7d21153.info Lines: 1761 1770 99.5 %
Date: 2022-12-01 09:37:31 Functions: 97 97 100.0 %
Branches: 990 1160 85.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * This file is part of the MicroPython project, http://micropython.org/
       3                 :            :  *
       4                 :            :  * The MIT License (MIT)
       5                 :            :  *
       6                 :            :  * Copyright (c) 2013-2020 Damien P. George
       7                 :            :  *
       8                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a copy
       9                 :            :  * of this software and associated documentation files (the "Software"), to deal
      10                 :            :  * in the Software without restriction, including without limitation the rights
      11                 :            :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12                 :            :  * copies of the Software, and to permit persons to whom the Software is
      13                 :            :  * furnished to do so, subject to the following conditions:
      14                 :            :  *
      15                 :            :  * The above copyright notice and this permission notice shall be included in
      16                 :            :  * all copies or substantial portions of the Software.
      17                 :            :  *
      18                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21                 :            :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22                 :            :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23                 :            :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      24                 :            :  * THE SOFTWARE.
      25                 :            :  */
      26                 :            : 
      27                 :            : #include <stdbool.h>
      28                 :            : #include <stdint.h>
      29                 :            : #include <stdio.h>
      30                 :            : #include <string.h>
      31                 :            : #include <assert.h>
      32                 :            : 
      33                 :            : #include "py/scope.h"
      34                 :            : #include "py/emit.h"
      35                 :            : #include "py/compile.h"
      36                 :            : #include "py/runtime.h"
      37                 :            : #include "py/asmbase.h"
      38                 :            : #include "py/nativeglue.h"
      39                 :            : #include "py/persistentcode.h"
      40                 :            : #include "py/smallint.h"
      41                 :            : 
      42                 :            : #if MICROPY_ENABLE_COMPILER
      43                 :            : 
      44                 :            : // TODO need to mangle __attr names
      45                 :            : 
      46                 :            : #define INVALID_LABEL (0xffff)
      47                 :            : 
      48                 :            : typedef enum {
      49                 :            : // define rules with a compile function
      50                 :            : #define DEF_RULE(rule, comp, kind, ...) PN_##rule,
      51                 :            : #define DEF_RULE_NC(rule, kind, ...)
      52                 :            :     #include "py/grammar.h"
      53                 :            : #undef DEF_RULE
      54                 :            : #undef DEF_RULE_NC
      55                 :            :     PN_const_object, // special node for a constant, generic Python object
      56                 :            : // define rules without a compile function
      57                 :            : #define DEF_RULE(rule, comp, kind, ...)
      58                 :            : #define DEF_RULE_NC(rule, kind, ...) PN_##rule,
      59                 :            :     #include "py/grammar.h"
      60                 :            : #undef DEF_RULE
      61                 :            : #undef DEF_RULE_NC
      62                 :            : } pn_kind_t;
      63                 :            : 
      64                 :            : // Whether a mp_parse_node_struct_t that has pns->kind == PN_testlist_comp
      65                 :            : // corresponds to a list comprehension or generator.
      66                 :            : #define MP_PARSE_NODE_TESTLIST_COMP_HAS_COMP_FOR(pns) \
      67                 :            :     (MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2 && \
      68                 :            :     MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for))
      69                 :            : 
      70                 :            : #define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE
      71                 :            : 
      72                 :            : #if NEED_METHOD_TABLE
      73                 :            : 
      74                 :            : // we need a method table to do the lookup for the emitter functions
      75                 :            : #define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
      76                 :            : #define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
      77                 :            : #define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.local(comp->emit, qst, local_num, MP_EMIT_IDOP_LOCAL_FAST))
      78                 :            : #define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst, MP_EMIT_IDOP_GLOBAL_GLOBAL))
      79                 :            : 
      80                 :            : #else
      81                 :            : 
      82                 :            : // if we only have the bytecode emitter enabled then we can do a direct call to the functions
      83                 :            : #define EMIT(fun) (mp_emit_bc_##fun(comp->emit))
      84                 :            : #define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__))
      85                 :            : #define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_local(comp->emit, qst, local_num, MP_EMIT_IDOP_LOCAL_FAST))
      86                 :            : #define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst, MP_EMIT_IDOP_GLOBAL_GLOBAL))
      87                 :            : 
      88                 :            : #endif
      89                 :            : 
      90                 :            : #if MICROPY_EMIT_NATIVE && MICROPY_DYNAMIC_COMPILER
      91                 :            : 
      92                 :            : #define NATIVE_EMITTER(f) emit_native_table[mp_dynamic_compiler.native_arch]->emit_##f
      93                 :            : #define NATIVE_EMITTER_TABLE (emit_native_table[mp_dynamic_compiler.native_arch])
      94                 :            : 
      95                 :            : STATIC const emit_method_table_t *emit_native_table[] = {
      96                 :            :     NULL,
      97                 :            :     &emit_native_x86_method_table,
      98                 :            :     &emit_native_x64_method_table,
      99                 :            :     &emit_native_arm_method_table,
     100                 :            :     &emit_native_thumb_method_table,
     101                 :            :     &emit_native_thumb_method_table,
     102                 :            :     &emit_native_thumb_method_table,
     103                 :            :     &emit_native_thumb_method_table,
     104                 :            :     &emit_native_thumb_method_table,
     105                 :            :     &emit_native_xtensa_method_table,
     106                 :            :     &emit_native_xtensawin_method_table,
     107                 :            : };
     108                 :            : 
     109                 :            : #elif MICROPY_EMIT_NATIVE
     110                 :            : // define a macro to access external native emitter
     111                 :            : #if MICROPY_EMIT_X64
     112                 :            : #define NATIVE_EMITTER(f) emit_native_x64_##f
     113                 :            : #elif MICROPY_EMIT_X86
     114                 :            : #define NATIVE_EMITTER(f) emit_native_x86_##f
     115                 :            : #elif MICROPY_EMIT_THUMB
     116                 :            : #define NATIVE_EMITTER(f) emit_native_thumb_##f
     117                 :            : #elif MICROPY_EMIT_ARM
     118                 :            : #define NATIVE_EMITTER(f) emit_native_arm_##f
     119                 :            : #elif MICROPY_EMIT_XTENSA
     120                 :            : #define NATIVE_EMITTER(f) emit_native_xtensa_##f
     121                 :            : #elif MICROPY_EMIT_XTENSAWIN
     122                 :            : #define NATIVE_EMITTER(f) emit_native_xtensawin_##f
     123                 :            : #else
     124                 :            : #error "unknown native emitter"
     125                 :            : #endif
     126                 :            : #define NATIVE_EMITTER_TABLE (&NATIVE_EMITTER(method_table))
     127                 :            : #endif
     128                 :            : 
     129                 :            : #if MICROPY_EMIT_INLINE_ASM && MICROPY_DYNAMIC_COMPILER
     130                 :            : 
     131                 :            : #define ASM_EMITTER(f) emit_asm_table[mp_dynamic_compiler.native_arch]->asm_##f
     132                 :            : #define ASM_EMITTER_TABLE emit_asm_table[mp_dynamic_compiler.native_arch]
     133                 :            : 
     134                 :            : STATIC const emit_inline_asm_method_table_t *emit_asm_table[] = {
     135                 :            :     NULL,
     136                 :            :     NULL,
     137                 :            :     NULL,
     138                 :            :     &emit_inline_thumb_method_table,
     139                 :            :     &emit_inline_thumb_method_table,
     140                 :            :     &emit_inline_thumb_method_table,
     141                 :            :     &emit_inline_thumb_method_table,
     142                 :            :     &emit_inline_thumb_method_table,
     143                 :            :     &emit_inline_thumb_method_table,
     144                 :            :     &emit_inline_xtensa_method_table,
     145                 :            :     NULL,
     146                 :            : };
     147                 :            : 
     148                 :            : #elif MICROPY_EMIT_INLINE_ASM
     149                 :            : // define macros for inline assembler
     150                 :            : #if MICROPY_EMIT_INLINE_THUMB
     151                 :            : #define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb
     152                 :            : #define ASM_EMITTER(f) emit_inline_thumb_##f
     153                 :            : #elif MICROPY_EMIT_INLINE_XTENSA
     154                 :            : #define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa
     155                 :            : #define ASM_EMITTER(f) emit_inline_xtensa_##f
     156                 :            : #else
     157                 :            : #error "unknown asm emitter"
     158                 :            : #endif
     159                 :            : #define ASM_EMITTER_TABLE &ASM_EMITTER(method_table)
     160                 :            : #endif
     161                 :            : 
     162                 :            : #define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
     163                 :            : #define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
     164                 :            : 
     165                 :            : // elements in this struct are ordered to make it compact
     166                 :            : typedef struct _compiler_t {
     167                 :            :     uint8_t is_repl;
     168                 :            :     uint8_t pass; // holds enum type pass_kind_t
     169                 :            :     uint8_t have_star;
     170                 :            : 
     171                 :            :     // try to keep compiler clean from nlr
     172                 :            :     mp_obj_t compile_error; // set to an exception object if there's an error
     173                 :            :     size_t compile_error_line; // set to best guess of line of error
     174                 :            : 
     175                 :            :     uint next_label;
     176                 :            : 
     177                 :            :     uint16_t num_dict_params;
     178                 :            :     uint16_t num_default_params;
     179                 :            : 
     180                 :            :     uint16_t break_label; // highest bit set indicates we are breaking out of a for loop
     181                 :            :     uint16_t continue_label;
     182                 :            :     uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
     183                 :            :     uint16_t break_continue_except_level;
     184                 :            : 
     185                 :            :     scope_t *scope_head;
     186                 :            :     scope_t *scope_cur;
     187                 :            : 
     188                 :            :     emit_t *emit;                                   // current emitter
     189                 :            :     #if NEED_METHOD_TABLE
     190                 :            :     const emit_method_table_t *emit_method_table;   // current emit method table
     191                 :            :     #endif
     192                 :            : 
     193                 :            :     #if MICROPY_EMIT_INLINE_ASM
     194                 :            :     emit_inline_asm_t *emit_inline_asm;                                   // current emitter for inline asm
     195                 :            :     const emit_inline_asm_method_table_t *emit_inline_asm_method_table;   // current emit method table for inline asm
     196                 :            :     #endif
     197                 :            : 
     198                 :            :     mp_emit_common_t emit_common;
     199                 :            : } compiler_t;
     200                 :            : 
     201                 :            : /******************************************************************************/
     202                 :            : // mp_emit_common_t helper functions
     203                 :            : // These are defined here so they can be inlined, to reduce code size.
     204                 :            : 
     205                 :       3560 : STATIC void mp_emit_common_init(mp_emit_common_t *emit, qstr source_file) {
     206                 :            :     #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
     207                 :       3560 :     mp_map_init(&emit->qstr_map, 1);
     208                 :            : 
     209                 :            :     // add the source file as the first entry in the qstr table
     210                 :       3560 :     mp_map_elem_t *elem = mp_map_lookup(&emit->qstr_map, MP_OBJ_NEW_QSTR(source_file), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
     211                 :       3560 :     elem->value = MP_OBJ_NEW_SMALL_INT(0);
     212                 :            :     #endif
     213                 :       3560 :     mp_obj_list_init(&emit->const_obj_list, 0);
     214                 :       3560 : }
     215                 :            : 
     216                 :      35483 : STATIC void mp_emit_common_start_pass(mp_emit_common_t *emit, pass_kind_t pass) {
     217                 :      35483 :     emit->pass = pass;
     218         [ +  + ]:      35483 :     if (pass == MP_PASS_CODE_SIZE) {
     219         [ +  + ]:       8720 :         if (emit->ct_cur_child == 0) {
     220                 :       6803 :             emit->children = NULL;
     221                 :            :         } else {
     222                 :       1917 :             emit->children = m_new0(mp_raw_code_t *, emit->ct_cur_child);
     223                 :            :         }
     224                 :            :     }
     225                 :      35483 :     emit->ct_cur_child = 0;
     226                 :      35483 : }
     227                 :            : 
     228                 :       3234 : STATIC void mp_emit_common_populate_module_context(mp_emit_common_t *emit, qstr source_file, mp_module_context_t *context) {
     229                 :            :     #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
     230                 :       3234 :     size_t qstr_map_used = emit->qstr_map.used;
     231                 :       3234 :     mp_module_context_alloc_tables(context, qstr_map_used, emit->const_obj_list.len);
     232         [ +  + ]:      41936 :     for (size_t i = 0; i < emit->qstr_map.alloc; ++i) {
     233         [ +  + ]:      38702 :         if (mp_map_slot_is_filled(&emit->qstr_map, i)) {
     234                 :      34735 :             size_t idx = MP_OBJ_SMALL_INT_VALUE(emit->qstr_map.table[i].value);
     235                 :      34735 :             qstr qst = MP_OBJ_QSTR_VALUE(emit->qstr_map.table[i].key);
     236                 :      34735 :             context->constants.qstr_table[idx] = qst;
     237                 :            :         }
     238                 :            :     }
     239                 :            :     #else
     240                 :            :     mp_module_context_alloc_tables(context, 0, emit->const_obj_list.len);
     241                 :            :     context->constants.source_file = source_file;
     242                 :            :     #endif
     243                 :            : 
     244         [ +  + ]:       9081 :     for (size_t i = 0; i < emit->const_obj_list.len; ++i) {
     245                 :       5847 :         context->constants.obj_table[i] = emit->const_obj_list.items[i];
     246                 :            :     }
     247                 :       3234 : }
     248                 :            : 
     249                 :            : /******************************************************************************/
     250                 :            : 
     251                 :        548 : STATIC void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) {
     252                 :            :     // if the line of the error is unknown then try to update it from the pn
     253   [ +  +  +  +  :        548 :     if (comp->compile_error_line == 0 && MP_PARSE_NODE_IS_STRUCT(pn)) {
                   +  + ]
     254                 :        304 :         comp->compile_error_line = ((mp_parse_node_struct_t *)pn)->source_line;
     255                 :            :     }
     256                 :        548 : }
     257                 :            : 
     258                 :        232 : STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, mp_rom_error_text_t msg) {
     259                 :            :     // only register the error if there has been no other error
     260         [ +  + ]:        232 :     if (comp->compile_error == MP_OBJ_NULL) {
     261                 :        220 :         comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
     262                 :        220 :         compile_error_set_line(comp, pn);
     263                 :            :     }
     264                 :        232 : }
     265                 :            : 
     266                 :            : STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
     267                 :            : STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind);
     268                 :            : STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map);
     269                 :            : STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn);
     270                 :            : 
     271                 :     281057 : STATIC uint comp_next_label(compiler_t *comp) {
     272                 :     281057 :     return comp->next_label++;
     273                 :            : }
     274                 :            : 
     275                 :            : #if MICROPY_EMIT_NATIVE
     276                 :     164263 : STATIC void reserve_labels_for_native(compiler_t *comp, int n) {
     277         [ +  + ]:     164263 :     if (comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {
     278                 :      26591 :         comp->next_label += n;
     279                 :            :     }
     280                 :     164263 : }
     281                 :            : #else
     282                 :            : #define reserve_labels_for_native(comp, n)
     283                 :            : #endif
     284                 :            : 
     285                 :      88868 : STATIC void compile_increase_except_level(compiler_t *comp, uint label, int kind) {
     286                 :      88868 :     EMIT_ARG(setup_block, label, kind);
     287                 :      88868 :     comp->cur_except_level += 1;
     288         [ +  + ]:      88868 :     if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {
     289                 :       2244 :         comp->scope_cur->exc_stack_size = comp->cur_except_level;
     290                 :            :     }
     291                 :      88868 : }
     292                 :            : 
     293                 :      88868 : STATIC void compile_decrease_except_level(compiler_t *comp) {
     294         [ -  + ]:      88868 :     assert(comp->cur_except_level > 0);
     295                 :      88868 :     comp->cur_except_level -= 1;
     296                 :      88868 :     EMIT(end_finally);
     297                 :      88868 :     reserve_labels_for_native(comp, 1);
     298                 :      88868 : }
     299                 :            : 
     300                 :       9114 : STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
     301                 :       9114 :     scope_t *scope = scope_new(kind, pn, emit_options);
     302                 :       9114 :     scope->parent = comp->scope_cur;
     303                 :       9114 :     scope->next = NULL;
     304         [ +  + ]:       9114 :     if (comp->scope_head == NULL) {
     305                 :       3560 :         comp->scope_head = scope;
     306                 :            :     } else {
     307                 :            :         scope_t *s = comp->scope_head;
     308         [ +  + ]:      46478 :         while (s->next != NULL) {
     309                 :            :             s = s->next;
     310                 :            :         }
     311                 :       5554 :         s->next = scope;
     312                 :            :     }
     313                 :       9114 :     return scope;
     314                 :            : }
     315                 :            : 
     316                 :            : typedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn);
     317                 :            : 
     318                 :      27110 : 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) {
     319   [ +  +  +  +  :      27110 :     if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) {
                   +  + ]
     320                 :       8553 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
     321                 :       8553 :         int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
     322         [ +  + ]:      28763 :         for (int i = 0; i < num_nodes; i++) {
     323                 :      20210 :             f(comp, pns->nodes[i]);
     324                 :            :         }
     325                 :            :     } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
     326                 :      12809 :         f(comp, pn);
     327                 :            :     }
     328                 :      27106 : }
     329                 :            : 
     330                 :      74030 : STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
     331                 :      74030 :     int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
     332         [ +  + ]:     284850 :     for (int i = 0; i < num_nodes; i++) {
     333                 :     210844 :         compile_node(comp, pns->nodes[i]);
     334         [ +  + ]:     210844 :         if (comp->compile_error != MP_OBJ_NULL) {
     335                 :            :             // add line info for the error in case it didn't have a line number
     336                 :         24 :             compile_error_set_line(comp, pns->nodes[i]);
     337                 :         24 :             return;
     338                 :            :         }
     339                 :            :     }
     340                 :            : }
     341                 :            : 
     342                 :     375361 : STATIC void compile_load_id(compiler_t *comp, qstr qst) {
     343         [ +  + ]:     375361 :     if (comp->pass == MP_PASS_SCOPE) {
     344                 :      71116 :         mp_emit_common_get_id_for_load(comp->scope_cur, qst);
     345                 :            :     } else {
     346                 :            :         #if NEED_METHOD_TABLE
     347                 :     304245 :         mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst);
     348                 :            :         #else
     349                 :            :         mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_load_id_ops, comp->scope_cur, qst);
     350                 :            :         #endif
     351                 :            :     }
     352                 :     375360 : }
     353                 :            : 
     354                 :     110256 : STATIC void compile_store_id(compiler_t *comp, qstr qst) {
     355         [ +  + ]:     110256 :     if (comp->pass == MP_PASS_SCOPE) {
     356                 :      20074 :         mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
     357                 :            :     } else {
     358                 :            :         #if NEED_METHOD_TABLE
     359                 :      90182 :         mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst);
     360                 :            :         #else
     361                 :            :         mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_store_id_ops, comp->scope_cur, qst);
     362                 :            :         #endif
     363                 :            :     }
     364                 :     110256 : }
     365                 :            : 
     366                 :       1586 : STATIC void compile_delete_id(compiler_t *comp, qstr qst) {
     367         [ +  + ]:       1586 :     if (comp->pass == MP_PASS_SCOPE) {
     368                 :        385 :         mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
     369                 :            :     } else {
     370                 :            :         #if NEED_METHOD_TABLE
     371                 :       1201 :         mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst);
     372                 :            :         #else
     373                 :            :         mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_delete_id_ops, comp->scope_cur, qst);
     374                 :            :         #endif
     375                 :            :     }
     376                 :       1586 : }
     377                 :            : 
     378                 :       3375 : STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
     379                 :            :     // a simple tuple expression
     380                 :       3375 :     size_t num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
     381         [ +  + ]:      13005 :     for (size_t i = 0; i < num_nodes; i++) {
     382                 :       9630 :         compile_node(comp, pns->nodes[i]);
     383                 :            :     }
     384                 :       3375 :     EMIT_ARG(build, num_nodes, MP_EMIT_BUILD_TUPLE);
     385                 :       3375 : }
     386                 :            : 
     387                 :      17055 : STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
     388         [ +  + ]:      17055 :     if (mp_parse_node_is_const_false(pn)) {
     389         [ +  + ]:        102 :         if (jump_if == false) {
     390                 :          8 :             EMIT_ARG(jump, label);
     391                 :            :         }
     392                 :        102 :         return;
     393         [ +  + ]:      16953 :     } else if (mp_parse_node_is_const_true(pn)) {
     394         [ +  + ]:        950 :         if (jump_if == true) {
     395                 :        750 :             EMIT_ARG(jump, label);
     396                 :            :         }
     397                 :        950 :         return;
     398   [ +  -  +  + ]:      16003 :     } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
     399                 :      14150 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
     400                 :      14150 :         int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
     401         [ +  + ]:      14150 :         if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
     402         [ +  + ]:        324 :             if (jump_if == false) {
     403                 :        316 :             and_or_logic1:;
     404                 :        352 :                 uint label2 = comp_next_label(comp);
     405         [ +  + ]:        712 :                 for (int i = 0; i < n - 1; i++) {
     406                 :        360 :                     c_if_cond(comp, pns->nodes[i], !jump_if, label2);
     407                 :            :                 }
     408                 :        352 :                 c_if_cond(comp, pns->nodes[n - 1], jump_if, label);
     409                 :        352 :                 EMIT_ARG(label_assign, label2);
     410                 :            :             } else {
     411                 :          8 :             and_or_logic2:
     412         [ +  + ]:       3126 :                 for (int i = 0; i < n; i++) {
     413                 :       2084 :                     c_if_cond(comp, pns->nodes[i], jump_if, label);
     414                 :            :                 }
     415                 :            :             }
     416                 :       1394 :             return;
     417         [ +  + ]:      13826 :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
     418         [ +  + ]:       1070 :             if (jump_if == false) {
     419                 :       1034 :                 goto and_or_logic2;
     420                 :            :             } else {
     421                 :         36 :                 goto and_or_logic1;
     422                 :            :             }
     423         [ +  + ]:      12756 :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
     424                 :       1648 :             c_if_cond(comp, pns->nodes[0], !jump_if, label);
     425                 :       1648 :             return;
     426         [ -  + ]:      11108 :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_atom_paren) {
     427                 :            :             // cond is something in parenthesis
     428         [ #  # ]:          0 :             if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
     429                 :            :                 // empty tuple, acts as false for the condition
     430         [ #  # ]:          0 :                 if (jump_if == false) {
     431                 :          0 :                     EMIT_ARG(jump, label);
     432                 :            :                 }
     433                 :            :             } else {
     434   [ #  #  #  # ]:          0 :                 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
     435                 :            :                 // non-empty tuple, acts as true for the condition
     436         [ #  # ]:          0 :                 if (jump_if == true) {
     437                 :          0 :                     EMIT_ARG(jump, label);
     438                 :            :                 }
     439                 :            :             }
     440                 :          0 :             return;
     441                 :            :         }
     442                 :            :     }
     443                 :            : 
     444                 :            :     // nothing special, fall back to default compiling for node and jump
     445                 :      12961 :     compile_node(comp, pn);
     446                 :      12961 :     EMIT_ARG(pop_jump_if, jump_if, label);
     447                 :            : }
     448                 :            : 
     449                 :            : typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
     450                 :            : STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
     451                 :            : 
     452                 :       9000 : STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
     453         [ +  + ]:       9000 :     if (assign_kind != ASSIGN_AUG_STORE) {
     454                 :       8840 :         compile_node(comp, pns->nodes[0]);
     455                 :            :     }
     456                 :            : 
     457   [ +  -  +  - ]:       9000 :     if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
     458                 :       9000 :         mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pns->nodes[1];
     459         [ +  + ]:       9000 :         if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) {
     460                 :       1239 :             int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
     461         [ +  - ]:       1239 :             if (assign_kind != ASSIGN_AUG_STORE) {
     462         [ +  + ]:       2502 :                 for (int i = 0; i < n - 1; i++) {
     463                 :       1263 :                     compile_node(comp, pns1->nodes[i]);
     464                 :            :                 }
     465                 :            :             }
     466   [ +  -  -  + ]:       1239 :             assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
     467                 :       1239 :             pns1 = (mp_parse_node_struct_t *)pns1->nodes[n - 1];
     468                 :            :         }
     469         [ +  + ]:       9000 :         if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
     470         [ +  + ]:       3649 :             if (assign_kind == ASSIGN_AUG_STORE) {
     471                 :         44 :                 EMIT(rot_three);
     472                 :         44 :                 EMIT_ARG(subscr, MP_EMIT_SUBSCR_STORE);
     473                 :            :             } else {
     474                 :       3605 :                 compile_node(comp, pns1->nodes[0]);
     475         [ +  + ]:       3605 :                 if (assign_kind == ASSIGN_AUG_LOAD) {
     476                 :         44 :                     EMIT(dup_top_two);
     477                 :         44 :                     EMIT_ARG(subscr, MP_EMIT_SUBSCR_LOAD);
     478                 :            :                 } else {
     479                 :       3561 :                     EMIT_ARG(subscr, MP_EMIT_SUBSCR_STORE);
     480                 :            :                 }
     481                 :            :             }
     482                 :       3649 :             return;
     483         [ +  + ]:       5351 :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
     484         [ -  + ]:       5347 :             assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
     485         [ +  + ]:       5347 :             if (assign_kind == ASSIGN_AUG_LOAD) {
     486                 :        116 :                 EMIT(dup_top);
     487                 :        116 :                 EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_LOAD);
     488                 :            :             } else {
     489         [ +  + ]:       5231 :                 if (assign_kind == ASSIGN_AUG_STORE) {
     490                 :        116 :                     EMIT(rot_two);
     491                 :            :                 }
     492                 :       5231 :                 EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_STORE);
     493                 :            :             }
     494                 :       5347 :             return;
     495                 :            :         }
     496                 :            :     }
     497                 :            : 
     498                 :          4 :     compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("can't assign to expression"));
     499                 :            : }
     500                 :            : 
     501                 :       1264 : STATIC void c_assign_tuple(compiler_t *comp, uint num_tail, mp_parse_node_t *nodes_tail) {
     502                 :            :     // look for star expression
     503                 :       1264 :     uint have_star_index = -1;
     504         [ +  + ]:       4238 :     for (uint i = 0; i < num_tail; i++) {
     505   [ +  -  +  +  :       2978 :         if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {
                   +  + ]
     506         [ +  + ]:        280 :             if (have_star_index == (uint)-1) {
     507                 :        276 :                 EMIT_ARG(unpack_ex, i, num_tail - i - 1);
     508                 :        276 :                 have_star_index = i;
     509                 :            :             } else {
     510                 :          4 :                 compile_syntax_error(comp, nodes_tail[i], MP_ERROR_TEXT("multiple *x in assignment"));
     511                 :          4 :                 return;
     512                 :            :             }
     513                 :            :         }
     514                 :            :     }
     515         [ +  + ]:       1260 :     if (have_star_index == (uint)-1) {
     516                 :        988 :         EMIT_ARG(unpack_sequence, num_tail);
     517                 :            :     }
     518         [ +  + ]:       4230 :     for (uint i = 0; i < num_tail; i++) {
     519         [ +  + ]:       2970 :         if (i == have_star_index) {
     520                 :        272 :             c_assign(comp, ((mp_parse_node_struct_t *)nodes_tail[i])->nodes[0], ASSIGN_STORE);
     521                 :            :         } else {
     522                 :       2698 :             c_assign(comp, nodes_tail[i], ASSIGN_STORE);
     523                 :            :         }
     524                 :            :     }
     525                 :            : }
     526                 :            : 
     527                 :            : // assigns top of stack to pn
     528                 :      83525 : STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
     529         [ -  + ]:      83525 :     assert(!MP_PARSE_NODE_IS_NULL(pn));
     530         [ +  + ]:      83525 :     if (MP_PARSE_NODE_IS_LEAF(pn)) {
     531         [ +  + ]:      73217 :         if (MP_PARSE_NODE_IS_ID(pn)) {
     532                 :      73205 :             qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);
     533         [ +  + ]:      73205 :             switch (assign_kind) {
     534                 :      71838 :                 case ASSIGN_STORE:
     535                 :            :                 case ASSIGN_AUG_STORE:
     536                 :      71838 :                     compile_store_id(comp, arg);
     537                 :      71838 :                     break;
     538                 :       1367 :                 case ASSIGN_AUG_LOAD:
     539                 :            :                 default:
     540                 :       1367 :                     compile_load_id(comp, arg);
     541                 :       1367 :                     break;
     542                 :            :             }
     543                 :            :         } else {
     544                 :         12 :             goto cannot_assign;
     545                 :            :         }
     546                 :            :     } else {
     547                 :            :         // pn must be a struct
     548                 :      10308 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
     549   [ +  +  +  +  :      10308 :         switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
                      + ]
     550                 :       9000 :             case PN_atom_expr_normal:
     551                 :            :                 // lhs is an index or attribute
     552                 :       9000 :                 c_assign_atom_expr(comp, pns, assign_kind);
     553                 :       9000 :                 break;
     554                 :            : 
     555                 :       1168 :             case PN_testlist_star_expr:
     556                 :            :             case PN_exprlist:
     557                 :            :                 // lhs is a tuple
     558         [ +  + ]:       1168 :                 if (assign_kind != ASSIGN_STORE) {
     559                 :          8 :                     goto cannot_assign;
     560                 :            :                 }
     561                 :       1160 :                 c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
     562                 :       1160 :                 break;
     563                 :            : 
     564                 :         72 :             case PN_atom_paren:
     565                 :            :                 // lhs is something in parenthesis
     566         [ +  + ]:         72 :                 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
     567                 :            :                     // empty tuple
     568                 :          4 :                     goto cannot_assign;
     569                 :            :                 } else {
     570   [ +  -  -  + ]:         68 :                     assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
     571         [ +  + ]:         68 :                     if (assign_kind != ASSIGN_STORE) {
     572                 :          8 :                         goto cannot_assign;
     573                 :            :                     }
     574                 :         60 :                     pns = (mp_parse_node_struct_t *)pns->nodes[0];
     575                 :         60 :                     goto testlist_comp;
     576                 :            :                 }
     577                 :         56 :                 break;
     578                 :            : 
     579                 :         56 :             case PN_atom_bracket:
     580                 :            :                 // lhs is something in brackets
     581         [ +  + ]:         56 :                 if (assign_kind != ASSIGN_STORE) {
     582                 :          8 :                     goto cannot_assign;
     583                 :            :                 }
     584         [ +  + ]:         48 :                 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
     585                 :            :                     // empty list, assignment allowed
     586                 :          8 :                     c_assign_tuple(comp, 0, NULL);
     587   [ +  +  +  + ]:         40 :                 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
     588                 :         24 :                     pns = (mp_parse_node_struct_t *)pns->nodes[0];
     589                 :         24 :                     goto testlist_comp;
     590                 :            :                 } else {
     591                 :            :                     // brackets around 1 item
     592                 :         16 :                     c_assign_tuple(comp, 1, pns->nodes);
     593                 :            :                 }
     594                 :            :                 break;
     595                 :            : 
     596                 :         12 :             default:
     597                 :         12 :                 goto cannot_assign;
     598                 :            :         }
     599                 :      10184 :         return;
     600                 :            : 
     601                 :         84 :     testlist_comp:
     602                 :            :         // lhs is a sequence
     603   [ +  +  +  -  :         84 :         if (MP_PARSE_NODE_TESTLIST_COMP_HAS_COMP_FOR(pns)) {
             +  +  +  + ]
     604                 :          4 :             goto cannot_assign;
     605                 :            :         }
     606                 :         80 :         c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
     607                 :         80 :         return;
     608                 :            :     }
     609                 :            :     return;
     610                 :            : 
     611                 :         56 : cannot_assign:
     612                 :         56 :     compile_syntax_error(comp, pn, MP_ERROR_TEXT("can't assign to expression"));
     613                 :            : }
     614                 :            : 
     615                 :            : // stuff for lambda and comprehensions and generators:
     616                 :            : //  if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults
     617                 :            : //  if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults
     618                 :            : //  if both exist, the tuple is above the dictionary (ie the first pop gets the tuple)
     619                 :      22042 : STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
     620         [ -  + ]:      22042 :     assert(n_pos_defaults >= 0);
     621         [ -  + ]:      22042 :     assert(n_kw_defaults >= 0);
     622                 :            : 
     623                 :            :     // set flags
     624         [ +  + ]:      22042 :     if (n_kw_defaults > 0) {
     625                 :        100 :         this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS;
     626                 :            :     }
     627                 :      22042 :     this_scope->num_def_pos_args = n_pos_defaults;
     628                 :            : 
     629                 :            :     #if MICROPY_EMIT_NATIVE
     630                 :            :     // When creating a function/closure it will take a reference to the current globals
     631                 :      22042 :     comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_REFGLOBALS | MP_SCOPE_FLAG_HASCONSTS;
     632                 :            :     #endif
     633                 :            : 
     634                 :            :     // make closed over variables, if any
     635                 :            :     // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
     636                 :      22042 :     int nfree = 0;
     637         [ +  + ]:      22042 :     if (comp->scope_cur->kind != SCOPE_MODULE) {
     638         [ +  + ]:     102085 :         for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
     639                 :      92673 :             id_info_t *id = &comp->scope_cur->id_info[i];
     640         [ +  + ]:      92673 :             if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
     641         [ +  + ]:       4171 :                 for (int j = 0; j < this_scope->id_info_len; j++) {
     642                 :       3348 :                     id_info_t *id2 = &this_scope->id_info[j];
     643   [ +  +  +  + ]:       3348 :                     if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
     644                 :            :                         // in MicroPython we load closures using LOAD_FAST
     645                 :        576 :                         EMIT_LOAD_FAST(id->qst, id->local_num);
     646                 :        576 :                         nfree += 1;
     647                 :            :                     }
     648                 :            :                 }
     649                 :            :             }
     650                 :            :         }
     651                 :            :     }
     652                 :            : 
     653                 :            :     // make the function/closure
     654         [ +  + ]:       9412 :     if (nfree == 0) {
     655                 :      21652 :         EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);
     656                 :            :     } else {
     657                 :        390 :         EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);
     658                 :            :     }
     659                 :      22042 : }
     660                 :            : 
     661                 :      21964 : STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) {
     662                 :            :     // For efficiency of the code below we extract the parse-node kind here
     663                 :      21964 :     int pn_kind;
     664         [ +  + ]:      21964 :     if (MP_PARSE_NODE_IS_ID(pn)) {
     665                 :            :         pn_kind = -1;
     666                 :            :     } else {
     667   [ +  -  -  + ]:       3364 :         assert(MP_PARSE_NODE_IS_STRUCT(pn));
     668                 :       3364 :         pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pn);
     669                 :            :     }
     670                 :            : 
     671         [ +  + ]:      21964 :     if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) {
     672                 :        449 :         comp->have_star = true;
     673                 :            :         /* don't need to distinguish bare from named star
     674                 :            :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
     675                 :            :         if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
     676                 :            :             // bare star
     677                 :            :         } else {
     678                 :            :             // named star
     679                 :            :         }
     680                 :            :         */
     681                 :            : 
     682         [ +  + ]:      21515 :     } else if (pn_kind == PN_typedargslist_dbl_star || pn_kind == PN_varargslist_dbl_star) {
     683                 :            :         // named double star
     684                 :            :         // TODO do we need to do anything with this?
     685                 :            : 
     686                 :            :     } else {
     687                 :      21370 :         mp_parse_node_t pn_id;
     688                 :      21370 :         mp_parse_node_t pn_equal;
     689         [ +  + ]:      21370 :         if (pn_kind == -1) {
     690                 :            :             // this parameter is just an id
     691                 :            : 
     692                 :            :             pn_id = pn;
     693                 :            :             pn_equal = MP_PARSE_NODE_NULL;
     694                 :            : 
     695         [ +  + ]:       2770 :         } else if (pn_kind == PN_typedargslist_name) {
     696                 :            :             // this parameter has a colon and/or equal specifier
     697                 :            : 
     698                 :       2746 :             mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
     699                 :       2746 :             pn_id = pns->nodes[0];
     700                 :            :             // pn_colon = pns->nodes[1]; // unused
     701                 :       2746 :             pn_equal = pns->nodes[2];
     702                 :            : 
     703                 :            :         } else {
     704         [ -  + ]:         24 :             assert(pn_kind == PN_varargslist_name); // should be
     705                 :            :             // this parameter has an equal specifier
     706                 :            : 
     707                 :         24 :             mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
     708                 :         24 :             pn_id = pns->nodes[0];
     709                 :         24 :             pn_equal = pns->nodes[1];
     710                 :            :         }
     711                 :            : 
     712         [ +  + ]:       2770 :         if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
     713                 :            :             // this parameter does not have a default value
     714                 :            : 
     715                 :            :             // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
     716   [ +  +  +  + ]:      19928 :             if (!comp->have_star && comp->num_default_params != 0) {
     717                 :          4 :                 compile_syntax_error(comp, pn, MP_ERROR_TEXT("non-default argument follows default argument"));
     718                 :          4 :                 return;
     719                 :            :             }
     720                 :            : 
     721                 :            :         } else {
     722                 :            :             // this parameter has a default value
     723                 :            :             // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
     724                 :            : 
     725         [ +  + ]:       1442 :             if (comp->have_star) {
     726                 :        116 :                 comp->num_dict_params += 1;
     727                 :            :                 // in MicroPython we put the default dict parameters into a dictionary using the bytecode
     728         [ +  + ]:        116 :                 if (comp->num_dict_params == 1) {
     729                 :            :                     // in MicroPython we put the default positional parameters into a tuple using the bytecode
     730                 :            :                     // we need to do this here before we start building the map for the default keywords
     731         [ +  + ]:        100 :                     if (comp->num_default_params > 0) {
     732                 :          8 :                         EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE);
     733                 :            :                     } else {
     734                 :         92 :                         EMIT(load_null); // sentinel indicating empty default positional args
     735                 :            :                     }
     736                 :            :                     // first default dict param, so make the map
     737                 :        100 :                     EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
     738                 :            :                 }
     739                 :            : 
     740                 :            :                 // compile value then key, then store it to the dict
     741                 :        116 :                 compile_node(comp, pn_equal);
     742                 :        116 :                 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
     743                 :        116 :                 EMIT(store_map);
     744                 :            :             } else {
     745                 :       1326 :                 comp->num_default_params += 1;
     746                 :       1326 :                 compile_node(comp, pn_equal);
     747                 :            :             }
     748                 :            :         }
     749                 :            :     }
     750                 :            : }
     751                 :            : 
     752                 :      17626 : STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) {
     753                 :            :     // When we call compile_funcdef_lambdef_param below it can compile an arbitrary
     754                 :            :     // expression for default arguments, which may contain a lambda.  The lambda will
     755                 :            :     // call here in a nested way, so we must save and restore the relevant state.
     756                 :      17626 :     bool orig_have_star = comp->have_star;
     757                 :      17626 :     uint16_t orig_num_dict_params = comp->num_dict_params;
     758                 :      17626 :     uint16_t orig_num_default_params = comp->num_default_params;
     759                 :            : 
     760                 :            :     // compile default parameters
     761                 :      17626 :     comp->have_star = false;
     762                 :      17626 :     comp->num_dict_params = 0;
     763                 :      17626 :     comp->num_default_params = 0;
     764                 :      17626 :     apply_to_single_or_list(comp, pn_params, pn_list_kind, compile_funcdef_lambdef_param);
     765                 :            : 
     766         [ +  + ]:      17626 :     if (comp->compile_error != MP_OBJ_NULL) {
     767                 :            :         return;
     768                 :            :     }
     769                 :            : 
     770                 :            :     // in MicroPython we put the default positional parameters into a tuple using the bytecode
     771                 :            :     // the default keywords args may have already made the tuple; if not, do it now
     772   [ +  +  +  + ]:      17614 :     if (comp->num_default_params > 0 && comp->num_dict_params == 0) {
     773                 :       1026 :         EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE);
     774                 :       1026 :         EMIT(load_null); // sentinel indicating empty default keyword args
     775                 :            :     }
     776                 :            : 
     777                 :            :     // make the function
     778                 :      17614 :     close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);
     779                 :            : 
     780                 :            :     // restore state
     781                 :      17614 :     comp->have_star = orig_have_star;
     782                 :      17614 :     comp->num_dict_params = orig_num_dict_params;
     783                 :      17614 :     comp->num_default_params = orig_num_default_params;
     784                 :            : }
     785                 :            : 
     786                 :            : // leaves function object on stack
     787                 :            : // returns function name
     788                 :      17052 : STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
     789         [ +  + ]:      17052 :     if (comp->pass == MP_PASS_SCOPE) {
     790                 :            :         // create a new scope for this function
     791                 :       4300 :         scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
     792                 :            :         // store the function scope so the compiling function can use it at each pass
     793                 :       4300 :         pns->nodes[4] = (mp_parse_node_t)s;
     794                 :            :     }
     795                 :            : 
     796                 :            :     // get the scope for this function
     797                 :      17052 :     scope_t *fscope = (scope_t *)pns->nodes[4];
     798                 :            : 
     799                 :            :     // compile the function definition
     800                 :      17052 :     compile_funcdef_lambdef(comp, fscope, pns->nodes[1], PN_typedargslist);
     801                 :            : 
     802                 :            :     // return its name (the 'f' in "def f(...):")
     803                 :      17052 :     return fscope->simple_name;
     804                 :            : }
     805                 :            : 
     806                 :            : // leaves class object on stack
     807                 :            : // returns class name
     808                 :       3684 : STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
     809         [ +  + ]:       3684 :     if (comp->pass == MP_PASS_SCOPE) {
     810                 :            :         // create a new scope for this class
     811                 :        920 :         scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
     812                 :            :         // store the class scope so the compiling function can use it at each pass
     813                 :        920 :         pns->nodes[3] = (mp_parse_node_t)s;
     814                 :            :     }
     815                 :            : 
     816                 :       3684 :     EMIT(load_build_class);
     817                 :            : 
     818                 :            :     // scope for this class
     819                 :       3684 :     scope_t *cscope = (scope_t *)pns->nodes[3];
     820                 :            : 
     821                 :            :     // compile the class
     822                 :       3684 :     close_over_variables_etc(comp, cscope, 0, 0);
     823                 :            : 
     824                 :            :     // get its name
     825                 :       3684 :     EMIT_ARG(load_const_str, cscope->simple_name);
     826                 :            : 
     827                 :            :     // nodes[1] has parent classes, if any
     828                 :            :     // empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling
     829                 :       3684 :     mp_parse_node_t parents = pns->nodes[1];
     830   [ +  +  +  +  :       3684 :     if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
                   +  + ]
     831                 :         48 :         parents = MP_PARSE_NODE_NULL;
     832                 :            :     }
     833                 :       3684 :     compile_trailer_paren_helper(comp, parents, false, 2);
     834                 :            : 
     835                 :            :     // return its name (the 'C' in class C(...):")
     836                 :       3684 :     return cscope->simple_name;
     837                 :            : }
     838                 :            : 
     839                 :            : // returns true if it was a built-in decorator (even if the built-in had an error)
     840                 :       1688 : STATIC bool compile_built_in_decorator(compiler_t *comp, size_t name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
     841         [ +  + ]:       1688 :     if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
     842                 :            :         return false;
     843                 :            :     }
     844                 :            : 
     845         [ +  + ]:       1488 :     if (name_len != 2) {
     846                 :          4 :         compile_syntax_error(comp, name_nodes[0], MP_ERROR_TEXT("invalid micropython decorator"));
     847                 :          4 :         return true;
     848                 :            :     }
     849                 :            : 
     850                 :       1484 :     qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
     851         [ +  + ]:       1484 :     if (attr == MP_QSTR_bytecode) {
     852                 :         16 :         *emit_options = MP_EMIT_OPT_BYTECODE;
     853                 :            :     #if MICROPY_EMIT_NATIVE
     854         [ +  + ]:       1468 :     } else if (attr == MP_QSTR_native) {
     855                 :        252 :         *emit_options = MP_EMIT_OPT_NATIVE_PYTHON;
     856         [ +  + ]:       1216 :     } else if (attr == MP_QSTR_viper) {
     857                 :       1212 :         *emit_options = MP_EMIT_OPT_VIPER;
     858                 :            :     #endif
     859                 :            :         #if MICROPY_EMIT_INLINE_ASM
     860                 :            :     #if MICROPY_DYNAMIC_COMPILER
     861                 :            :     } else if (attr == MP_QSTR_asm_thumb) {
     862                 :            :         *emit_options = MP_EMIT_OPT_ASM;
     863                 :            :     } else if (attr == MP_QSTR_asm_xtensa) {
     864                 :            :         *emit_options = MP_EMIT_OPT_ASM;
     865                 :            :     #else
     866                 :            :     } else if (attr == ASM_DECORATOR_QSTR) {
     867                 :            :         *emit_options = MP_EMIT_OPT_ASM;
     868                 :            :     #endif
     869                 :            :         #endif
     870                 :            :     } else {
     871                 :          4 :         compile_syntax_error(comp, name_nodes[1], MP_ERROR_TEXT("invalid micropython decorator"));
     872                 :            :     }
     873                 :            : 
     874                 :            :     #if MICROPY_EMIT_NATIVE && MICROPY_DYNAMIC_COMPILER
     875                 :            :     if (*emit_options == MP_EMIT_OPT_NATIVE_PYTHON || *emit_options == MP_EMIT_OPT_VIPER) {
     876                 :            :         if (emit_native_table[mp_dynamic_compiler.native_arch] == NULL) {
     877                 :            :             compile_syntax_error(comp, name_nodes[1], MP_ERROR_TEXT("invalid arch"));
     878                 :            :         }
     879                 :            :     } else if (*emit_options == MP_EMIT_OPT_ASM) {
     880                 :            :         if (emit_asm_table[mp_dynamic_compiler.native_arch] == NULL) {
     881                 :            :             compile_syntax_error(comp, name_nodes[1], MP_ERROR_TEXT("invalid arch"));
     882                 :            :         }
     883                 :            :     }
     884                 :            :     #endif
     885                 :            : 
     886                 :            :     return true;
     887                 :            : }
     888                 :            : 
     889                 :       1688 : STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
     890                 :            :     // get the list of decorators
     891                 :       1688 :     mp_parse_node_t *nodes;
     892                 :       1688 :     size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_decorators, &nodes);
     893                 :            : 
     894                 :            :     // inherit emit options for this function/class definition
     895                 :       1688 :     uint emit_options = comp->scope_cur->emit_options;
     896                 :            : 
     897                 :            :     // compile each decorator
     898                 :       1688 :     size_t num_built_in_decorators = 0;
     899         [ +  + ]:       3376 :     for (size_t i = 0; i < n; i++) {
     900   [ +  -  +  -  :       1688 :         assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
                   -  + ]
     901                 :       1688 :         mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t *)nodes[i];
     902                 :            : 
     903                 :            :         // nodes[0] contains the decorator function, which is a dotted name
     904                 :       1688 :         mp_parse_node_t *name_nodes;
     905                 :       1688 :         size_t name_len = mp_parse_node_extract_list(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
     906                 :            : 
     907                 :            :         // check for built-in decorators
     908         [ +  + ]:       1688 :         if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
     909                 :            :             // this was a built-in
     910                 :       1488 :             num_built_in_decorators += 1;
     911                 :            : 
     912                 :            :         } else {
     913                 :            :             // not a built-in, compile normally
     914                 :            : 
     915                 :            :             // compile the decorator function
     916                 :        200 :             compile_node(comp, name_nodes[0]);
     917         [ +  + ]:        216 :             for (size_t j = 1; j < name_len; j++) {
     918         [ -  + ]:         16 :                 assert(MP_PARSE_NODE_IS_ID(name_nodes[j])); // should be
     919                 :         16 :                 EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[j]), MP_EMIT_ATTR_LOAD);
     920                 :            :             }
     921                 :            : 
     922                 :            :             // nodes[1] contains arguments to the decorator function, if any
     923         [ +  + ]:        200 :             if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
     924                 :            :                 // call the decorator function with the arguments in nodes[1]
     925                 :          8 :                 compile_node(comp, pns_decorator->nodes[1]);
     926                 :            :             }
     927                 :            :         }
     928                 :            :     }
     929                 :            : 
     930                 :            :     // compile the body (funcdef, async funcdef or classdef) and get its name
     931                 :       1688 :     mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t *)pns->nodes[1];
     932                 :       1688 :     qstr body_name = 0;
     933         [ +  + ]:       1688 :     if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
     934                 :       1672 :         body_name = compile_funcdef_helper(comp, pns_body, emit_options);
     935                 :            :     #if MICROPY_PY_ASYNC_AWAIT
     936         [ +  + ]:         16 :     } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_async_funcdef) {
     937   [ +  -  -  + ]:          8 :         assert(MP_PARSE_NODE_IS_STRUCT(pns_body->nodes[0]));
     938                 :          8 :         mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t *)pns_body->nodes[0];
     939                 :          8 :         body_name = compile_funcdef_helper(comp, pns0, emit_options);
     940                 :          8 :         scope_t *fscope = (scope_t *)pns0->nodes[4];
     941                 :          8 :         fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
     942                 :            :     #endif
     943                 :            :     } else {
     944         [ -  + ]:          8 :         assert(MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef); // should be
     945                 :          8 :         body_name = compile_classdef_helper(comp, pns_body, emit_options);
     946                 :            :     }
     947                 :            : 
     948                 :            :     // call each decorator
     949         [ +  + ]:       1888 :     for (size_t i = 0; i < n - num_built_in_decorators; i++) {
     950                 :        200 :         EMIT_ARG(call_function, 1, 0, 0);
     951                 :            :     }
     952                 :            : 
     953                 :            :     // store func/class object into name
     954                 :       1688 :     compile_store_id(comp, body_name);
     955                 :       1688 : }
     956                 :            : 
     957                 :      15372 : STATIC void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
     958                 :      15372 :     qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
     959                 :            :     // store function object into function name
     960                 :      15372 :     compile_store_id(comp, fname);
     961                 :      15372 : }
     962                 :            : 
     963                 :        770 : STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
     964         [ +  + ]:        770 :     if (MP_PARSE_NODE_IS_ID(pn)) {
     965                 :        156 :         compile_delete_id(comp, MP_PARSE_NODE_LEAF_ARG(pn));
     966   [ +  -  +  -  :        614 :     } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_expr_normal)) {
                   +  + ]
     967                 :        562 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
     968                 :            : 
     969                 :        562 :         compile_node(comp, pns->nodes[0]); // base of the atom_expr_normal node
     970                 :            : 
     971   [ +  -  +  - ]:        562 :         if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
     972                 :        562 :             mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pns->nodes[1];
     973         [ +  + ]:        562 :             if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) {
     974                 :        264 :                 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
     975         [ +  + ]:        528 :                 for (int i = 0; i < n - 1; i++) {
     976                 :        264 :                     compile_node(comp, pns1->nodes[i]);
     977                 :            :                 }
     978   [ +  -  -  + ]:        264 :                 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
     979                 :        264 :                 pns1 = (mp_parse_node_struct_t *)pns1->nodes[n - 1];
     980                 :            :             }
     981         [ +  + ]:        562 :             if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
     982                 :        442 :                 compile_node(comp, pns1->nodes[0]);
     983                 :        442 :                 EMIT_ARG(subscr, MP_EMIT_SUBSCR_DELETE);
     984         [ +  + ]:        120 :             } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
     985         [ -  + ]:        116 :                 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
     986                 :        116 :                 EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_DELETE);
     987                 :            :             } else {
     988                 :          4 :                 goto cannot_delete;
     989                 :            :             }
     990                 :            :         } else {
     991                 :          0 :             goto cannot_delete;
     992                 :            :         }
     993                 :            : 
     994   [ +  -  +  + ]:         52 :     } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
     995                 :         48 :         pn = ((mp_parse_node_struct_t *)pn)->nodes[0];
     996         [ +  + ]:         48 :         if (MP_PARSE_NODE_IS_NULL(pn)) {
     997                 :          4 :             goto cannot_delete;
     998                 :            :         } else {
     999   [ +  -  -  + ]:         44 :             assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp));
    1000                 :         44 :             mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
    1001   [ +  +  +  -  :         44 :             if (MP_PARSE_NODE_TESTLIST_COMP_HAS_COMP_FOR(pns)) {
             +  +  +  + ]
    1002                 :          4 :                 goto cannot_delete;
    1003                 :            :             }
    1004         [ +  + ]:        120 :             for (size_t i = 0; i < MP_PARSE_NODE_STRUCT_NUM_NODES(pns); ++i) {
    1005                 :         80 :                 c_del_stmt(comp, pns->nodes[i]);
    1006                 :            :             }
    1007                 :            :         }
    1008                 :            :     } else {
    1009                 :            :         // some arbitrary statement that we can't delete (eg del 1)
    1010                 :          4 :         goto cannot_delete;
    1011                 :            :     }
    1012                 :            : 
    1013                 :            :     return;
    1014                 :            : 
    1015                 :         16 : cannot_delete:
    1016                 :         16 :     compile_syntax_error(comp, (mp_parse_node_t)pn, MP_ERROR_TEXT("can't delete expression"));
    1017                 :            : }
    1018                 :            : 
    1019                 :        690 : STATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1020                 :        690 :     apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
    1021                 :        690 : }
    1022                 :            : 
    1023                 :        966 : STATIC void compile_break_cont_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1024                 :        966 :     uint16_t label;
    1025         [ +  + ]:        966 :     if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_break_stmt) {
    1026                 :        812 :         label = comp->break_label;
    1027                 :            :     } else {
    1028                 :        154 :         label = comp->continue_label;
    1029                 :            :     }
    1030         [ +  + ]:        966 :     if (label == INVALID_LABEL) {
    1031                 :          8 :         compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'break'/'continue' outside loop"));
    1032                 :            :     }
    1033         [ -  + ]:        966 :     assert(comp->cur_except_level >= comp->break_continue_except_level);
    1034                 :        966 :     EMIT_ARG(unwind_jump, label, comp->cur_except_level - comp->break_continue_except_level);
    1035                 :        966 : }
    1036                 :            : 
    1037                 :       7760 : STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1038                 :            :     #if MICROPY_CPYTHON_COMPAT
    1039         [ +  + ]:       7760 :     if (comp->scope_cur->kind != SCOPE_FUNCTION) {
    1040                 :          4 :         compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'return' outside function"));
    1041                 :          4 :         return;
    1042                 :            :     }
    1043                 :            :     #endif
    1044         [ +  + ]:       7756 :     if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
    1045                 :            :         // no argument to 'return', so return None
    1046                 :        446 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    1047                 :       7310 :     } else if (MICROPY_COMP_RETURN_IF_EXPR
    1048   [ +  +  +  + ]:       7526 :                && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
    1049                 :            :         // special case when returning an if-expression; to match CPython optimisation
    1050                 :        216 :         mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t *)pns->nodes[0];
    1051                 :        216 :         mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t *)pns_test_if_expr->nodes[1];
    1052                 :            : 
    1053                 :        216 :         uint l_fail = comp_next_label(comp);
    1054                 :        216 :         c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
    1055                 :        216 :         compile_node(comp, pns_test_if_expr->nodes[0]); // success value
    1056                 :        216 :         EMIT(return_value);
    1057                 :        216 :         EMIT_ARG(label_assign, l_fail);
    1058                 :        216 :         compile_node(comp, pns_test_if_else->nodes[1]); // failure value
    1059                 :            :     } else {
    1060                 :       7094 :         compile_node(comp, pns->nodes[0]);
    1061                 :            :     }
    1062                 :       7756 :     EMIT(return_value);
    1063                 :            : }
    1064                 :            : 
    1065                 :       1148 : STATIC void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1066                 :       1148 :     compile_node(comp, pns->nodes[0]);
    1067                 :       1140 :     EMIT(pop_top);
    1068                 :       1140 : }
    1069                 :            : 
    1070                 :       5852 : STATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1071         [ +  + ]:       5852 :     if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
    1072                 :            :         // raise
    1073                 :         54 :         EMIT_ARG(raise_varargs, 0);
    1074   [ +  +  +  + ]:       5798 :     } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
    1075                 :            :         // raise x from y
    1076                 :          4 :         pns = (mp_parse_node_struct_t *)pns->nodes[0];
    1077                 :          4 :         compile_node(comp, pns->nodes[0]);
    1078                 :          4 :         compile_node(comp, pns->nodes[1]);
    1079                 :          4 :         EMIT_ARG(raise_varargs, 2);
    1080                 :            :     } else {
    1081                 :            :         // raise x
    1082                 :       5794 :         compile_node(comp, pns->nodes[0]);
    1083                 :       5794 :         EMIT_ARG(raise_varargs, 1);
    1084                 :            :     }
    1085                 :       5852 : }
    1086                 :            : 
    1087                 :            : // q_base holds the base of the name
    1088                 :            : // eg   a -> q_base=a
    1089                 :            : //      a.b.c -> q_base=a
    1090                 :       6706 : STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
    1091                 :       6706 :     bool is_as = false;
    1092   [ +  +  +  +  :       6706 :     if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
                   +  + ]
    1093                 :       1238 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
    1094                 :            :         // a name of the form x as y; unwrap it
    1095                 :       1238 :         *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
    1096                 :       1238 :         pn = pns->nodes[0];
    1097                 :       1238 :         is_as = true;
    1098                 :            :     }
    1099         [ -  + ]:       1394 :     if (MP_PARSE_NODE_IS_NULL(pn)) {
    1100                 :            :         // empty name (eg, from . import x)
    1101                 :        108 :         *q_base = MP_QSTR_;
    1102                 :        108 :         EMIT_ARG(import, MP_QSTR_, MP_EMIT_IMPORT_NAME); // import the empty string
    1103         [ +  + ]:       6598 :     } else if (MP_PARSE_NODE_IS_ID(pn)) {
    1104                 :            :         // just a simple name
    1105                 :       6434 :         qstr q_full = MP_PARSE_NODE_LEAF_ARG(pn);
    1106         [ +  + ]:       6434 :         if (!is_as) {
    1107                 :       5204 :             *q_base = q_full;
    1108                 :            :         }
    1109                 :       6434 :         EMIT_ARG(import, q_full, MP_EMIT_IMPORT_NAME);
    1110                 :            :     } else {
    1111   [ +  -  +  -  :        164 :         assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_name)); // should be
                   -  + ]
    1112                 :        164 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
    1113                 :            :         {
    1114                 :            :             // a name of the form a.b.c
    1115         [ +  + ]:        164 :             if (!is_as) {
    1116                 :        156 :                 *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
    1117                 :            :             }
    1118                 :        164 :             size_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
    1119         [ -  + ]:        164 :             if (n == 0) {
    1120                 :            :                 // There must be at least one node in this PN_dotted_name.
    1121                 :            :                 // Let the compiler know this so it doesn't warn, and can generate better code.
    1122                 :          0 :                 MP_UNREACHABLE;
    1123                 :            :             }
    1124                 :        164 :             size_t len = n - 1;
    1125         [ +  + ]:        516 :             for (size_t i = 0; i < n; i++) {
    1126                 :        352 :                 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
    1127                 :            :             }
    1128                 :        164 :             char *q_ptr = mp_local_alloc(len);
    1129                 :        164 :             char *str_dest = q_ptr;
    1130         [ +  + ]:        516 :             for (size_t i = 0; i < n; i++) {
    1131         [ +  + ]:        352 :                 if (i > 0) {
    1132                 :        188 :                     *str_dest++ = '.';
    1133                 :            :                 }
    1134                 :        352 :                 size_t str_src_len;
    1135                 :        352 :                 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
    1136                 :        352 :                 memcpy(str_dest, str_src, str_src_len);
    1137                 :        352 :                 str_dest += str_src_len;
    1138                 :            :             }
    1139                 :        164 :             qstr q_full = qstr_from_strn(q_ptr, len);
    1140                 :        160 :             mp_local_free(q_ptr);
    1141                 :        160 :             EMIT_ARG(import, q_full, MP_EMIT_IMPORT_NAME);
    1142         [ +  + ]:        160 :             if (is_as) {
    1143         [ +  + ]:         16 :                 for (size_t i = 1; i < n; i++) {
    1144                 :          8 :                     EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), MP_EMIT_ATTR_LOAD);
    1145                 :            :                 }
    1146                 :            :             }
    1147                 :            :         }
    1148                 :            :     }
    1149                 :       6702 : }
    1150                 :            : 
    1151                 :       4829 : STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
    1152                 :       4829 :     EMIT_ARG(load_const_small_int, 0); // level 0 import
    1153                 :       4829 :     EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything
    1154                 :       4829 :     qstr q_base;
    1155                 :       4829 :     do_import_name(comp, pn, &q_base);
    1156                 :       4825 :     compile_store_id(comp, q_base);
    1157                 :       4825 : }
    1158                 :            : 
    1159                 :       4357 : STATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1160                 :       4357 :     apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
    1161                 :       4353 : }
    1162                 :            : 
    1163                 :       1881 : STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1164                 :       1881 :     mp_parse_node_t pn_import_source = pns->nodes[0];
    1165                 :            : 
    1166                 :            :     // extract the preceding .'s (if any) for a relative import, to compute the import level
    1167                 :       1881 :     uint import_level = 0;
    1168                 :       3762 :     do {
    1169                 :       1881 :         mp_parse_node_t pn_rel;
    1170   [ +  +  +  -  :       1881 :         if (MP_PARSE_NODE_IS_TOKEN(pn_import_source) || MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_one_or_more_period_or_ellipsis)) {
             +  +  +  + ]
    1171                 :            :             // This covers relative imports with dots only like "from .. import"
    1172                 :        108 :             pn_rel = pn_import_source;
    1173                 :        108 :             pn_import_source = MP_PARSE_NODE_NULL;
    1174   [ +  +  +  + ]:       1773 :         } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_import_from_2b)) {
    1175                 :            :             // This covers relative imports starting with dot(s) like "from .foo import"
    1176                 :        464 :             mp_parse_node_struct_t *pns_2b = (mp_parse_node_struct_t *)pn_import_source;
    1177                 :        464 :             pn_rel = pns_2b->nodes[0];
    1178                 :        464 :             pn_import_source = pns_2b->nodes[1];
    1179         [ -  + ]:        464 :             assert(!MP_PARSE_NODE_IS_NULL(pn_import_source)); // should not be
    1180                 :            :         } else {
    1181                 :            :             // Not a relative import
    1182                 :            :             break;
    1183                 :            :         }
    1184                 :            : 
    1185                 :            :         // get the list of . and/or ...'s
    1186                 :        572 :         mp_parse_node_t *nodes;
    1187                 :        572 :         size_t n = mp_parse_node_extract_list(&pn_rel, PN_one_or_more_period_or_ellipsis, &nodes);
    1188                 :            : 
    1189                 :            :         // count the total number of .'s
    1190         [ +  + ]:       1168 :         for (size_t i = 0; i < n; i++) {
    1191         [ +  + ]:        596 :             if (MP_PARSE_NODE_IS_TOKEN_KIND(nodes[i], MP_TOKEN_DEL_PERIOD)) {
    1192                 :        572 :                 import_level++;
    1193                 :            :             } else {
    1194                 :            :                 // should be an MP_TOKEN_ELLIPSIS
    1195                 :         24 :                 import_level += 3;
    1196                 :            :             }
    1197                 :            :         }
    1198                 :            :     } while (0);
    1199                 :            : 
    1200         [ +  + ]:       1881 :     if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
    1201                 :            :         #if MICROPY_CPYTHON_COMPAT
    1202         [ +  + ]:        286 :         if (comp->scope_cur->kind != SCOPE_MODULE) {
    1203                 :          4 :             compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("import * not at module level"));
    1204                 :          4 :             return;
    1205                 :            :         }
    1206                 :            :         #endif
    1207                 :            : 
    1208                 :        282 :         EMIT_ARG(load_const_small_int, import_level);
    1209                 :            : 
    1210                 :            :         // build the "fromlist" tuple
    1211                 :        282 :         EMIT_ARG(load_const_str, MP_QSTR__star_);
    1212                 :        282 :         EMIT_ARG(build, 1, MP_EMIT_BUILD_TUPLE);
    1213                 :            : 
    1214                 :            :         // do the import
    1215                 :        282 :         qstr dummy_q;
    1216                 :        282 :         do_import_name(comp, pn_import_source, &dummy_q);
    1217                 :        282 :         EMIT_ARG(import, MP_QSTRnull, MP_EMIT_IMPORT_STAR);
    1218                 :            : 
    1219                 :            :     } else {
    1220                 :       1595 :         EMIT_ARG(load_const_small_int, import_level);
    1221                 :            : 
    1222                 :            :         // build the "fromlist" tuple
    1223                 :       1595 :         mp_parse_node_t *pn_nodes;
    1224                 :       1595 :         size_t n = mp_parse_node_extract_list(&pns->nodes[1], PN_import_as_names, &pn_nodes);
    1225         [ +  + ]:       4104 :         for (size_t i = 0; i < n; i++) {
    1226   [ +  -  +  -  :       2509 :             assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
                   -  + ]
    1227                 :       2509 :             mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t *)pn_nodes[i];
    1228                 :       2509 :             qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
    1229                 :       2509 :             EMIT_ARG(load_const_str, id2);
    1230                 :            :         }
    1231                 :       1595 :         EMIT_ARG(build, n, MP_EMIT_BUILD_TUPLE);
    1232                 :            : 
    1233                 :            :         // do the import
    1234                 :       1595 :         qstr dummy_q;
    1235                 :       1595 :         do_import_name(comp, pn_import_source, &dummy_q);
    1236         [ +  + ]:       4104 :         for (size_t i = 0; i < n; i++) {
    1237   [ +  -  +  -  :       2509 :             assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
                   -  + ]
    1238                 :       2509 :             mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t *)pn_nodes[i];
    1239                 :       2509 :             qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
    1240                 :       2509 :             EMIT_ARG(import, id2, MP_EMIT_IMPORT_FROM);
    1241         [ +  + ]:       2509 :             if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
    1242                 :       2293 :                 compile_store_id(comp, id2);
    1243                 :            :             } else {
    1244                 :        216 :                 compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
    1245                 :            :             }
    1246                 :            :         }
    1247                 :       1595 :         EMIT(pop_top);
    1248                 :            :     }
    1249                 :            : }
    1250                 :            : 
    1251                 :        314 : STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
    1252         [ +  + ]:        314 :     if (id_info->kind != ID_INFO_KIND_UNDECIDED && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
    1253                 :          4 :         compile_syntax_error(comp, pn, MP_ERROR_TEXT("identifier redefined as global"));
    1254                 :          4 :         return;
    1255                 :            :     }
    1256                 :        310 :     id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
    1257                 :            : 
    1258                 :            :     // if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL
    1259                 :        310 :     id_info = scope_find_global(comp->scope_cur, id_info->qst);
    1260         [ +  + ]:        310 :     if (id_info != NULL) {
    1261                 :        144 :         id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
    1262                 :            :     }
    1263                 :            : }
    1264                 :            : 
    1265                 :         41 : STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
    1266         [ +  + ]:         41 :     if (id_info->kind == ID_INFO_KIND_UNDECIDED) {
    1267                 :         33 :         id_info->kind = ID_INFO_KIND_GLOBAL_IMPLICIT;
    1268                 :         33 :         scope_check_to_close_over(comp->scope_cur, id_info);
    1269         [ +  + ]:         33 :         if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
    1270                 :          8 :             compile_syntax_error(comp, pn, MP_ERROR_TEXT("no binding for nonlocal found"));
    1271                 :            :         }
    1272         [ +  + ]:          8 :     } else if (id_info->kind != ID_INFO_KIND_FREE) {
    1273                 :          4 :         compile_syntax_error(comp, pn, MP_ERROR_TEXT("identifier redefined as nonlocal"));
    1274                 :            :     }
    1275                 :         41 : }
    1276                 :            : 
    1277                 :       1172 : STATIC void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1278         [ +  + ]:       1172 :     if (comp->pass == MP_PASS_SCOPE) {
    1279                 :        301 :         bool is_global = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_global_stmt;
    1280                 :            : 
    1281   [ +  +  +  + ]:        301 :         if (!is_global && comp->scope_cur->kind == SCOPE_MODULE) {
    1282                 :          4 :             compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("can't declare nonlocal in outer code"));
    1283                 :          4 :             return;
    1284                 :            :         }
    1285                 :            : 
    1286                 :        297 :         mp_parse_node_t *nodes;
    1287                 :        297 :         size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
    1288         [ +  + ]:        652 :         for (size_t i = 0; i < n; i++) {
    1289                 :        355 :             qstr qst = MP_PARSE_NODE_LEAF_ARG(nodes[i]);
    1290                 :        355 :             id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, ID_INFO_KIND_UNDECIDED);
    1291         [ +  + ]:        355 :             if (is_global) {
    1292                 :        314 :                 compile_declare_global(comp, (mp_parse_node_t)pns, id_info);
    1293                 :            :             } else {
    1294                 :         41 :                 compile_declare_nonlocal(comp, (mp_parse_node_t)pns, id_info);
    1295                 :            :             }
    1296                 :            :         }
    1297                 :            :     }
    1298                 :            : }
    1299                 :            : 
    1300                 :       2004 : STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1301                 :            :     // with optimisations enabled we don't compile assertions
    1302         [ +  + ]:       2004 :     if (MP_STATE_VM(mp_optimise_value) != 0) {
    1303                 :            :         return;
    1304                 :            :     }
    1305                 :            : 
    1306                 :       1980 :     uint l_end = comp_next_label(comp);
    1307                 :       1980 :     c_if_cond(comp, pns->nodes[0], true, l_end);
    1308                 :       1980 :     EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
    1309         [ +  + ]:       1980 :     if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
    1310                 :            :         // assertion message
    1311                 :         64 :         compile_node(comp, pns->nodes[1]);
    1312                 :         64 :         EMIT_ARG(call_function, 1, 0, 0);
    1313                 :            :     }
    1314                 :       1980 :     EMIT_ARG(raise_varargs, 1);
    1315                 :       1980 :     EMIT_ARG(label_assign, l_end);
    1316                 :            : }
    1317                 :            : 
    1318                 :       7433 : STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1319                 :       7433 :     uint l_end = comp_next_label(comp);
    1320                 :            : 
    1321                 :            :     // optimisation: don't emit anything when "if False"
    1322         [ +  + ]:       7433 :     if (!mp_parse_node_is_const_false(pns->nodes[0])) {
    1323                 :       7321 :         uint l_fail = comp_next_label(comp);
    1324                 :       7321 :         c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
    1325                 :            : 
    1326                 :       7321 :         compile_node(comp, pns->nodes[1]); // if block
    1327                 :            : 
    1328                 :            :         // optimisation: skip everything else when "if True"
    1329         [ +  + ]:       7321 :         if (mp_parse_node_is_const_true(pns->nodes[0])) {
    1330                 :        184 :             goto done;
    1331                 :            :         }
    1332                 :            : 
    1333                 :            :         // optimisation: don't jump over non-existent elif/else blocks
    1334   [ +  +  +  + ]:       7137 :         if (!(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))) {
    1335                 :            :             // jump over elif/else blocks
    1336                 :       2555 :             EMIT_ARG(jump, l_end);
    1337                 :            :         }
    1338                 :            : 
    1339                 :       7137 :         EMIT_ARG(label_assign, l_fail);
    1340                 :            :     }
    1341                 :            : 
    1342                 :            :     // compile elif blocks (if any)
    1343                 :       7249 :     mp_parse_node_t *pn_elif;
    1344                 :       7249 :     size_t n_elif = mp_parse_node_extract_list(&pns->nodes[2], PN_if_stmt_elif_list, &pn_elif);
    1345         [ +  + ]:       8424 :     for (size_t i = 0; i < n_elif; i++) {
    1346   [ +  -  +  -  :       1183 :         assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_elif[i], PN_if_stmt_elif)); // should be
                   -  + ]
    1347                 :       1183 :         mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t *)pn_elif[i];
    1348                 :            : 
    1349                 :            :         // optimisation: don't emit anything when "if False"
    1350         [ +  + ]:       1183 :         if (!mp_parse_node_is_const_false(pns_elif->nodes[0])) {
    1351                 :       1175 :             uint l_fail = comp_next_label(comp);
    1352                 :       1175 :             c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
    1353                 :            : 
    1354                 :       1175 :             compile_node(comp, pns_elif->nodes[1]); // elif block
    1355                 :            : 
    1356                 :            :             // optimisation: skip everything else when "elif True"
    1357         [ +  + ]:       1175 :             if (mp_parse_node_is_const_true(pns_elif->nodes[0])) {
    1358                 :          8 :                 goto done;
    1359                 :            :             }
    1360                 :            : 
    1361                 :       1167 :             EMIT_ARG(jump, l_end);
    1362                 :       1167 :             EMIT_ARG(label_assign, l_fail);
    1363                 :            :         }
    1364                 :            :     }
    1365                 :            : 
    1366                 :            :     // compile else block
    1367                 :       7241 :     compile_node(comp, pns->nodes[3]); // can be null
    1368                 :            : 
    1369                 :       7433 : done:
    1370                 :       7433 :     EMIT_ARG(label_assign, l_end);
    1371                 :       7433 : }
    1372                 :            : 
    1373                 :            : #define START_BREAK_CONTINUE_BLOCK \
    1374                 :            :     uint16_t old_break_label = comp->break_label; \
    1375                 :            :     uint16_t old_continue_label = comp->continue_label; \
    1376                 :            :     uint16_t old_break_continue_except_level = comp->break_continue_except_level; \
    1377                 :            :     uint break_label = comp_next_label(comp); \
    1378                 :            :     uint continue_label = comp_next_label(comp); \
    1379                 :            :     comp->break_label = break_label; \
    1380                 :            :     comp->continue_label = continue_label; \
    1381                 :            :     comp->break_continue_except_level = comp->cur_except_level;
    1382                 :            : 
    1383                 :            : #define END_BREAK_CONTINUE_BLOCK \
    1384                 :            :     comp->break_label = old_break_label; \
    1385                 :            :     comp->continue_label = old_continue_label; \
    1386                 :            :     comp->break_continue_except_level = old_break_continue_except_level;
    1387                 :            : 
    1388                 :       1592 : STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1389                 :       1592 :     START_BREAK_CONTINUE_BLOCK
    1390                 :            : 
    1391         [ +  + ]:       1592 :     if (!mp_parse_node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False"
    1392                 :       1552 :         uint top_label = comp_next_label(comp);
    1393         [ +  + ]:       1552 :         if (!mp_parse_node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for "while True"
    1394                 :        810 :             EMIT_ARG(jump, continue_label);
    1395                 :            :         }
    1396                 :       1552 :         EMIT_ARG(label_assign, top_label);
    1397                 :       1552 :         compile_node(comp, pns->nodes[1]); // body
    1398                 :       1552 :         EMIT_ARG(label_assign, continue_label);
    1399                 :       1552 :         c_if_cond(comp, pns->nodes[0], true, top_label); // condition
    1400                 :            :     }
    1401                 :            : 
    1402                 :            :     // break/continue apply to outer loop (if any) in the else block
    1403                 :       1592 :     END_BREAK_CONTINUE_BLOCK
    1404                 :            : 
    1405                 :       1592 :     compile_node(comp, pns->nodes[2]); // else
    1406                 :            : 
    1407                 :       1592 :     EMIT_ARG(label_assign, break_label);
    1408                 :       1592 : }
    1409                 :            : 
    1410                 :            : // This function compiles an optimised for-loop of the form:
    1411                 :            : //      for <var> in range(<start>, <end>, <step>):
    1412                 :            : //          <body>
    1413                 :            : //      else:
    1414                 :            : //          <else>
    1415                 :            : // <var> must be an identifier and <step> must be a small-int.
    1416                 :            : //
    1417                 :            : // Semantics of for-loop require:
    1418                 :            : //  - final failing value should not be stored in the loop variable
    1419                 :            : //  - if the loop never runs, the loop variable should never be assigned
    1420                 :            : //  - assignments to <var>, <end> or <step> in the body do not alter the loop
    1421                 :            : //    (<step> is a constant for us, so no need to worry about it changing)
    1422                 :            : //
    1423                 :            : // If <end> is a small-int, then the stack during the for-loop contains just
    1424                 :            : // the current value of <var>.  Otherwise, the stack contains <end> then the
    1425                 :            : // current value of <var>.
    1426                 :       2127 : STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) {
    1427                 :       2127 :     START_BREAK_CONTINUE_BLOCK
    1428                 :            : 
    1429                 :       2127 :     uint top_label = comp_next_label(comp);
    1430                 :       2127 :     uint entry_label = comp_next_label(comp);
    1431                 :            : 
    1432                 :            :     // put the end value on the stack if it's not a small-int constant
    1433                 :       2127 :     bool end_on_stack = !MP_PARSE_NODE_IS_SMALL_INT(pn_end);
    1434         [ +  + ]:       2127 :     if (end_on_stack) {
    1435                 :       1037 :         compile_node(comp, pn_end);
    1436                 :            :     }
    1437                 :            : 
    1438                 :            :     // compile: start
    1439                 :       2127 :     compile_node(comp, pn_start);
    1440                 :            : 
    1441                 :       2127 :     EMIT_ARG(jump, entry_label);
    1442                 :       2127 :     EMIT_ARG(label_assign, top_label);
    1443                 :            : 
    1444                 :            :     // duplicate next value and store it to var
    1445                 :       2127 :     EMIT(dup_top);
    1446                 :       2127 :     c_assign(comp, pn_var, ASSIGN_STORE);
    1447                 :            : 
    1448                 :            :     // compile body
    1449                 :       2127 :     compile_node(comp, pn_body);
    1450                 :            : 
    1451                 :       2127 :     EMIT_ARG(label_assign, continue_label);
    1452                 :            : 
    1453                 :            :     // compile: var + step
    1454                 :       2127 :     compile_node(comp, pn_step);
    1455                 :       2127 :     EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);
    1456                 :            : 
    1457                 :       2127 :     EMIT_ARG(label_assign, entry_label);
    1458                 :            : 
    1459                 :            :     // compile: if var <cond> end: goto top
    1460         [ +  + ]:       2127 :     if (end_on_stack) {
    1461                 :       1037 :         EMIT(dup_top_two);
    1462                 :       1037 :         EMIT(rot_two);
    1463                 :            :     } else {
    1464                 :       1090 :         EMIT(dup_top);
    1465                 :       1090 :         compile_node(comp, pn_end);
    1466                 :            :     }
    1467         [ -  + ]:       2127 :     assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
    1468         [ +  + ]:       2127 :     if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
    1469                 :       2110 :         EMIT_ARG(binary_op, MP_BINARY_OP_LESS);
    1470                 :            :     } else {
    1471                 :         17 :         EMIT_ARG(binary_op, MP_BINARY_OP_MORE);
    1472                 :            :     }
    1473                 :       2127 :     EMIT_ARG(pop_jump_if, true, top_label);
    1474                 :            : 
    1475                 :            :     // break/continue apply to outer loop (if any) in the else block
    1476                 :       2127 :     END_BREAK_CONTINUE_BLOCK
    1477                 :            : 
    1478                 :            :     // Compile the else block.  We must pop the iterator variables before
    1479                 :            :     // executing the else code because it may contain break/continue statements.
    1480                 :       2127 :     uint end_label = 0;
    1481         [ +  + ]:       2127 :     if (!MP_PARSE_NODE_IS_NULL(pn_else)) {
    1482                 :            :         // discard final value of "var", and possible "end" value
    1483                 :         32 :         EMIT(pop_top);
    1484         [ +  + ]:         32 :         if (end_on_stack) {
    1485                 :          8 :             EMIT(pop_top);
    1486                 :            :         }
    1487                 :         32 :         compile_node(comp, pn_else);
    1488                 :         32 :         end_label = comp_next_label(comp);
    1489                 :         32 :         EMIT_ARG(jump, end_label);
    1490                 :         32 :         EMIT_ARG(adjust_stack_size, 1 + end_on_stack);
    1491                 :            :     }
    1492                 :            : 
    1493                 :       2127 :     EMIT_ARG(label_assign, break_label);
    1494                 :            : 
    1495                 :            :     // discard final value of var that failed the loop condition
    1496                 :       2127 :     EMIT(pop_top);
    1497                 :            : 
    1498                 :            :     // discard <end> value if it's on the stack
    1499         [ +  + ]:       2127 :     if (end_on_stack) {
    1500                 :       1037 :         EMIT(pop_top);
    1501                 :            :     }
    1502                 :            : 
    1503         [ +  + ]:       2127 :     if (!MP_PARSE_NODE_IS_NULL(pn_else)) {
    1504                 :         32 :         EMIT_ARG(label_assign, end_label);
    1505                 :            :     }
    1506                 :       2127 : }
    1507                 :            : 
    1508                 :       4905 : STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1509                 :            :     // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
    1510                 :            :     // this is actually slower, but uses no heap memory
    1511                 :            :     // for viper it will be much, much faster
    1512   [ +  +  +  -  :       4905 :     if (/*comp->scope_cur->emit_options == MP_EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_atom_expr_normal)) {
             +  +  +  + ]
    1513                 :       2683 :         mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t *)pns->nodes[1];
    1514         [ +  - ]:       2683 :         if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
    1515         [ +  + ]:       2683 :             && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
    1516         [ +  - ]:       2251 :             && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pns_it->nodes[1]) == PN_trailer_paren) {
    1517                 :       2251 :             mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t *)pns_it->nodes[1])->nodes[0];
    1518                 :       2251 :             mp_parse_node_t *args;
    1519                 :       2251 :             size_t n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args);
    1520                 :       2251 :             mp_parse_node_t pn_range_start;
    1521                 :       2251 :             mp_parse_node_t pn_range_end;
    1522                 :       2251 :             mp_parse_node_t pn_range_step;
    1523                 :       2251 :             bool optimize = false;
    1524         [ +  - ]:       2251 :             if (1 <= n_args && n_args <= 3) {
    1525                 :       2251 :                 optimize = true;
    1526         [ +  + ]:       2251 :                 if (n_args == 1) {
    1527                 :       1726 :                     pn_range_start = mp_parse_node_new_small_int(0);
    1528                 :       1726 :                     pn_range_end = args[0];
    1529                 :       1726 :                     pn_range_step = mp_parse_node_new_small_int(1);
    1530         [ +  + ]:        525 :                 } else if (n_args == 2) {
    1531                 :        430 :                     pn_range_start = args[0];
    1532                 :        430 :                     pn_range_end = args[1];
    1533                 :        430 :                     pn_range_step = mp_parse_node_new_small_int(1);
    1534                 :            :                 } else {
    1535                 :         95 :                     pn_range_start = args[0];
    1536                 :         95 :                     pn_range_end = args[1];
    1537                 :         95 :                     pn_range_step = args[2];
    1538                 :            :                     // the step must be a non-zero constant integer to do the optimisation
    1539         [ +  + ]:         95 :                     if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)
    1540         [ +  + ]:         52 :                         || MP_PARSE_NODE_LEAF_SMALL_INT(pn_range_step) == 0) {
    1541                 :         52 :                         optimize = false;
    1542                 :            :                     }
    1543                 :            :                 }
    1544                 :            :                 // arguments must be able to be compiled as standard expressions
    1545   [ +  +  +  + ]:       2251 :                 if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_start)) {
    1546                 :         17 :                     int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pn_range_start);
    1547         [ +  + ]:         17 :                     if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {
    1548                 :          9 :                         optimize = false;
    1549                 :            :                     }
    1550                 :            :                 }
    1551   [ +  +  +  + ]:       2251 :                 if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_end)) {
    1552                 :        545 :                     int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pn_range_end);
    1553         [ +  + ]:        545 :                     if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {
    1554                 :         63 :                         optimize = false;
    1555                 :            :                     }
    1556                 :            :                 }
    1557                 :            :             }
    1558         [ +  + ]:       2251 :             if (optimize) {
    1559                 :       2127 :                 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
    1560                 :       2127 :                 return;
    1561                 :            :             }
    1562                 :            :         }
    1563                 :            :     }
    1564                 :            : 
    1565                 :       2778 :     START_BREAK_CONTINUE_BLOCK
    1566                 :       2778 :     comp->break_label |= MP_EMIT_BREAK_FROM_FOR;
    1567                 :            : 
    1568                 :       2778 :     uint pop_label = comp_next_label(comp);
    1569                 :            : 
    1570                 :       2778 :     compile_node(comp, pns->nodes[1]); // iterator
    1571                 :       2778 :     EMIT_ARG(get_iter, true);
    1572                 :       2778 :     EMIT_ARG(label_assign, continue_label);
    1573                 :       2778 :     EMIT_ARG(for_iter, pop_label);
    1574                 :       2778 :     c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
    1575                 :       2778 :     compile_node(comp, pns->nodes[2]); // body
    1576                 :       2778 :     EMIT_ARG(jump, continue_label);
    1577                 :       2778 :     EMIT_ARG(label_assign, pop_label);
    1578                 :       2778 :     EMIT(for_iter_end);
    1579                 :            : 
    1580                 :            :     // break/continue apply to outer loop (if any) in the else block
    1581                 :       2778 :     END_BREAK_CONTINUE_BLOCK
    1582                 :            : 
    1583                 :       2778 :     compile_node(comp, pns->nodes[3]); // else (may be empty)
    1584                 :            : 
    1585                 :       2778 :     EMIT_ARG(label_assign, break_label);
    1586                 :            : }
    1587                 :            : 
    1588                 :      49563 : STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) {
    1589                 :            :     // setup code
    1590                 :      49563 :     uint l1 = comp_next_label(comp);
    1591                 :      49563 :     uint success_label = comp_next_label(comp);
    1592                 :            : 
    1593                 :      49563 :     compile_increase_except_level(comp, l1, MP_EMIT_SETUP_BLOCK_EXCEPT);
    1594                 :            : 
    1595                 :      49563 :     compile_node(comp, pn_body); // body
    1596                 :      49563 :     EMIT_ARG(pop_except_jump, success_label, false); // jump over exception handler
    1597                 :            : 
    1598                 :      49563 :     EMIT_ARG(label_assign, l1); // start of exception handler
    1599                 :      49563 :     EMIT(start_except_handler);
    1600                 :            : 
    1601                 :            :     // at this point the top of the stack contains the exception instance that was raised
    1602                 :            : 
    1603                 :      49563 :     uint l2 = comp_next_label(comp);
    1604                 :            : 
    1605         [ +  + ]:      99208 :     for (int i = 0; i < n_except; i++) {
    1606   [ +  -  +  -  :      49649 :         assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
                   -  + ]
    1607                 :      49649 :         mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t *)pn_excepts[i];
    1608                 :            : 
    1609                 :      49649 :         qstr qstr_exception_local = 0;
    1610                 :      49649 :         uint end_finally_label = comp_next_label(comp);
    1611                 :            :         #if MICROPY_PY_SYS_SETTRACE
    1612                 :            :         EMIT_ARG(set_source_line, pns_except->source_line);
    1613                 :            :         #endif
    1614                 :            : 
    1615         [ +  + ]:      49649 :         if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
    1616                 :            :             // this is a catch all exception handler
    1617         [ +  + ]:       1508 :             if (i + 1 != n_except) {
    1618                 :          4 :                 compile_syntax_error(comp, pn_excepts[i], MP_ERROR_TEXT("default 'except' must be last"));
    1619                 :          4 :                 compile_decrease_except_level(comp);
    1620                 :          4 :                 return;
    1621                 :            :             }
    1622                 :            :         } else {
    1623                 :            :             // this exception handler requires a match to a certain type of exception
    1624                 :      48141 :             mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
    1625         [ +  + ]:      48141 :             if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
    1626                 :       1929 :                 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t *)pns_exception_expr;
    1627         [ +  + ]:       1929 :                 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
    1628                 :            :                     // handler binds the exception to a local
    1629                 :       1430 :                     pns_exception_expr = pns3->nodes[0];
    1630                 :       1430 :                     qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
    1631                 :            :                 }
    1632                 :            :             }
    1633                 :      48141 :             EMIT(dup_top);
    1634                 :      48141 :             compile_node(comp, pns_exception_expr);
    1635                 :      48141 :             EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
    1636                 :      48141 :             EMIT_ARG(pop_jump_if, false, end_finally_label);
    1637                 :            :         }
    1638                 :            : 
    1639                 :            :         // either discard or store the exception instance
    1640         [ +  + ]:      48141 :         if (qstr_exception_local == 0) {
    1641                 :      48215 :             EMIT(pop_top);
    1642                 :            :         } else {
    1643                 :       1430 :             compile_store_id(comp, qstr_exception_local);
    1644                 :            :         }
    1645                 :            : 
    1646                 :            :         // If the exception is bound to a variable <e> then the <body> of the
    1647                 :            :         // exception handler is wrapped in a try-finally so that the name <e> can
    1648                 :            :         // be deleted (per Python semantics) even if the <body> has an exception.
    1649                 :            :         // In such a case the generated code for the exception handler is:
    1650                 :            :         //      try:
    1651                 :            :         //          <body>
    1652                 :            :         //      finally:
    1653                 :            :         //          <e> = None
    1654                 :            :         //          del <e>
    1655                 :      49645 :         uint l3 = 0;
    1656         [ +  + ]:      49645 :         if (qstr_exception_local != 0) {
    1657                 :       1430 :             l3 = comp_next_label(comp);
    1658                 :       1430 :             compile_increase_except_level(comp, l3, MP_EMIT_SETUP_BLOCK_FINALLY);
    1659                 :            :         }
    1660                 :      49645 :         compile_node(comp, pns_except->nodes[1]); // the <body>
    1661         [ +  + ]:      49645 :         if (qstr_exception_local != 0) {
    1662                 :       1430 :             EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    1663                 :       1430 :             EMIT_ARG(label_assign, l3);
    1664                 :       1430 :             EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    1665                 :       1430 :             compile_store_id(comp, qstr_exception_local);
    1666                 :       1430 :             compile_delete_id(comp, qstr_exception_local);
    1667                 :       1430 :             compile_decrease_except_level(comp);
    1668                 :            :         }
    1669                 :            : 
    1670                 :      49645 :         EMIT_ARG(pop_except_jump, l2, true);
    1671                 :      49645 :         EMIT_ARG(label_assign, end_finally_label);
    1672                 :      49645 :         EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance
    1673                 :            :     }
    1674                 :            : 
    1675                 :      49559 :     compile_decrease_except_level(comp);
    1676                 :      49559 :     EMIT(end_except_handler);
    1677                 :            : 
    1678                 :      49559 :     EMIT_ARG(label_assign, success_label);
    1679                 :      49559 :     compile_node(comp, pn_else); // else block, can be null
    1680                 :      49559 :     EMIT_ARG(label_assign, l2);
    1681                 :            : }
    1682                 :            : 
    1683                 :        975 : STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) {
    1684                 :        975 :     uint l_finally_block = comp_next_label(comp);
    1685                 :            : 
    1686                 :        975 :     compile_increase_except_level(comp, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY);
    1687                 :            : 
    1688         [ +  + ]:        975 :     if (n_except == 0) {
    1689         [ -  + ]:        883 :         assert(MP_PARSE_NODE_IS_NULL(pn_else));
    1690                 :        883 :         EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state
    1691                 :        883 :         compile_node(comp, pn_body);
    1692                 :        883 :         EMIT_ARG(adjust_stack_size, -3);
    1693                 :            :     } else {
    1694                 :         92 :         compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
    1695                 :            :     }
    1696                 :        975 :     EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    1697                 :        975 :     EMIT_ARG(label_assign, l_finally_block);
    1698                 :        975 :     compile_node(comp, pn_finally);
    1699                 :            : 
    1700                 :        975 :     compile_decrease_except_level(comp);
    1701                 :        975 : }
    1702                 :            : 
    1703                 :      50446 : STATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1704   [ +  -  -  + ]:      50446 :     assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should be
    1705                 :            :     {
    1706                 :      50446 :         mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t *)pns->nodes[1];
    1707         [ +  + ]:      50446 :         if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
    1708                 :            :             // just try-finally
    1709                 :        883 :             compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
    1710         [ +  + ]:      49563 :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
    1711                 :            :             // try-except and possibly else and/or finally
    1712                 :        464 :             mp_parse_node_t *pn_excepts;
    1713                 :        464 :             size_t n_except = mp_parse_node_extract_list(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
    1714         [ +  + ]:        464 :             if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
    1715                 :            :                 // no finally
    1716                 :        372 :                 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
    1717                 :            :             } else {
    1718                 :            :                 // have finally
    1719                 :         92 :                 compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((mp_parse_node_struct_t *)pns2->nodes[2])->nodes[0]);
    1720                 :            :             }
    1721                 :            :         } else {
    1722                 :            :             // just try-except
    1723                 :      49099 :             mp_parse_node_t *pn_excepts;
    1724                 :      49099 :             size_t n_except = mp_parse_node_extract_list(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
    1725                 :      49099 :             compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
    1726                 :            :         }
    1727                 :            :     }
    1728                 :      50446 : }
    1729                 :            : 
    1730                 :      73656 : STATIC void compile_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_node_t *nodes, mp_parse_node_t body) {
    1731         [ +  + ]:      73656 :     if (n == 0) {
    1732                 :            :         // no more pre-bits, compile the body of the with
    1733                 :      36828 :         compile_node(comp, body);
    1734                 :            :     } else {
    1735                 :      36828 :         uint l_end = comp_next_label(comp);
    1736   [ +  -  +  +  :      73442 :         if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
                   +  + ]
    1737                 :            :             // this pre-bit is of the form "a as b"
    1738                 :      36614 :             mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)nodes[0];
    1739                 :      36614 :             compile_node(comp, pns->nodes[0]);
    1740                 :      36614 :             compile_increase_except_level(comp, l_end, MP_EMIT_SETUP_BLOCK_WITH);
    1741                 :      36614 :             c_assign(comp, pns->nodes[1], ASSIGN_STORE);
    1742                 :            :         } else {
    1743                 :            :             // this pre-bit is just an expression
    1744                 :        214 :             compile_node(comp, nodes[0]);
    1745                 :        214 :             compile_increase_except_level(comp, l_end, MP_EMIT_SETUP_BLOCK_WITH);
    1746                 :        214 :             EMIT(pop_top);
    1747                 :            :         }
    1748                 :            :         // compile additional pre-bits and the body
    1749                 :      36828 :         compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
    1750                 :            :         // finish this with block
    1751                 :      36828 :         EMIT_ARG(with_cleanup, l_end);
    1752                 :      36828 :         reserve_labels_for_native(comp, 3); // used by native's with_cleanup
    1753                 :      36828 :         compile_decrease_except_level(comp);
    1754                 :            :     }
    1755                 :      73656 : }
    1756                 :            : 
    1757                 :      36828 : STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1758                 :            :     // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
    1759                 :      36828 :     mp_parse_node_t *nodes;
    1760                 :      36828 :     size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);
    1761         [ -  + ]:      36828 :     assert(n > 0);
    1762                 :            : 
    1763                 :            :     // compile in a nested fashion
    1764                 :      36828 :     compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
    1765                 :      36828 : }
    1766                 :            : 
    1767                 :       1840 : STATIC void compile_yield_from(compiler_t *comp) {
    1768                 :       1840 :     EMIT_ARG(get_iter, false);
    1769                 :       1840 :     EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    1770                 :       1840 :     EMIT_ARG(yield, MP_EMIT_YIELD_FROM);
    1771                 :       1836 :     reserve_labels_for_native(comp, 3);
    1772                 :       1836 : }
    1773                 :            : 
    1774                 :            : #if MICROPY_PY_ASYNC_AWAIT
    1775                 :         72 : STATIC void compile_await_object_method(compiler_t *comp, qstr method) {
    1776                 :         72 :     EMIT_ARG(load_method, method, false);
    1777                 :         72 :     EMIT_ARG(call_method, 0, 0, 0);
    1778                 :         72 :     compile_yield_from(comp);
    1779                 :         72 : }
    1780                 :            : 
    1781                 :         16 : STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1782                 :            :     // comp->break_label |= MP_EMIT_BREAK_FROM_FOR;
    1783                 :            : 
    1784                 :         16 :     qstr context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
    1785                 :         16 :     uint while_else_label = comp_next_label(comp);
    1786                 :         16 :     uint try_exception_label = comp_next_label(comp);
    1787                 :         16 :     uint try_else_label = comp_next_label(comp);
    1788                 :         16 :     uint try_finally_label = comp_next_label(comp);
    1789                 :            : 
    1790                 :         16 :     compile_node(comp, pns->nodes[1]); // iterator
    1791                 :         16 :     EMIT_ARG(load_method, MP_QSTR___aiter__, false);
    1792                 :         16 :     EMIT_ARG(call_method, 0, 0, 0);
    1793                 :         16 :     compile_store_id(comp, context);
    1794                 :            : 
    1795                 :         16 :     START_BREAK_CONTINUE_BLOCK
    1796                 :            : 
    1797                 :         16 :     EMIT_ARG(label_assign, continue_label);
    1798                 :            : 
    1799                 :         16 :     compile_increase_except_level(comp, try_exception_label, MP_EMIT_SETUP_BLOCK_EXCEPT);
    1800                 :            : 
    1801                 :         16 :     compile_load_id(comp, context);
    1802                 :         16 :     compile_await_object_method(comp, MP_QSTR___anext__);
    1803                 :         16 :     c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
    1804                 :         16 :     EMIT_ARG(pop_except_jump, try_else_label, false);
    1805                 :            : 
    1806                 :         16 :     EMIT_ARG(label_assign, try_exception_label);
    1807                 :         16 :     EMIT(start_except_handler);
    1808                 :         16 :     EMIT(dup_top);
    1809                 :         16 :     EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration);
    1810                 :         16 :     EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
    1811                 :         16 :     EMIT_ARG(pop_jump_if, false, try_finally_label);
    1812                 :         16 :     EMIT(pop_top); // pop exception instance
    1813                 :         16 :     EMIT_ARG(pop_except_jump, while_else_label, true);
    1814                 :            : 
    1815                 :         16 :     EMIT_ARG(label_assign, try_finally_label);
    1816                 :         16 :     EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack
    1817                 :         16 :     compile_decrease_except_level(comp);
    1818                 :         16 :     EMIT(end_except_handler);
    1819                 :            : 
    1820                 :         16 :     EMIT_ARG(label_assign, try_else_label);
    1821                 :         16 :     compile_node(comp, pns->nodes[2]); // body
    1822                 :            : 
    1823                 :         16 :     EMIT_ARG(jump, continue_label);
    1824                 :            :     // break/continue apply to outer loop (if any) in the else block
    1825                 :         16 :     END_BREAK_CONTINUE_BLOCK
    1826                 :            : 
    1827                 :         16 :     EMIT_ARG(label_assign, while_else_label);
    1828                 :         16 :     compile_node(comp, pns->nodes[3]); // else
    1829                 :            : 
    1830                 :         16 :     EMIT_ARG(label_assign, break_label);
    1831                 :         16 : }
    1832                 :            : 
    1833                 :        112 : STATIC void compile_async_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_node_t *nodes, mp_parse_node_t body) {
    1834         [ +  + ]:        112 :     if (n == 0) {
    1835                 :            :         // no more pre-bits, compile the body of the with
    1836                 :         56 :         compile_node(comp, body);
    1837                 :            :     } else {
    1838                 :         56 :         uint l_finally_block = comp_next_label(comp);
    1839                 :         56 :         uint l_aexit_no_exc = comp_next_label(comp);
    1840                 :         56 :         uint l_ret_unwind_jump = comp_next_label(comp);
    1841                 :         56 :         uint l_end = comp_next_label(comp);
    1842                 :            : 
    1843   [ +  -  +  +  :         60 :         if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
                   +  + ]
    1844                 :            :             // this pre-bit is of the form "a as b"
    1845                 :          4 :             mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)nodes[0];
    1846                 :          4 :             compile_node(comp, pns->nodes[0]);
    1847                 :          4 :             EMIT(dup_top);
    1848                 :          4 :             compile_await_object_method(comp, MP_QSTR___aenter__);
    1849                 :          4 :             c_assign(comp, pns->nodes[1], ASSIGN_STORE);
    1850                 :            :         } else {
    1851                 :            :             // this pre-bit is just an expression
    1852                 :         52 :             compile_node(comp, nodes[0]);
    1853                 :         52 :             EMIT(dup_top);
    1854                 :         52 :             compile_await_object_method(comp, MP_QSTR___aenter__);
    1855                 :         52 :             EMIT(pop_top);
    1856                 :            :         }
    1857                 :            : 
    1858                 :            :         // To keep the Python stack size down, and because we can't access values on
    1859                 :            :         // this stack further down than 3 elements (via rot_three), we don't preload
    1860                 :            :         // __aexit__ (as per normal with) but rather wait until we need it below.
    1861                 :            : 
    1862                 :            :         // Start the try-finally statement
    1863                 :         56 :         compile_increase_except_level(comp, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY);
    1864                 :            : 
    1865                 :            :         // Compile any additional pre-bits of the "async with", and also the body
    1866                 :         56 :         EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state
    1867                 :         56 :         compile_async_with_stmt_helper(comp, n - 1, nodes + 1, body);
    1868                 :         56 :         EMIT_ARG(adjust_stack_size, -3);
    1869                 :            : 
    1870                 :            :         // We have now finished the "try" block and fall through to the "finally"
    1871                 :            : 
    1872                 :            :         // At this point, after the with body has executed, we have 3 cases:
    1873                 :            :         // 1. no exception, we just fall through to this point; stack: (..., ctx_mgr)
    1874                 :            :         // 2. exception propagating out, we get to the finally block; stack: (..., ctx_mgr, exc)
    1875                 :            :         // 3. return or unwind jump, we get to the finally block; stack: (..., ctx_mgr, X, INT)
    1876                 :            : 
    1877                 :            :         // Handle case 1: call __aexit__
    1878                 :            :         // Stack: (..., ctx_mgr)
    1879                 :         56 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // to tell end_finally there's no exception
    1880                 :         56 :         EMIT(rot_two);
    1881                 :         56 :         EMIT_ARG(jump, l_aexit_no_exc); // jump to code below to call __aexit__
    1882                 :            : 
    1883                 :            :         // Start of "finally" block
    1884                 :            :         // At this point we have case 2 or 3, we detect which one by the TOS being an exception or not
    1885                 :         56 :         EMIT_ARG(label_assign, l_finally_block);
    1886                 :            : 
    1887                 :            :         // Detect if TOS an exception or not
    1888                 :         56 :         EMIT(dup_top);
    1889                 :         56 :         EMIT_LOAD_GLOBAL(MP_QSTR_BaseException);
    1890                 :         56 :         EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
    1891                 :         56 :         EMIT_ARG(pop_jump_if, false, l_ret_unwind_jump); // if not an exception then we have case 3
    1892                 :            : 
    1893                 :            :         // Handle case 2: call __aexit__ and either swallow or re-raise the exception
    1894                 :            :         // Stack: (..., ctx_mgr, exc)
    1895                 :         56 :         EMIT(dup_top);
    1896                 :         56 :         EMIT(rot_three);
    1897                 :         56 :         EMIT(rot_two);
    1898                 :         56 :         EMIT_ARG(load_method, MP_QSTR___aexit__, false);
    1899                 :         56 :         EMIT(rot_three);
    1900                 :         56 :         EMIT(rot_three);
    1901                 :         56 :         EMIT(dup_top);
    1902                 :            :         #if MICROPY_CPYTHON_COMPAT
    1903                 :         56 :         EMIT_ARG(attr, MP_QSTR___class__, MP_EMIT_ATTR_LOAD); // get type(exc)
    1904                 :            :         #else
    1905                 :            :         compile_load_id(comp, MP_QSTR_type);
    1906                 :            :         EMIT(rot_two);
    1907                 :            :         EMIT_ARG(call_function, 1, 0, 0); // get type(exc)
    1908                 :            :         #endif
    1909                 :         56 :         EMIT(rot_two);
    1910                 :         56 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // dummy traceback value
    1911                 :            :         // Stack: (..., exc, __aexit__, ctx_mgr, type(exc), exc, None)
    1912                 :         56 :         EMIT_ARG(call_method, 3, 0, 0);
    1913                 :         56 :         compile_yield_from(comp);
    1914                 :         56 :         EMIT_ARG(pop_jump_if, false, l_end);
    1915                 :         56 :         EMIT(pop_top); // pop exception
    1916                 :         56 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // replace with None to swallow exception
    1917                 :         56 :         EMIT_ARG(jump, l_end);
    1918                 :         56 :         EMIT_ARG(adjust_stack_size, 2);
    1919                 :            : 
    1920                 :            :         // Handle case 3: call __aexit__
    1921                 :            :         // Stack: (..., ctx_mgr, X, INT)
    1922                 :         56 :         EMIT_ARG(label_assign, l_ret_unwind_jump);
    1923                 :         56 :         EMIT(rot_three);
    1924                 :         56 :         EMIT(rot_three);
    1925                 :         56 :         EMIT_ARG(label_assign, l_aexit_no_exc);
    1926                 :         56 :         EMIT_ARG(load_method, MP_QSTR___aexit__, false);
    1927                 :         56 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    1928                 :         56 :         EMIT(dup_top);
    1929                 :         56 :         EMIT(dup_top);
    1930                 :         56 :         EMIT_ARG(call_method, 3, 0, 0);
    1931                 :         56 :         compile_yield_from(comp);
    1932                 :         56 :         EMIT(pop_top);
    1933                 :         56 :         EMIT_ARG(adjust_stack_size, -1);
    1934                 :            : 
    1935                 :            :         // End of "finally" block
    1936                 :            :         // Stack can have one of three configurations:
    1937                 :            :         // a. (..., None) - from either case 1, or case 2 with swallowed exception
    1938                 :            :         // b. (..., exc) - from case 2 with re-raised exception
    1939                 :            :         // c. (..., X, INT) - from case 3
    1940                 :         56 :         EMIT_ARG(label_assign, l_end);
    1941                 :         56 :         compile_decrease_except_level(comp);
    1942                 :            :     }
    1943                 :        112 : }
    1944                 :            : 
    1945                 :         56 : STATIC void compile_async_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1946                 :            :     // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
    1947                 :         56 :     mp_parse_node_t *nodes;
    1948                 :         56 :     size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);
    1949         [ -  + ]:         56 :     assert(n > 0);
    1950                 :            : 
    1951                 :            :     // compile in a nested fashion
    1952                 :         56 :     compile_async_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
    1953                 :         56 : }
    1954                 :            : 
    1955                 :       1264 : STATIC void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1956   [ +  -  -  + ]:       1264 :     assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[0]));
    1957                 :       1264 :     mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t *)pns->nodes[0];
    1958         [ +  + ]:       1264 :     if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_funcdef) {
    1959                 :            :         // async def
    1960                 :       1184 :         compile_funcdef(comp, pns0);
    1961                 :       1184 :         scope_t *fscope = (scope_t *)pns0->nodes[4];
    1962                 :       1184 :         fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
    1963                 :            :     } else {
    1964                 :            :         // async for/with; first verify the scope is a generator
    1965                 :         80 :         int scope_flags = comp->scope_cur->scope_flags;
    1966         [ +  + ]:         80 :         if (!(scope_flags & MP_SCOPE_FLAG_GENERATOR)) {
    1967                 :          8 :             compile_syntax_error(comp, (mp_parse_node_t)pns0,
    1968                 :          8 :                 MP_ERROR_TEXT("async for/with outside async function"));
    1969                 :          8 :             return;
    1970                 :            :         }
    1971                 :            : 
    1972         [ +  + ]:         72 :         if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_for_stmt) {
    1973                 :            :             // async for
    1974                 :         16 :             compile_async_for_stmt(comp, pns0);
    1975                 :            :         } else {
    1976                 :            :             // async with
    1977         [ -  + ]:         56 :             assert(MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_with_stmt);
    1978                 :         56 :             compile_async_with_stmt(comp, pns0);
    1979                 :            :         }
    1980                 :            :     }
    1981                 :            : }
    1982                 :            : #endif
    1983                 :            : 
    1984                 :     162744 : STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
    1985                 :     162744 :     mp_parse_node_t pn_rhs = pns->nodes[1];
    1986         [ +  + ]:     162744 :     if (MP_PARSE_NODE_IS_NULL(pn_rhs)) {
    1987   [ +  +  +  + ]:     126359 :         if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
    1988                 :            :             // for REPL, evaluate then print the expression
    1989                 :        456 :             compile_load_id(comp, MP_QSTR___repl_print__);
    1990                 :        456 :             compile_node(comp, pns->nodes[0]);
    1991                 :        456 :             EMIT_ARG(call_function, 1, 0, 0);
    1992                 :        456 :             EMIT(pop_top);
    1993                 :            : 
    1994                 :            :         } else {
    1995                 :            :             // for non-REPL, evaluate then discard the expression
    1996   [ +  +  +  - ]:     125903 :             if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
    1997   [ +  -  +  +  :     125903 :                 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
                   +  - ]
    1998                 :            :                 // do nothing with a lonely constant
    1999                 :            :             } else {
    2000                 :     125903 :                 compile_node(comp, pns->nodes[0]); // just an expression
    2001                 :     125894 :                 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
    2002                 :            :             }
    2003                 :            :         }
    2004         [ +  + ]:      36385 :     } else if (MP_PARSE_NODE_IS_STRUCT(pn_rhs)) {
    2005                 :      22639 :         mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pn_rhs;
    2006                 :      22639 :         int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
    2007         [ +  + ]:      22639 :         if (kind == PN_annassign) {
    2008                 :            :             // the annotation is in pns1->nodes[0] and is ignored
    2009         [ +  + ]:         20 :             if (MP_PARSE_NODE_IS_NULL(pns1->nodes[1])) {
    2010                 :            :                 // an annotation of the form "x: y"
    2011                 :            :                 // inside a function this declares "x" as a local
    2012         [ +  + ]:         12 :                 if (comp->scope_cur->kind == SCOPE_FUNCTION) {
    2013         [ +  + ]:          8 :                     if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
    2014                 :          4 :                         qstr lhs = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
    2015                 :          4 :                         scope_find_or_add_id(comp->scope_cur, lhs, ID_INFO_KIND_LOCAL);
    2016                 :            :                     }
    2017                 :            :                 }
    2018                 :            :             } else {
    2019                 :            :                 // an assigned annotation of the form "x: y = z"
    2020                 :          8 :                 pn_rhs = pns1->nodes[1];
    2021                 :          8 :                 goto plain_assign;
    2022                 :            :             }
    2023         [ +  + ]:      22619 :         } else if (kind == PN_expr_stmt_augassign) {
    2024                 :       1539 :             c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
    2025                 :       1539 :             compile_node(comp, pns1->nodes[1]); // rhs
    2026         [ -  + ]:       1539 :             assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
    2027                 :       1539 :             mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);
    2028                 :       1539 :             mp_binary_op_t op = MP_BINARY_OP_INPLACE_OR + (tok - MP_TOKEN_DEL_PIPE_EQUAL);
    2029                 :       1539 :             EMIT_ARG(binary_op, op);
    2030                 :       1539 :             c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
    2031         [ +  + ]:      21080 :         } else if (kind == PN_expr_stmt_assign_list) {
    2032                 :        128 :             int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
    2033                 :        128 :             compile_node(comp, pns1->nodes[rhs]); // rhs
    2034                 :            :             // following CPython, we store left-most first
    2035         [ +  - ]:        128 :             if (rhs > 0) {
    2036                 :        128 :                 EMIT(dup_top);
    2037                 :            :             }
    2038                 :        128 :             c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
    2039         [ +  + ]:        400 :             for (int i = 0; i < rhs; i++) {
    2040         [ +  + ]:        272 :                 if (i + 1 < rhs) {
    2041                 :        144 :                     EMIT(dup_top);
    2042                 :            :                 }
    2043                 :        272 :                 c_assign(comp, pns1->nodes[i], ASSIGN_STORE); // middle store
    2044                 :            :             }
    2045                 :            :         } else {
    2046                 :      20952 :         plain_assign:
    2047                 :            :             #if MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
    2048   [ +  -  +  +  :      34706 :             if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_rhs, PN_testlist_star_expr)
                   +  + ]
    2049   [ +  -  +  -  :         68 :                 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)) {
                   +  - ]
    2050                 :         68 :                 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t *)pns->nodes[0];
    2051                 :         68 :                 pns1 = (mp_parse_node_struct_t *)pn_rhs;
    2052                 :         68 :                 uint32_t n_pns0 = MP_PARSE_NODE_STRUCT_NUM_NODES(pns0);
    2053                 :            :                 // Can only optimise a tuple-to-tuple assignment when all of the following hold:
    2054                 :            :                 //  - equal number of items in LHS and RHS tuples
    2055                 :            :                 //  - 2 or 3 items in the tuples
    2056                 :            :                 //  - there are no star expressions in the LHS tuple
    2057         [ +  - ]:         68 :                 if (n_pns0 == MP_PARSE_NODE_STRUCT_NUM_NODES(pns1)
    2058                 :         68 :                     && (n_pns0 == 2
    2059                 :            :                         #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
    2060         [ +  - ]:         68 :                         || n_pns0 == 3
    2061                 :            :                         #endif
    2062                 :            :                         )
    2063   [ +  -  +  +  :         68 :                     && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
                   +  - ]
    2064   [ +  -  +  +  :         68 :                     && !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)
                   +  - ]
    2065                 :            :                     #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
    2066   [ +  +  +  -  :         68 :                     && (n_pns0 == 2 || !MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr))
             -  +  -  - ]
    2067                 :            :                     #endif
    2068                 :            :                     ) {
    2069                 :            :                     // Optimisation for a, b = c, d or a, b, c = d, e, f
    2070                 :         68 :                     compile_node(comp, pns1->nodes[0]); // rhs
    2071                 :         68 :                     compile_node(comp, pns1->nodes[1]); // rhs
    2072                 :            :                     #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
    2073         [ +  + ]:         68 :                     if (n_pns0 == 3) {
    2074                 :         16 :                         compile_node(comp, pns1->nodes[2]); // rhs
    2075                 :         16 :                         EMIT(rot_three);
    2076                 :            :                     }
    2077                 :            :                     #endif
    2078                 :         68 :                     EMIT(rot_two);
    2079                 :         68 :                     c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
    2080                 :         68 :                     c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
    2081                 :            :                     #if MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
    2082         [ +  + ]:         68 :                     if (n_pns0 == 3) {
    2083                 :         16 :                         c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
    2084                 :            :                     }
    2085                 :            :                     #endif
    2086                 :         68 :                     return;
    2087                 :            :                 }
    2088                 :            :             }
    2089                 :            :             #endif
    2090                 :            : 
    2091                 :      34638 :             compile_node(comp, pn_rhs); // rhs
    2092                 :      34638 :             c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
    2093                 :            :         }
    2094                 :            :     } else {
    2095                 :      13746 :         goto plain_assign;
    2096                 :            :     }
    2097                 :            : }
    2098                 :            : 
    2099                 :        319 : STATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2100   [ +  -  +  -  :        319 :     assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
                   -  + ]
    2101                 :        319 :     mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t *)pns->nodes[1];
    2102                 :            : 
    2103                 :        319 :     uint l_fail = comp_next_label(comp);
    2104                 :        319 :     uint l_end = comp_next_label(comp);
    2105                 :        319 :     c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
    2106                 :        319 :     compile_node(comp, pns->nodes[0]); // success value
    2107                 :        319 :     EMIT_ARG(jump, l_end);
    2108                 :        319 :     EMIT_ARG(label_assign, l_fail);
    2109                 :        319 :     EMIT_ARG(adjust_stack_size, -1); // adjust stack size
    2110                 :        319 :     compile_node(comp, pns_test_if_else->nodes[1]); // failure value
    2111                 :        319 :     EMIT_ARG(label_assign, l_end);
    2112                 :        319 : }
    2113                 :            : 
    2114                 :        574 : STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2115         [ +  + ]:        574 :     if (comp->pass == MP_PASS_SCOPE) {
    2116                 :            :         // create a new scope for this lambda
    2117                 :        149 :         scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
    2118                 :            :         // store the lambda scope so the compiling function (this one) can use it at each pass
    2119                 :        149 :         pns->nodes[2] = (mp_parse_node_t)s;
    2120                 :            :     }
    2121                 :            : 
    2122                 :            :     // get the scope for this lambda
    2123                 :        574 :     scope_t *this_scope = (scope_t *)pns->nodes[2];
    2124                 :            : 
    2125                 :            :     // compile the lambda definition
    2126                 :        574 :     compile_funcdef_lambdef(comp, this_scope, pns->nodes[0], PN_varargslist);
    2127                 :        574 : }
    2128                 :            : 
    2129                 :            : #if MICROPY_PY_ASSIGN_EXPR
    2130                 :        124 : STATIC void compile_namedexpr_helper(compiler_t *comp, mp_parse_node_t pn_name, mp_parse_node_t pn_expr) {
    2131         [ +  + ]:        124 :     if (!MP_PARSE_NODE_IS_ID(pn_name)) {
    2132                 :          4 :         compile_syntax_error(comp, (mp_parse_node_t)pn_name, MP_ERROR_TEXT("can't assign to expression"));
    2133                 :            :     }
    2134                 :        124 :     compile_node(comp, pn_expr);
    2135                 :        124 :     EMIT(dup_top);
    2136                 :        124 :     scope_t *old_scope = comp->scope_cur;
    2137         [ +  + ]:        124 :     if (SCOPE_IS_COMP_LIKE(comp->scope_cur->kind)) {
    2138                 :            :         // Use parent's scope for assigned value so it can "escape"
    2139                 :         88 :         comp->scope_cur = comp->scope_cur->parent;
    2140                 :            :     }
    2141                 :        124 :     compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pn_name));
    2142                 :        124 :     comp->scope_cur = old_scope;
    2143                 :        124 : }
    2144                 :            : 
    2145                 :        108 : STATIC void compile_namedexpr(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2146                 :        108 :     compile_namedexpr_helper(comp, pns->nodes[0], pns->nodes[1]);
    2147                 :        108 : }
    2148                 :            : #endif
    2149                 :            : 
    2150                 :        469 : STATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2151                 :        469 :     bool cond = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test;
    2152                 :        469 :     uint l_end = comp_next_label(comp);
    2153                 :        469 :     int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
    2154         [ +  + ]:       1407 :     for (int i = 0; i < n; i += 1) {
    2155                 :        938 :         compile_node(comp, pns->nodes[i]);
    2156         [ +  + ]:        938 :         if (i + 1 < n) {
    2157                 :        469 :             EMIT_ARG(jump_if_or_pop, cond, l_end);
    2158                 :            :         }
    2159                 :            :     }
    2160                 :        469 :     EMIT_ARG(label_assign, l_end);
    2161                 :        469 : }
    2162                 :            : 
    2163                 :         96 : STATIC void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2164                 :         96 :     compile_node(comp, pns->nodes[0]);
    2165                 :         96 :     EMIT_ARG(unary_op, MP_UNARY_OP_NOT);
    2166                 :         96 : }
    2167                 :            : 
    2168                 :      15457 : STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2169                 :      15457 :     int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
    2170                 :      15457 :     compile_node(comp, pns->nodes[0]);
    2171                 :      15457 :     bool multi = (num_nodes > 3);
    2172                 :      15457 :     uint l_fail = 0;
    2173         [ +  + ]:      15457 :     if (multi) {
    2174                 :        238 :         l_fail = comp_next_label(comp);
    2175                 :            :     }
    2176         [ +  + ]:      31160 :     for (int i = 1; i + 1 < num_nodes; i += 2) {
    2177                 :      15703 :         compile_node(comp, pns->nodes[i + 1]);
    2178         [ +  + ]:      15703 :         if (i + 2 < num_nodes) {
    2179                 :        246 :             EMIT(dup_top);
    2180                 :        246 :             EMIT(rot_three);
    2181                 :            :         }
    2182         [ +  + ]:      15703 :         if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
    2183                 :      10667 :             mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]);
    2184                 :      10667 :             mp_binary_op_t op;
    2185         [ +  + ]:      10667 :             if (tok == MP_TOKEN_KW_IN) {
    2186                 :            :                 op = MP_BINARY_OP_IN;
    2187                 :            :             } else {
    2188                 :       9866 :                 op = MP_BINARY_OP_LESS + (tok - MP_TOKEN_OP_LESS);
    2189                 :            :             }
    2190                 :      10667 :             EMIT_ARG(binary_op, op);
    2191                 :            :         } else {
    2192   [ +  -  -  + ]:       5036 :             assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])); // should be
    2193                 :       5036 :             mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t *)pns->nodes[i];
    2194                 :       5036 :             int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
    2195         [ +  + ]:       5036 :             if (kind == PN_comp_op_not_in) {
    2196                 :        376 :                 EMIT_ARG(binary_op, MP_BINARY_OP_NOT_IN);
    2197                 :            :             } else {
    2198         [ -  + ]:       4660 :                 assert(kind == PN_comp_op_is); // should be
    2199         [ +  + ]:       4660 :                 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
    2200                 :       3216 :                     EMIT_ARG(binary_op, MP_BINARY_OP_IS);
    2201                 :            :                 } else {
    2202                 :       1444 :                     EMIT_ARG(binary_op, MP_BINARY_OP_IS_NOT);
    2203                 :            :                 }
    2204                 :            :             }
    2205                 :            :         }
    2206         [ +  + ]:      15703 :         if (i + 2 < num_nodes) {
    2207                 :        246 :             EMIT_ARG(jump_if_or_pop, false, l_fail);
    2208                 :            :         }
    2209                 :            :     }
    2210         [ +  + ]:      15457 :     if (multi) {
    2211                 :        238 :         uint l_end = comp_next_label(comp);
    2212                 :        238 :         EMIT_ARG(jump, l_end);
    2213                 :        238 :         EMIT_ARG(label_assign, l_fail);
    2214                 :        238 :         EMIT_ARG(adjust_stack_size, 1);
    2215                 :        238 :         EMIT(rot_two);
    2216                 :        238 :         EMIT(pop_top);
    2217                 :        238 :         EMIT_ARG(label_assign, l_end);
    2218                 :            :     }
    2219                 :      15457 : }
    2220                 :            : 
    2221                 :          4 : STATIC void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2222                 :          4 :     compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("*x must be assignment target"));
    2223                 :          4 : }
    2224                 :            : 
    2225                 :       1685 : STATIC void compile_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2226                 :       1685 :     MP_STATIC_ASSERT(MP_BINARY_OP_OR + PN_xor_expr - PN_expr == MP_BINARY_OP_XOR);
    2227                 :       1685 :     MP_STATIC_ASSERT(MP_BINARY_OP_OR + PN_and_expr - PN_expr == MP_BINARY_OP_AND);
    2228                 :       1685 :     mp_binary_op_t binary_op = MP_BINARY_OP_OR + MP_PARSE_NODE_STRUCT_KIND(pns) - PN_expr;
    2229                 :       1685 :     int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
    2230                 :       1685 :     compile_node(comp, pns->nodes[0]);
    2231         [ +  + ]:       3434 :     for (int i = 1; i < num_nodes; ++i) {
    2232                 :       1749 :         compile_node(comp, pns->nodes[i]);
    2233                 :       1749 :         EMIT_ARG(binary_op, binary_op);
    2234                 :            :     }
    2235                 :       1685 : }
    2236                 :            : 
    2237                 :      10825 : STATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2238                 :      10825 :     int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
    2239                 :      10825 :     compile_node(comp, pns->nodes[0]);
    2240         [ +  + ]:      22644 :     for (int i = 1; i + 1 < num_nodes; i += 2) {
    2241                 :      11819 :         compile_node(comp, pns->nodes[i + 1]);
    2242                 :      11819 :         mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]);
    2243                 :      11819 :         mp_binary_op_t op = MP_BINARY_OP_LSHIFT + (tok - MP_TOKEN_OP_DBL_LESS);
    2244                 :      11819 :         EMIT_ARG(binary_op, op);
    2245                 :            :     }
    2246                 :      10825 : }
    2247                 :            : 
    2248                 :       3147 : STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2249                 :       3147 :     compile_node(comp, pns->nodes[1]);
    2250                 :       3147 :     mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
    2251                 :       3147 :     mp_unary_op_t op;
    2252         [ +  + ]:       3147 :     if (tok == MP_TOKEN_OP_TILDE) {
    2253                 :            :         op = MP_UNARY_OP_INVERT;
    2254                 :            :     } else {
    2255         [ -  + ]:       2569 :         assert(tok == MP_TOKEN_OP_PLUS || tok == MP_TOKEN_OP_MINUS);
    2256                 :            :         op = MP_UNARY_OP_POSITIVE + (tok - MP_TOKEN_OP_PLUS);
    2257                 :            :     }
    2258                 :       3147 :     EMIT_ARG(unary_op, op);
    2259                 :       3147 : }
    2260                 :            : 
    2261                 :     237800 : STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2262                 :            :     // compile the subject of the expression
    2263                 :     237800 :     compile_node(comp, pns->nodes[0]);
    2264                 :            : 
    2265                 :            :     // compile_atom_expr_await may call us with a NULL node
    2266         [ +  + ]:     237802 :     if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
    2267                 :            :         return;
    2268                 :            :     }
    2269                 :            : 
    2270                 :            :     // get the array of trailers (known to be an array of PARSE_NODE_STRUCT)
    2271                 :     237474 :     size_t num_trail = 1;
    2272                 :     237474 :     mp_parse_node_struct_t **pns_trail = (mp_parse_node_struct_t **)&pns->nodes[1];
    2273         [ +  + ]:     237474 :     if (MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_atom_expr_trailers) {
    2274                 :     112568 :         num_trail = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_trail[0]);
    2275                 :     112568 :         pns_trail = (mp_parse_node_struct_t **)&pns_trail[0]->nodes[0];
    2276                 :            :     }
    2277                 :            : 
    2278                 :            :     // the current index into the array of trailers
    2279                 :     237474 :     size_t i = 0;
    2280                 :            : 
    2281                 :            :     // handle special super() call
    2282         [ +  + ]:     237474 :     if (comp->scope_cur->kind == SCOPE_FUNCTION
    2283         [ +  + ]:      49575 :         && MP_PARSE_NODE_IS_ID(pns->nodes[0])
    2284         [ +  + ]:      49125 :         && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super
    2285         [ +  + ]:        154 :         && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren
    2286         [ +  + ]:        146 :         && MP_PARSE_NODE_IS_NULL(pns_trail[0]->nodes[0])) {
    2287                 :            :         // at this point we have matched "super()" within a function
    2288                 :            : 
    2289                 :            :         // load the class for super to search for a parent
    2290                 :        138 :         compile_load_id(comp, MP_QSTR___class__);
    2291                 :            : 
    2292                 :            :         // look for first argument to function (assumes it's "self")
    2293                 :        138 :         bool found = false;
    2294                 :        138 :         id_info_t *id = &comp->scope_cur->id_info[0];
    2295         [ +  + ]:        142 :         for (size_t n = comp->scope_cur->id_info_len; n > 0; --n, ++id) {
    2296         [ +  + ]:        140 :             if (id->flags & ID_FLAG_IS_PARAM) {
    2297                 :            :                 // first argument found; load it
    2298                 :        136 :                 compile_load_id(comp, id->qst);
    2299                 :        136 :                 found = true;
    2300                 :        136 :                 break;
    2301                 :            :             }
    2302                 :            :         }
    2303                 :        138 :         if (!found) {
    2304                 :          2 :             compile_syntax_error(comp, (mp_parse_node_t)pns_trail[0],
    2305                 :          2 :                 MP_ERROR_TEXT("super() can't find self")); // really a TypeError
    2306                 :          2 :             return;
    2307                 :            :         }
    2308                 :            : 
    2309         [ +  + ]:        136 :         if (num_trail >= 3
    2310         [ +  - ]:        120 :             && MP_PARSE_NODE_STRUCT_KIND(pns_trail[1]) == PN_trailer_period
    2311         [ +  - ]:        240 :             && MP_PARSE_NODE_STRUCT_KIND(pns_trail[2]) == PN_trailer_paren) {
    2312                 :            :             // optimisation for method calls super().f(...), to eliminate heap allocation
    2313                 :        120 :             mp_parse_node_struct_t *pns_period = pns_trail[1];
    2314                 :        120 :             mp_parse_node_struct_t *pns_paren = pns_trail[2];
    2315                 :        120 :             EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), true);
    2316                 :        120 :             compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
    2317                 :        120 :             i = 3;
    2318                 :            :         } else {
    2319                 :            :             // a super() call
    2320                 :         16 :             EMIT_ARG(call_function, 2, 0, 0);
    2321                 :         16 :             i = 1;
    2322                 :            :         }
    2323                 :            : 
    2324                 :            :         #if MICROPY_COMP_CONST_LITERAL && MICROPY_PY_COLLECTIONS_ORDEREDDICT
    2325                 :            :         // handle special OrderedDict constructor
    2326         [ +  + ]:     237336 :     } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])
    2327         [ +  + ]:     231287 :                && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_OrderedDict
    2328         [ +  - ]:         56 :                && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren
    2329   [ +  +  +  -  :         56 :                && MP_PARSE_NODE_IS_STRUCT_KIND(pns_trail[0]->nodes[0], PN_atom_brace)) {
                   +  + ]
    2330                 :            :         // at this point we have matched "OrderedDict({...})"
    2331                 :            : 
    2332                 :          8 :         EMIT_ARG(call_function, 0, 0, 0);
    2333                 :          8 :         mp_parse_node_struct_t *pns_dict = (mp_parse_node_struct_t *)pns_trail[0]->nodes[0];
    2334                 :          8 :         compile_atom_brace_helper(comp, pns_dict, false);
    2335                 :          8 :         i = 1;
    2336                 :            :         #endif
    2337                 :            :     }
    2338                 :            : 
    2339                 :            :     // compile the remaining trailers
    2340         [ +  + ]:     628184 :     for (; i < num_trail; i++) {
    2341         [ +  + ]:     390719 :         if (i + 1 < num_trail
    2342         [ +  + ]:     189333 :             && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i]) == PN_trailer_period
    2343         [ +  + ]:      77676 :             && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i + 1]) == PN_trailer_paren) {
    2344                 :            :             // optimisation for method calls a.f(...), following PyPy
    2345                 :      36336 :             mp_parse_node_struct_t *pns_period = pns_trail[i];
    2346                 :      36336 :             mp_parse_node_struct_t *pns_paren = pns_trail[i + 1];
    2347                 :      36336 :             EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false);
    2348                 :      36336 :             compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
    2349                 :      36336 :             i += 1;
    2350                 :            :         } else {
    2351                 :            :             // node is one of: trailer_paren, trailer_bracket, trailer_period
    2352                 :     354383 :             compile_node(comp, (mp_parse_node_t)pns_trail[i]);
    2353                 :            :         }
    2354                 :            :     }
    2355                 :            : }
    2356                 :            : 
    2357                 :        830 : STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2358                 :        830 :     compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power
    2359                 :        830 :     EMIT_ARG(binary_op, MP_BINARY_OP_POWER);
    2360                 :        830 : }
    2361                 :            : 
    2362                 :     365900 : STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) {
    2363                 :            :     // function to call is on top of stack
    2364                 :            : 
    2365                 :            :     // get the list of arguments
    2366                 :     365900 :     mp_parse_node_t *args;
    2367                 :     365900 :     size_t n_args = mp_parse_node_extract_list(&pn_arglist, PN_arglist, &args);
    2368                 :            : 
    2369                 :            :     // compile the arguments
    2370                 :            :     // Rather than calling compile_node on the list, we go through the list of args
    2371                 :            :     // explicitly here so that we can count the number of arguments and give sensible
    2372                 :            :     // error messages.
    2373                 :     365900 :     int n_positional = n_positional_extra;
    2374                 :     365900 :     uint n_keyword = 0;
    2375                 :     365900 :     uint star_flags = 0;
    2376                 :     365900 :     mp_uint_t star_args = 0;
    2377         [ +  + ]:     549642 :     for (size_t i = 0; i < n_args; i++) {
    2378   [ -  +  +  + ]:     183781 :         if (MP_PARSE_NODE_IS_STRUCT(args[i])) {
    2379                 :      71034 :             mp_parse_node_struct_t *pns_arg = (mp_parse_node_struct_t *)args[i];
    2380         [ +  + ]:      71034 :             if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_star) {
    2381         [ +  + ]:        998 :                 if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) {
    2382                 :          8 :                     compile_syntax_error(comp, (mp_parse_node_t)pns_arg, MP_ERROR_TEXT("* arg after **"));
    2383                 :         46 :                     return;
    2384                 :            :                 }
    2385                 :            :                 #if MICROPY_DYNAMIC_COMPILER
    2386                 :            :                 if (i >= (size_t)mp_dynamic_compiler.small_int_bits - 1)
    2387                 :            :                 #else
    2388         [ +  + ]:        990 :                 if (i >= MP_SMALL_INT_BITS - 1)
    2389                 :            :                 #endif
    2390                 :            :                 {
    2391                 :            :                     // If there are not enough bits in a small int to fit the flag, then we consider
    2392                 :            :                     // it a syntax error. It should be unlikely to have this many args in practice.
    2393                 :         18 :                     compile_syntax_error(comp, (mp_parse_node_t)pns_arg, MP_ERROR_TEXT("too many args"));
    2394                 :         18 :                     return;
    2395                 :            :                 }
    2396                 :        972 :                 star_flags |= MP_EMIT_STAR_FLAG_SINGLE;
    2397                 :        972 :                 star_args |= (mp_uint_t)1 << i;
    2398                 :        972 :                 compile_node(comp, pns_arg->nodes[0]);
    2399                 :        972 :                 n_positional++;
    2400         [ +  + ]:      70036 :             } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_dbl_star) {
    2401                 :        368 :                 star_flags |= MP_EMIT_STAR_FLAG_DOUBLE;
    2402                 :            :                 // double-star args are stored as kw arg with key of None
    2403                 :        368 :                 EMIT(load_null);
    2404                 :        368 :                 compile_node(comp, pns_arg->nodes[0]);
    2405                 :        368 :                 n_keyword++;
    2406         [ +  + ]:      69668 :             } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) {
    2407                 :            :                 #if MICROPY_PY_ASSIGN_EXPR
    2408   [ +  -  +  +  :       2593 :                 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_argument_3)) {
                   +  + ]
    2409                 :         16 :                     compile_namedexpr_helper(comp, pns_arg->nodes[0], ((mp_parse_node_struct_t *)pns_arg->nodes[1])->nodes[0]);
    2410                 :         16 :                     n_positional++;
    2411                 :            :                 } else
    2412                 :            :                 #endif
    2413   [ +  -  +  +  :       2577 :                 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_comp_for)) {
                   +  + ]
    2414         [ +  + ]:       2500 :                     if (!MP_PARSE_NODE_IS_ID(pns_arg->nodes[0])) {
    2415                 :          4 :                         compile_syntax_error(comp, (mp_parse_node_t)pns_arg, MP_ERROR_TEXT("LHS of keyword arg must be an id"));
    2416                 :          4 :                         return;
    2417                 :            :                     }
    2418                 :       2496 :                     EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]));
    2419                 :       2496 :                     compile_node(comp, pns_arg->nodes[1]);
    2420                 :       2496 :                     n_keyword++;
    2421                 :            :                 } else {
    2422                 :         77 :                     compile_comprehension(comp, pns_arg, SCOPE_GEN_EXPR);
    2423                 :         77 :                     n_positional++;
    2424                 :            :                 }
    2425                 :            :             } else {
    2426                 :      67075 :                 goto normal_argument;
    2427                 :            :             }
    2428                 :            :         } else {
    2429                 :     112747 :         normal_argument:
    2430         [ +  + ]:     179822 :             if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) {
    2431                 :          4 :                 compile_syntax_error(comp, args[i], MP_ERROR_TEXT("positional arg after **"));
    2432                 :          4 :                 return;
    2433                 :            :             }
    2434         [ +  + ]:     179818 :             if (n_keyword > 0) {
    2435                 :          4 :                 compile_syntax_error(comp, args[i], MP_ERROR_TEXT("positional arg after keyword arg"));
    2436                 :          4 :                 return;
    2437                 :            :             }
    2438                 :     179814 :             compile_node(comp, args[i]);
    2439                 :     179813 :             n_positional++;
    2440                 :            :         }
    2441                 :            :     }
    2442                 :            : 
    2443         [ +  + ]:     365861 :     if (star_flags != 0) {
    2444                 :            :         // one extra object that contains the star_args map
    2445                 :       1144 :         EMIT_ARG(load_const_small_int, star_args);
    2446                 :            :     }
    2447                 :            : 
    2448                 :            :     // emit the function/method call
    2449         [ +  + ]:     365861 :     if (is_method_call) {
    2450                 :      36452 :         EMIT_ARG(call_method, n_positional, n_keyword, star_flags);
    2451                 :            :     } else {
    2452                 :     329409 :         EMIT_ARG(call_function, n_positional, n_keyword, star_flags);
    2453                 :            :     }
    2454                 :            : }
    2455                 :            : 
    2456                 :            : // pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
    2457                 :        744 : STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
    2458         [ -  + ]:        744 :     assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
    2459   [ +  -  +  -  :        744 :     assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
                   -  + ]
    2460                 :        744 :     mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t *)pns->nodes[1];
    2461                 :            : 
    2462         [ +  + ]:        744 :     if (comp->pass == MP_PASS_SCOPE) {
    2463                 :            :         // create a new scope for this comprehension
    2464                 :        185 :         scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
    2465                 :            :         // store the comprehension scope so the compiling function (this one) can use it at each pass
    2466                 :        185 :         pns_comp_for->nodes[3] = (mp_parse_node_t)s;
    2467                 :            :     }
    2468                 :            : 
    2469                 :            :     // get the scope for this comprehension
    2470                 :        744 :     scope_t *this_scope = (scope_t *)pns_comp_for->nodes[3];
    2471                 :            : 
    2472                 :            :     // compile the comprehension
    2473                 :        744 :     close_over_variables_etc(comp, this_scope, 0, 0);
    2474                 :            : 
    2475                 :        744 :     compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
    2476         [ +  + ]:        744 :     if (kind == SCOPE_GEN_EXPR) {
    2477                 :        232 :         EMIT_ARG(get_iter, false);
    2478                 :            :     }
    2479                 :        744 :     EMIT_ARG(call_function, 1, 0, 0);
    2480                 :        744 : }
    2481                 :            : 
    2482                 :       4174 : STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2483         [ +  + ]:       4174 :     if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
    2484                 :            :         // an empty tuple
    2485                 :        860 :         EMIT_ARG(build, 0, MP_EMIT_BUILD_TUPLE);
    2486                 :            :     } else {
    2487   [ +  -  -  + ]:       3314 :         assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
    2488                 :       3314 :         pns = (mp_parse_node_struct_t *)pns->nodes[0];
    2489   [ +  +  +  -  :       3314 :         if (MP_PARSE_NODE_TESTLIST_COMP_HAS_COMP_FOR(pns)) {
             +  +  +  + ]
    2490                 :            :             // generator expression
    2491                 :        155 :             compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
    2492                 :            :         } else {
    2493                 :            :             // tuple with N items
    2494                 :       3159 :             compile_generic_tuple(comp, pns);
    2495                 :            :         }
    2496                 :            :     }
    2497                 :       4174 : }
    2498                 :            : 
    2499                 :       5911 : STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2500         [ +  + ]:       5911 :     if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
    2501                 :            :         // empty list
    2502                 :       1168 :         EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST);
    2503   [ +  +  +  + ]:       4743 :     } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
    2504                 :       3482 :         mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t *)pns->nodes[0];
    2505   [ +  +  +  -  :       3482 :         if (MP_PARSE_NODE_TESTLIST_COMP_HAS_COMP_FOR(pns2)) {
             +  +  +  + ]
    2506                 :            :             // list comprehension
    2507                 :        432 :             compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
    2508                 :            :         } else {
    2509                 :            :             // list with N items
    2510                 :       3050 :             compile_generic_all_nodes(comp, pns2);
    2511                 :       3050 :             EMIT_ARG(build, MP_PARSE_NODE_STRUCT_NUM_NODES(pns2), MP_EMIT_BUILD_LIST);
    2512                 :            :         }
    2513                 :            :     } else {
    2514                 :            :         // list with 1 item
    2515                 :       1261 :         compile_node(comp, pns->nodes[0]);
    2516                 :       1261 :         EMIT_ARG(build, 1, MP_EMIT_BUILD_LIST);
    2517                 :            :     }
    2518                 :       5911 : }
    2519                 :            : 
    2520                 :       3337 : STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map) {
    2521                 :       3337 :     mp_parse_node_t pn = pns->nodes[0];
    2522         [ +  + ]:       3337 :     if (MP_PARSE_NODE_IS_NULL(pn)) {
    2523                 :            :         // empty dict
    2524         [ +  - ]:        777 :         if (create_map) {
    2525                 :        777 :             EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
    2526                 :            :         }
    2527         [ +  + ]:       2560 :     } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
    2528                 :       2298 :         pns = (mp_parse_node_struct_t *)pn;
    2529         [ +  + ]:       2298 :         if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
    2530                 :            :             // dict with one element
    2531         [ +  - ]:        953 :             if (create_map) {
    2532                 :        953 :                 EMIT_ARG(build, 1, MP_EMIT_BUILD_MAP);
    2533                 :            :             }
    2534                 :        953 :             compile_node(comp, pn);
    2535                 :        953 :             EMIT(store_map);
    2536         [ +  + ]:       1345 :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
    2537   [ +  -  -  + ]:       1337 :             assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
    2538                 :       1337 :             mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pns->nodes[1];
    2539         [ +  + ]:       1337 :             if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
    2540                 :            :                 // dict/set with multiple elements
    2541                 :            : 
    2542                 :            :                 // get tail elements (2nd, 3rd, ...)
    2543                 :       1257 :                 mp_parse_node_t *nodes;
    2544                 :       1257 :                 size_t n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
    2545                 :            : 
    2546                 :            :                 // first element sets whether it's a dict or set
    2547                 :       1257 :                 bool is_dict;
    2548   [ +  -  +  +  :       1257 :                 if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
                   +  - ]
    2549                 :            :                     // a dictionary
    2550         [ +  + ]:        933 :                     if (create_map) {
    2551                 :        925 :                         EMIT_ARG(build, 1 + n, MP_EMIT_BUILD_MAP);
    2552                 :            :                     }
    2553                 :        933 :                     compile_node(comp, pns->nodes[0]);
    2554                 :        933 :                     EMIT(store_map);
    2555                 :        933 :                     is_dict = true;
    2556                 :            :                 } else {
    2557                 :            :                     // a set
    2558                 :        324 :                     compile_node(comp, pns->nodes[0]); // 1st value of set
    2559                 :        324 :                     is_dict = false;
    2560                 :            :                 }
    2561                 :            : 
    2562                 :            :                 // process rest of elements
    2563         [ +  + ]:       5150 :                 for (size_t i = 0; i < n; i++) {
    2564                 :       3901 :                     mp_parse_node_t pn_i = nodes[i];
    2565   [ +  -  +  +  :       3901 :                     bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn_i, PN_dictorsetmaker_item);
                   +  + ]
    2566                 :       3901 :                     compile_node(comp, pn_i);
    2567         [ +  + ]:       3901 :                     if (is_dict) {
    2568         [ +  + ]:       3305 :                         if (!is_key_value) {
    2569                 :            :                             #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
    2570                 :            :                             compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("invalid syntax"));
    2571                 :            :                             #else
    2572                 :          4 :                             compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("expecting key:value for dict"));
    2573                 :            :                             #endif
    2574                 :         12 :                             return;
    2575                 :            :                         }
    2576                 :       3301 :                         EMIT(store_map);
    2577                 :            :                     } else {
    2578         [ +  + ]:        596 :                         if (is_key_value) {
    2579                 :            :                             #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE
    2580                 :            :                             compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("invalid syntax"));
    2581                 :            :                             #else
    2582                 :          4 :                             compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("expecting just a value for set"));
    2583                 :            :                             #endif
    2584                 :          4 :                             return;
    2585                 :            :                         }
    2586                 :            :                     }
    2587                 :            :                 }
    2588                 :            : 
    2589                 :            :                 #if MICROPY_PY_BUILTINS_SET
    2590                 :            :                 // if it's a set, build it
    2591         [ +  + ]:       1249 :                 if (!is_dict) {
    2592                 :        320 :                     EMIT_ARG(build, 1 + n, MP_EMIT_BUILD_SET);
    2593                 :            :                 }
    2594                 :            :                 #endif
    2595                 :            :             } else {
    2596         [ -  + ]:         80 :                 assert(MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for); // should be
    2597                 :            :                 // dict/set comprehension
    2598   [ +  -  +  +  :         80 :                 if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
                   +  - ]
    2599                 :            :                     // a dictionary comprehension
    2600                 :         72 :                     compile_comprehension(comp, pns, SCOPE_DICT_COMP);
    2601                 :            :                 } else {
    2602                 :            :                     // a set comprehension
    2603                 :          8 :                     compile_comprehension(comp, pns, SCOPE_SET_COMP);
    2604                 :            :                 }
    2605                 :            :             }
    2606                 :            :         } else {
    2607                 :            :             // set with one element
    2608                 :          8 :             goto set_with_one_element;
    2609                 :            :         }
    2610                 :            :     } else {
    2611                 :            :         // set with one element
    2612                 :        262 :     set_with_one_element:
    2613                 :            :         #if MICROPY_PY_BUILTINS_SET
    2614                 :        270 :         compile_node(comp, pn);
    2615                 :        270 :         EMIT_ARG(build, 1, MP_EMIT_BUILD_SET);
    2616                 :            :         #else
    2617                 :            :         assert(0);
    2618                 :            :         #endif
    2619                 :            :     }
    2620                 :            : }
    2621                 :            : 
    2622                 :       3329 : STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2623                 :       3329 :     compile_atom_brace_helper(comp, pns, true);
    2624                 :       3329 : }
    2625                 :            : 
    2626                 :     325759 : STATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2627                 :     325759 :     compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
    2628                 :     325752 : }
    2629                 :            : 
    2630                 :       9645 : STATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2631                 :            :     // object who's index we want is on top of stack
    2632                 :       9645 :     compile_node(comp, pns->nodes[0]); // the index
    2633                 :       9645 :     EMIT_ARG(subscr, MP_EMIT_SUBSCR_LOAD);
    2634                 :       9645 : }
    2635                 :            : 
    2636                 :      20514 : STATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2637                 :            :     // object who's attribute we want is on top of stack
    2638                 :      20514 :     EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]), MP_EMIT_ATTR_LOAD); // attribute to get
    2639                 :      20514 : }
    2640                 :            : 
    2641                 :            : #if MICROPY_PY_BUILTINS_SLICE
    2642                 :       2298 : STATIC void compile_subscript(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2643         [ +  + ]:       2298 :     if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_2) {
    2644                 :       1432 :         compile_node(comp, pns->nodes[0]); // start of slice
    2645   [ +  -  -  + ]:       1432 :         assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
    2646                 :       1432 :         pns = (mp_parse_node_struct_t *)pns->nodes[1];
    2647                 :            :     } else {
    2648                 :            :         // pns is a PN_subscript_3, load None for start of slice
    2649                 :        866 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    2650                 :            :     }
    2651                 :            : 
    2652         [ -  + ]:       2298 :     assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
    2653                 :       2298 :     mp_parse_node_t pn = pns->nodes[0];
    2654         [ +  + ]:       2298 :     if (MP_PARSE_NODE_IS_NULL(pn)) {
    2655                 :            :         // [?:]
    2656                 :        465 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    2657                 :        465 :         EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE);
    2658         [ +  + ]:       1833 :     } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
    2659                 :        599 :         pns = (mp_parse_node_struct_t *)pn;
    2660         [ +  + ]:        599 :         if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
    2661                 :        168 :             EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    2662                 :        168 :             pn = pns->nodes[0];
    2663         [ +  + ]:        168 :             if (MP_PARSE_NODE_IS_NULL(pn)) {
    2664                 :            :                 // [?::]
    2665                 :         24 :                 EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE);
    2666                 :            :             } else {
    2667                 :            :                 // [?::x]
    2668                 :        144 :                 compile_node(comp, pn);
    2669                 :        144 :                 EMIT_ARG(build, 3, MP_EMIT_BUILD_SLICE);
    2670                 :            :             }
    2671         [ +  + ]:        431 :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
    2672                 :        342 :             compile_node(comp, pns->nodes[0]);
    2673   [ +  -  -  + ]:        342 :             assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
    2674                 :        342 :             pns = (mp_parse_node_struct_t *)pns->nodes[1];
    2675         [ -  + ]:        342 :             assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
    2676         [ +  + ]:        342 :             if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
    2677                 :            :                 // [?:x:]
    2678                 :         24 :                 EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE);
    2679                 :            :             } else {
    2680                 :            :                 // [?:x:x]
    2681                 :        318 :                 compile_node(comp, pns->nodes[0]);
    2682                 :        318 :                 EMIT_ARG(build, 3, MP_EMIT_BUILD_SLICE);
    2683                 :            :             }
    2684                 :            :         } else {
    2685                 :            :             // [?:x]
    2686                 :         89 :             compile_node(comp, pn);
    2687                 :         89 :             EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE);
    2688                 :            :         }
    2689                 :            :     } else {
    2690                 :            :         // [?:x]
    2691                 :       1234 :         compile_node(comp, pn);
    2692                 :       1234 :         EMIT_ARG(build, 2, MP_EMIT_BUILD_SLICE);
    2693                 :            :     }
    2694                 :       2298 : }
    2695                 :            : #endif // MICROPY_PY_BUILTINS_SLICE
    2696                 :            : 
    2697                 :       5263 : STATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2698                 :            :     // if this is called then we are compiling a dict key:value pair
    2699                 :       5263 :     compile_node(comp, pns->nodes[1]); // value
    2700                 :       5263 :     compile_node(comp, pns->nodes[0]); // key
    2701                 :       5263 : }
    2702                 :            : 
    2703                 :       3676 : STATIC void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2704                 :       3676 :     qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
    2705                 :            :     // store class object into class name
    2706                 :       3676 :     compile_store_id(comp, cname);
    2707                 :       3676 : }
    2708                 :            : 
    2709                 :       1284 : STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2710         [ +  + ]:       1284 :     if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {
    2711                 :          4 :         compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'yield' outside function"));
    2712                 :          4 :         return;
    2713                 :            :     }
    2714         [ +  + ]:       1280 :     if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
    2715                 :        140 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    2716                 :        140 :         EMIT_ARG(yield, MP_EMIT_YIELD_VALUE);
    2717                 :        136 :         reserve_labels_for_native(comp, 1);
    2718   [ +  +  +  + ]:       1140 :     } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
    2719                 :        260 :         pns = (mp_parse_node_struct_t *)pns->nodes[0];
    2720                 :        260 :         compile_node(comp, pns->nodes[0]);
    2721                 :        260 :         compile_yield_from(comp);
    2722                 :            :     } else {
    2723                 :        880 :         compile_node(comp, pns->nodes[0]);
    2724                 :        880 :         EMIT_ARG(yield, MP_EMIT_YIELD_VALUE);
    2725                 :        880 :         reserve_labels_for_native(comp, 1);
    2726                 :            :     }
    2727                 :            : }
    2728                 :            : 
    2729                 :            : #if MICROPY_PY_ASYNC_AWAIT
    2730                 :       1400 : STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2731         [ +  + ]:       1400 :     if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {
    2732                 :          4 :         compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'await' outside function"));
    2733                 :          4 :         return;
    2734                 :            :     }
    2735                 :       1396 :     compile_atom_expr_normal(comp, pns);
    2736                 :       1396 :     compile_yield_from(comp);
    2737                 :            : }
    2738                 :            : #endif
    2739                 :            : 
    2740                 :      28645 : STATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) {
    2741                 :      28645 :     return mp_parse_node_extract_const_object(pns);
    2742                 :            : }
    2743                 :            : 
    2744                 :      28645 : STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
    2745                 :      28645 :     EMIT_ARG(load_const_obj, get_const_object(pns));
    2746                 :      28645 : }
    2747                 :            : 
    2748                 :            : typedef void (*compile_function_t)(compiler_t *, mp_parse_node_struct_t *);
    2749                 :            : STATIC const compile_function_t compile_function[] = {
    2750                 :            : // only define rules with a compile function
    2751                 :            : #define c(f) compile_##f
    2752                 :            : #define DEF_RULE(rule, comp, kind, ...) comp,
    2753                 :            : #define DEF_RULE_NC(rule, kind, ...)
    2754                 :            :     #include "py/grammar.h"
    2755                 :            : #undef c
    2756                 :            : #undef DEF_RULE
    2757                 :            : #undef DEF_RULE_NC
    2758                 :            :     compile_const_object,
    2759                 :            : };
    2760                 :            : 
    2761                 :    1642514 : STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
    2762         [ +  + ]:    1642514 :     if (MP_PARSE_NODE_IS_NULL(pn)) {
    2763                 :            :         // pass
    2764         [ +  + ]:    1583910 :     } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
    2765                 :      86509 :         mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
    2766                 :      86509 :         EMIT_ARG(load_const_small_int, arg);
    2767         [ +  + ]:    1497401 :     } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
    2768                 :     438300 :         uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
    2769      [ +  +  + ]:     438300 :         switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
    2770                 :     368834 :             case MP_PARSE_NODE_ID:
    2771                 :     368834 :                 compile_load_id(comp, arg);
    2772                 :     368834 :                 break;
    2773                 :      49194 :             case MP_PARSE_NODE_STRING:
    2774                 :      49194 :                 EMIT_ARG(load_const_str, arg);
    2775                 :      49194 :                 break;
    2776                 :      20272 :             case MP_PARSE_NODE_TOKEN:
    2777                 :            :             default:
    2778         [ +  + ]:      20272 :                 if (arg == MP_TOKEN_NEWLINE) {
    2779                 :            :                     // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
    2780                 :            :                     // or when single_input lets through a NEWLINE (user enters a blank line)
    2781                 :            :                     // do nothing
    2782                 :            :                 } else {
    2783                 :      14166 :                     EMIT_ARG(load_const_tok, arg);
    2784                 :            :                 }
    2785                 :            :                 break;
    2786                 :            :         }
    2787                 :            :     } else {
    2788                 :    1059101 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
    2789                 :    1059101 :         EMIT_ARG(set_source_line, pns->source_line);
    2790         [ -  + ]:    1059100 :         assert(MP_PARSE_NODE_STRUCT_KIND(pns) <= PN_const_object);
    2791                 :    1059100 :         compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
    2792                 :    1059100 :         f(comp, pns);
    2793                 :            :     }
    2794                 :    1642470 : }
    2795                 :            : 
    2796                 :            : #if MICROPY_EMIT_NATIVE
    2797                 :        650 : STATIC int compile_viper_type_annotation(compiler_t *comp, mp_parse_node_t pn_annotation) {
    2798                 :        650 :     int native_type = MP_NATIVE_TYPE_OBJ;
    2799         [ +  + ]:        650 :     if (MP_PARSE_NODE_IS_NULL(pn_annotation)) {
    2800                 :            :         // No annotation, type defaults to object
    2801         [ +  + ]:        406 :     } else if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
    2802                 :        398 :         qstr type_name = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
    2803                 :        398 :         native_type = mp_native_type_from_qstr(type_name);
    2804         [ +  + ]:        398 :         if (native_type < 0) {
    2805                 :          4 :             comp->compile_error = mp_obj_new_exception_msg_varg(&mp_type_ViperTypeError, MP_ERROR_TEXT("unknown type '%q'"), type_name);
    2806                 :          4 :             native_type = 0;
    2807                 :            :         }
    2808                 :            :     } else {
    2809                 :          8 :         compile_syntax_error(comp, pn_annotation, MP_ERROR_TEXT("annotation must be an identifier"));
    2810                 :            :     }
    2811                 :        650 :     return native_type;
    2812                 :            : }
    2813                 :            : #endif
    2814                 :            : 
    2815                 :       5536 : STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star) {
    2816                 :       5536 :     (void)pn_dbl_star;
    2817                 :            : 
    2818                 :            :     // check that **kw is last
    2819         [ +  + ]:       5536 :     if ((comp->scope_cur->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
    2820                 :          8 :         compile_syntax_error(comp, pn, MP_ERROR_TEXT("invalid syntax"));
    2821                 :          8 :         return;
    2822                 :            :     }
    2823                 :            : 
    2824                 :       5528 :     qstr param_name = MP_QSTRnull;
    2825                 :       5528 :     uint param_flag = ID_FLAG_IS_PARAM;
    2826                 :       5528 :     mp_parse_node_struct_t *pns = NULL;
    2827         [ +  + ]:       5528 :     if (MP_PARSE_NODE_IS_ID(pn)) {
    2828                 :       4660 :         param_name = MP_PARSE_NODE_LEAF_ARG(pn);
    2829         [ +  + ]:       4660 :         if (comp->have_star) {
    2830                 :            :             // comes after a star, so counts as a keyword-only parameter
    2831                 :         28 :             comp->scope_cur->num_kwonly_args += 1;
    2832                 :            :         } else {
    2833                 :            :             // comes before a star, so counts as a positional parameter
    2834                 :       4632 :             comp->scope_cur->num_pos_args += 1;
    2835                 :            :         }
    2836                 :            :     } else {
    2837   [ +  -  -  + ]:        868 :         assert(MP_PARSE_NODE_IS_STRUCT(pn));
    2838                 :        868 :         pns = (mp_parse_node_struct_t *)pn;
    2839         [ +  + ]:        868 :         if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
    2840                 :            :             // named parameter with possible annotation
    2841                 :        697 :             param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
    2842         [ +  + ]:        697 :             if (comp->have_star) {
    2843                 :            :                 // comes after a star, so counts as a keyword-only parameter
    2844                 :         29 :                 comp->scope_cur->num_kwonly_args += 1;
    2845                 :            :             } else {
    2846                 :            :                 // comes before a star, so counts as a positional parameter
    2847                 :        668 :                 comp->scope_cur->num_pos_args += 1;
    2848                 :            :             }
    2849         [ +  + ]:        171 :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
    2850         [ +  + ]:        129 :             if (comp->have_star) {
    2851                 :            :                 // more than one star
    2852                 :          8 :                 compile_syntax_error(comp, pn, MP_ERROR_TEXT("invalid syntax"));
    2853                 :          8 :                 return;
    2854                 :            :             }
    2855                 :        121 :             comp->have_star = true;
    2856                 :        121 :             param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM;
    2857         [ +  + ]:        121 :             if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
    2858                 :            :                 // bare star
    2859                 :            :                 // TODO see http://www.python.org/dev/peps/pep-3102/
    2860                 :            :                 // assert(comp->scope_cur->num_dict_params == 0);
    2861                 :            :                 pns = NULL;
    2862         [ +  + ]:         97 :             } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
    2863                 :            :                 // named star
    2864                 :         20 :                 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
    2865                 :         20 :                 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
    2866                 :         20 :                 pns = NULL;
    2867                 :            :             } else {
    2868   [ +  -  -  + ]:         77 :                 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)); // should be
    2869                 :            :                 // named star with possible annotation
    2870                 :         77 :                 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
    2871                 :         77 :                 pns = (mp_parse_node_struct_t *)pns->nodes[0];
    2872                 :         77 :                 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
    2873                 :            :             }
    2874                 :            :         } else {
    2875                 :            :             // double star with possible annotation
    2876         [ -  + ]:         42 :             assert(MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star); // should be
    2877                 :         42 :             param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
    2878                 :         42 :             param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM;
    2879                 :         42 :             comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
    2880                 :            :         }
    2881                 :            :     }
    2882                 :            : 
    2883         [ +  + ]:       5520 :     if (param_name != MP_QSTRnull) {
    2884                 :       5496 :         id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, ID_INFO_KIND_UNDECIDED);
    2885         [ +  + ]:       5496 :         if (id_info->kind != ID_INFO_KIND_UNDECIDED) {
    2886                 :          4 :             compile_syntax_error(comp, pn, MP_ERROR_TEXT("argument name reused"));
    2887                 :          4 :             return;
    2888                 :            :         }
    2889                 :       5492 :         id_info->kind = ID_INFO_KIND_LOCAL;
    2890                 :       5492 :         id_info->flags = param_flag;
    2891                 :            : 
    2892                 :            :         #if MICROPY_EMIT_NATIVE
    2893   [ +  +  +  + ]:       5492 :         if (comp->scope_cur->emit_options == MP_EMIT_OPT_VIPER && pn_name == PN_typedargslist_name && pns != NULL) {
    2894                 :        338 :             id_info->flags |= compile_viper_type_annotation(comp, pns->nodes[1]) << ID_FLAG_VIPER_TYPE_POS;
    2895                 :            :         }
    2896                 :            :         #else
    2897                 :            :         (void)pns;
    2898                 :            :         #endif
    2899                 :            :     }
    2900                 :            : }
    2901                 :            : 
    2902                 :       5387 : STATIC void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
    2903                 :       5387 :     compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star);
    2904                 :       5387 : }
    2905                 :            : 
    2906                 :        149 : STATIC void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
    2907                 :        149 :     compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star);
    2908                 :        149 : }
    2909                 :            : 
    2910                 :        748 : STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pns_comp_for, mp_parse_node_t pn_inner_expr, int for_depth) {
    2911                 :        748 :     uint l_top = comp_next_label(comp);
    2912                 :        748 :     uint l_end = comp_next_label(comp);
    2913                 :        748 :     EMIT_ARG(label_assign, l_top);
    2914                 :        748 :     EMIT_ARG(for_iter, l_end);
    2915                 :        748 :     c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
    2916                 :        748 :     mp_parse_node_t pn_iter = pns_comp_for->nodes[2];
    2917                 :            : 
    2918                 :        796 : tail_recursion:
    2919         [ +  + ]:        796 :     if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
    2920                 :            :         // no more nested if/for; compile inner expression
    2921                 :        740 :         compile_node(comp, pn_inner_expr);
    2922         [ +  + ]:        740 :         if (comp->scope_cur->kind == SCOPE_GEN_EXPR) {
    2923                 :        228 :             EMIT_ARG(yield, MP_EMIT_YIELD_VALUE);
    2924                 :        228 :             reserve_labels_for_native(comp, 1);
    2925                 :        228 :             EMIT(pop_top);
    2926                 :            :         } else {
    2927                 :        512 :             EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5);
    2928                 :            :         }
    2929         [ +  + ]:         56 :     } else if (MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pn_iter) == PN_comp_if) {
    2930                 :            :         // if condition
    2931                 :         48 :         mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t *)pn_iter;
    2932                 :         48 :         c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
    2933                 :         48 :         pn_iter = pns_comp_if->nodes[1];
    2934                 :         48 :         goto tail_recursion;
    2935                 :            :     } else {
    2936         [ -  + ]:          8 :         assert(MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pn_iter) == PN_comp_for); // should be
    2937                 :            :         // for loop
    2938                 :          8 :         mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t *)pn_iter;
    2939                 :          8 :         compile_node(comp, pns_comp_for2->nodes[1]);
    2940                 :          8 :         EMIT_ARG(get_iter, true);
    2941                 :          8 :         compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1);
    2942                 :            :     }
    2943                 :            : 
    2944                 :        748 :     EMIT_ARG(jump, l_top);
    2945                 :        748 :     EMIT_ARG(label_assign, l_end);
    2946                 :        748 :     EMIT(for_iter_end);
    2947                 :        748 : }
    2948                 :            : 
    2949                 :            : STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
    2950                 :            :     #if MICROPY_ENABLE_DOC_STRING
    2951                 :            :     // see http://www.python.org/dev/peps/pep-0257/
    2952                 :            : 
    2953                 :            :     // look for the first statement
    2954                 :            :     if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
    2955                 :            :         // a statement; fall through
    2956                 :            :     } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
    2957                 :            :         // file input; find the first non-newline node
    2958                 :            :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
    2959                 :            :         int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
    2960                 :            :         for (int i = 0; i < num_nodes; i++) {
    2961                 :            :             pn = pns->nodes[i];
    2962                 :            :             if (!(MP_PARSE_NODE_IS_LEAF(pn) && MP_PARSE_NODE_LEAF_KIND(pn) == MP_PARSE_NODE_TOKEN && MP_PARSE_NODE_LEAF_ARG(pn) == MP_TOKEN_NEWLINE)) {
    2963                 :            :                 // not a newline, so this is the first statement; finish search
    2964                 :            :                 break;
    2965                 :            :             }
    2966                 :            :         }
    2967                 :            :         // if we didn't find a non-newline then it's okay to fall through; pn will be a newline and so doc-string test below will fail gracefully
    2968                 :            :     } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
    2969                 :            :         // a list of statements; get the first one
    2970                 :            :         pn = ((mp_parse_node_struct_t *)pn)->nodes[0];
    2971                 :            :     } else {
    2972                 :            :         return;
    2973                 :            :     }
    2974                 :            : 
    2975                 :            :     // check the first statement for a doc string
    2976                 :            :     if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
    2977                 :            :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
    2978                 :            :         if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])
    2979                 :            :              && MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)
    2980                 :            :             || (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)
    2981                 :            :                 && mp_obj_is_str(get_const_object((mp_parse_node_struct_t *)pns->nodes[0])))) {
    2982                 :            :             // compile the doc string
    2983                 :            :             compile_node(comp, pns->nodes[0]);
    2984                 :            :             // store the doc string
    2985                 :            :             compile_store_id(comp, MP_QSTR___doc__);
    2986                 :            :         }
    2987                 :            :     }
    2988                 :            :     #else
    2989                 :            :     (void)comp;
    2990                 :            :     (void)pn;
    2991                 :            :     #endif
    2992                 :            : }
    2993                 :            : 
    2994                 :      35487 : STATIC bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
    2995                 :      35487 :     comp->pass = pass;
    2996                 :      35487 :     comp->scope_cur = scope;
    2997                 :      35487 :     comp->next_label = 0;
    2998                 :      35487 :     mp_emit_common_start_pass(&comp->emit_common, pass);
    2999                 :      35487 :     EMIT_ARG(start_pass, pass, scope);
    3000                 :      35487 :     reserve_labels_for_native(comp, 6); // used by native's start_pass
    3001                 :            : 
    3002         [ +  + ]:      35488 :     if (comp->pass == MP_PASS_SCOPE) {
    3003                 :            :         // reset maximum stack sizes in scope
    3004                 :            :         // they will be computed in this first pass
    3005                 :       9102 :         scope->stack_size = 0;
    3006                 :       9102 :         scope->exc_stack_size = 0;
    3007                 :            :     }
    3008                 :            : 
    3009                 :            :     // compile
    3010   [ +  -  +  +  :      36758 :     if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
                   +  + ]
    3011         [ -  + ]:       1270 :         assert(scope->kind == SCOPE_MODULE);
    3012                 :       1270 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
    3013                 :       1270 :         compile_node(comp, pns->nodes[0]); // compile the expression
    3014                 :       1270 :         EMIT(return_value);
    3015         [ +  + ]:      34218 :     } else if (scope->kind == SCOPE_MODULE) {
    3016                 :      12381 :         if (!comp->is_repl) {
    3017                 :            :             check_for_doc_string(comp, scope->pn);
    3018                 :            :         }
    3019                 :      12381 :         compile_node(comp, scope->pn);
    3020                 :      12376 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    3021                 :      12376 :         EMIT(return_value);
    3022         [ +  + ]:      21837 :     } else if (scope->kind == SCOPE_FUNCTION) {
    3023   [ +  -  -  + ]:      16851 :         assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
    3024                 :      16851 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
    3025         [ -  + ]:      16851 :         assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
    3026                 :            : 
    3027                 :            :         // work out number of parameters, keywords and default parameters, and add them to the id_info array
    3028                 :            :         // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
    3029         [ +  + ]:      16851 :         if (comp->pass == MP_PASS_SCOPE) {
    3030                 :       4288 :             comp->have_star = false;
    3031                 :       4288 :             apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
    3032                 :            : 
    3033                 :            :             #if MICROPY_EMIT_NATIVE
    3034         [ +  + ]:       4288 :             if (scope->emit_options == MP_EMIT_OPT_VIPER) {
    3035                 :            :                 // Compile return type; pns->nodes[2] is return/whole function annotation
    3036                 :        312 :                 scope->scope_flags |= compile_viper_type_annotation(comp, pns->nodes[2]) << MP_SCOPE_FLAG_VIPERRET_POS;
    3037                 :            :             }
    3038                 :            :             #endif // MICROPY_EMIT_NATIVE
    3039                 :            :         }
    3040                 :            : 
    3041                 :      16851 :         compile_node(comp, pns->nodes[3]); // 3 is function body
    3042                 :      16835 :         EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    3043                 :      16835 :         EMIT(return_value);
    3044         [ +  + ]:       4986 :     } else if (scope->kind == SCOPE_LAMBDA) {
    3045   [ +  -  -  + ]:        572 :         assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
    3046                 :        572 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
    3047         [ -  + ]:        572 :         assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
    3048                 :            : 
    3049                 :            :         // Set the source line number for the start of the lambda
    3050                 :        572 :         EMIT_ARG(set_source_line, pns->source_line);
    3051                 :            : 
    3052                 :            :         // work out number of parameters, keywords and default parameters, and add them to the id_info array
    3053                 :            :         // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
    3054         [ +  + ]:        572 :         if (comp->pass == MP_PASS_SCOPE) {
    3055                 :        149 :             comp->have_star = false;
    3056                 :        149 :             apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
    3057                 :            :         }
    3058                 :            : 
    3059                 :        572 :         compile_node(comp, pns->nodes[1]); // 1 is lambda body
    3060                 :            : 
    3061                 :            :         // if the lambda is a generator, then we return None, not the result of the expression of the lambda
    3062         [ +  + ]:        572 :         if (scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
    3063                 :          8 :             EMIT(pop_top);
    3064                 :          8 :             EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    3065                 :            :         }
    3066                 :        572 :         EMIT(return_value);
    3067         [ +  + ]:       4414 :     } else if (SCOPE_IS_COMP_LIKE(scope->kind)) {
    3068                 :            :         // a bit of a hack at the moment
    3069                 :            : 
    3070   [ +  -  -  + ]:        740 :         assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
    3071                 :        740 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
    3072         [ -  + ]:        740 :         assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
    3073   [ +  -  +  -  :        740 :         assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
                   -  + ]
    3074                 :        740 :         mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t *)pns->nodes[1];
    3075                 :            : 
    3076                 :            :         // We need a unique name for the comprehension argument (the iterator).
    3077                 :            :         // CPython uses .0, but we should be able to use anything that won't
    3078                 :            :         // clash with a user defined variable.  Best to use an existing qstr,
    3079                 :            :         // so we use the blank qstr.
    3080                 :        740 :         qstr qstr_arg = MP_QSTR_;
    3081         [ +  + ]:        740 :         if (comp->pass == MP_PASS_SCOPE) {
    3082                 :        185 :             scope_find_or_add_id(comp->scope_cur, qstr_arg, ID_INFO_KIND_LOCAL);
    3083                 :        185 :             scope->num_pos_args = 1;
    3084                 :            :         }
    3085                 :            : 
    3086                 :            :         // Set the source line number for the start of the comprehension
    3087                 :        740 :         EMIT_ARG(set_source_line, pns->source_line);
    3088                 :            : 
    3089         [ +  + ]:        740 :         if (scope->kind == SCOPE_LIST_COMP) {
    3090                 :        432 :             EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST);
    3091         [ +  + ]:        308 :         } else if (scope->kind == SCOPE_DICT_COMP) {
    3092                 :         72 :             EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
    3093                 :            :         #if MICROPY_PY_BUILTINS_SET
    3094         [ +  + ]:        236 :         } else if (scope->kind == SCOPE_SET_COMP) {
    3095                 :          8 :             EMIT_ARG(build, 0, MP_EMIT_BUILD_SET);
    3096                 :            :         #endif
    3097                 :            :         }
    3098                 :            : 
    3099                 :            :         // There are 4 slots on the stack for the iterator, and the first one is
    3100                 :            :         // NULL to indicate that the second one points to the iterator object.
    3101         [ +  + ]:        740 :         if (scope->kind == SCOPE_GEN_EXPR) {
    3102                 :        228 :             MP_STATIC_ASSERT(MP_OBJ_ITER_BUF_NSLOTS == 4);
    3103                 :        228 :             EMIT(load_null);
    3104                 :        228 :             compile_load_id(comp, qstr_arg);
    3105                 :        228 :             EMIT(load_null);
    3106                 :        228 :             EMIT(load_null);
    3107                 :            :         } else {
    3108                 :        512 :             compile_load_id(comp, qstr_arg);
    3109                 :        512 :             EMIT_ARG(get_iter, true);
    3110                 :            :         }
    3111                 :            : 
    3112                 :        740 :         compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0);
    3113                 :            : 
    3114         [ +  + ]:        740 :         if (scope->kind == SCOPE_GEN_EXPR) {
    3115                 :        228 :             EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    3116                 :            :         }
    3117                 :        740 :         EMIT(return_value);
    3118                 :            :     } else {
    3119         [ -  + ]:       3674 :         assert(scope->kind == SCOPE_CLASS);
    3120   [ +  -  -  + ]:       3674 :         assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
    3121                 :       3674 :         mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
    3122         [ -  + ]:       3674 :         assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
    3123                 :            : 
    3124         [ +  + ]:       3674 :         if (comp->pass == MP_PASS_SCOPE) {
    3125                 :        920 :             scope_find_or_add_id(scope, MP_QSTR___class__, ID_INFO_KIND_LOCAL);
    3126                 :            :         }
    3127                 :            : 
    3128                 :            :         #if MICROPY_PY_SYS_SETTRACE
    3129                 :            :         EMIT_ARG(set_source_line, pns->source_line);
    3130                 :            :         #endif
    3131                 :       3674 :         compile_load_id(comp, MP_QSTR___name__);
    3132                 :       3674 :         compile_store_id(comp, MP_QSTR___module__);
    3133                 :       3674 :         EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
    3134                 :       3674 :         compile_store_id(comp, MP_QSTR___qualname__);
    3135                 :            : 
    3136                 :       3674 :         check_for_doc_string(comp, pns->nodes[2]);
    3137                 :       3674 :         compile_node(comp, pns->nodes[2]); // 2 is class body
    3138                 :            : 
    3139                 :       3674 :         id_info_t *id = scope_find(scope, MP_QSTR___class__);
    3140         [ -  + ]:       3674 :         assert(id != NULL);
    3141         [ +  + ]:       3674 :         if (id->kind == ID_INFO_KIND_LOCAL) {
    3142                 :       3590 :             EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
    3143                 :            :         } else {
    3144                 :         84 :             EMIT_LOAD_FAST(MP_QSTR___class__, id->local_num);
    3145                 :            :         }
    3146                 :       3674 :         EMIT(return_value);
    3147                 :            :     }
    3148                 :            : 
    3149                 :      35467 :     bool pass_complete = EMIT(end_pass);
    3150                 :            : 
    3151                 :            :     // make sure we match all the exception levels
    3152         [ -  + ]:      35465 :     assert(comp->cur_except_level == 0);
    3153                 :            : 
    3154                 :      35465 :     return pass_complete;
    3155                 :            : }
    3156                 :            : 
    3157                 :            : #if MICROPY_EMIT_INLINE_ASM
    3158                 :            : // requires 3 passes: SCOPE, CODE_SIZE, EMIT
    3159                 :            : STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
    3160                 :            :     comp->pass = pass;
    3161                 :            :     comp->scope_cur = scope;
    3162                 :            :     comp->next_label = 0;
    3163                 :            : 
    3164                 :            :     if (scope->kind != SCOPE_FUNCTION) {
    3165                 :            :         compile_syntax_error(comp, MP_PARSE_NODE_NULL, MP_ERROR_TEXT("inline assembler must be a function"));
    3166                 :            :         return;
    3167                 :            :     }
    3168                 :            : 
    3169                 :            :     if (comp->pass > MP_PASS_SCOPE) {
    3170                 :            :         EMIT_INLINE_ASM_ARG(start_pass, comp->pass, &comp->compile_error);
    3171                 :            :     }
    3172                 :            : 
    3173                 :            :     // get the function definition parse node
    3174                 :            :     assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
    3175                 :            :     mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
    3176                 :            :     assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
    3177                 :            : 
    3178                 :            :     // qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
    3179                 :            : 
    3180                 :            :     // parameters are in pns->nodes[1]
    3181                 :            :     if (comp->pass == MP_PASS_CODE_SIZE) {
    3182                 :            :         mp_parse_node_t *pn_params;
    3183                 :            :         size_t n_params = mp_parse_node_extract_list(&pns->nodes[1], PN_typedargslist, &pn_params);
    3184                 :            :         scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
    3185                 :            :         if (comp->compile_error != MP_OBJ_NULL) {
    3186                 :            :             goto inline_asm_error;
    3187                 :            :         }
    3188                 :            :     }
    3189                 :            : 
    3190                 :            :     // pns->nodes[2] is function return annotation
    3191                 :            :     mp_uint_t type_sig = MP_NATIVE_TYPE_INT;
    3192                 :            :     mp_parse_node_t pn_annotation = pns->nodes[2];
    3193                 :            :     if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
    3194                 :            :         // nodes[2] can be null or a test-expr
    3195                 :            :         if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
    3196                 :            :             qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
    3197                 :            :             switch (ret_type) {
    3198                 :            :                 case MP_QSTR_object:
    3199                 :            :                     type_sig = MP_NATIVE_TYPE_OBJ;
    3200                 :            :                     break;
    3201                 :            :                 case MP_QSTR_bool:
    3202                 :            :                     type_sig = MP_NATIVE_TYPE_BOOL;
    3203                 :            :                     break;
    3204                 :            :                 case MP_QSTR_int:
    3205                 :            :                     type_sig = MP_NATIVE_TYPE_INT;
    3206                 :            :                     break;
    3207                 :            :                 case MP_QSTR_uint:
    3208                 :            :                     type_sig = MP_NATIVE_TYPE_UINT;
    3209                 :            :                     break;
    3210                 :            :                 default:
    3211                 :            :                     compile_syntax_error(comp, pn_annotation, MP_ERROR_TEXT("unknown type"));
    3212                 :            :                     return;
    3213                 :            :             }
    3214                 :            :         } else {
    3215                 :            :             compile_syntax_error(comp, pn_annotation, MP_ERROR_TEXT("return annotation must be an identifier"));
    3216                 :            :         }
    3217                 :            :     }
    3218                 :            : 
    3219                 :            :     mp_parse_node_t pn_body = pns->nodes[3]; // body
    3220                 :            :     mp_parse_node_t *nodes;
    3221                 :            :     size_t num = mp_parse_node_extract_list(&pn_body, PN_suite_block_stmts, &nodes);
    3222                 :            : 
    3223                 :            :     for (size_t i = 0; i < num; i++) {
    3224                 :            :         assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
    3225                 :            :         mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t *)nodes[i];
    3226                 :            :         if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_pass_stmt) {
    3227                 :            :             // no instructions
    3228                 :            :             continue;
    3229                 :            :         } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_expr_stmt) {
    3230                 :            :             // not an instruction; error
    3231                 :            :         not_an_instruction:
    3232                 :            :             compile_syntax_error(comp, nodes[i], MP_ERROR_TEXT("expecting an assembler instruction"));
    3233                 :            :             return;
    3234                 :            :         }
    3235                 :            : 
    3236                 :            :         // check structure of parse node
    3237                 :            :         assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
    3238                 :            :         if (!MP_PARSE_NODE_IS_NULL(pns2->nodes[1])) {
    3239                 :            :             goto not_an_instruction;
    3240                 :            :         }
    3241                 :            :         pns2 = (mp_parse_node_struct_t *)pns2->nodes[0];
    3242                 :            :         if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_atom_expr_normal) {
    3243                 :            :             goto not_an_instruction;
    3244                 :            :         }
    3245                 :            :         if (!MP_PARSE_NODE_IS_ID(pns2->nodes[0])) {
    3246                 :            :             goto not_an_instruction;
    3247                 :            :         }
    3248                 :            :         if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren)) {
    3249                 :            :             goto not_an_instruction;
    3250                 :            :         }
    3251                 :            : 
    3252                 :            :         // parse node looks like an instruction
    3253                 :            :         // get instruction name and args
    3254                 :            :         qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
    3255                 :            :         pns2 = (mp_parse_node_struct_t *)pns2->nodes[1]; // PN_trailer_paren
    3256                 :            :         mp_parse_node_t *pn_arg;
    3257                 :            :         size_t n_args = mp_parse_node_extract_list(&pns2->nodes[0], PN_arglist, &pn_arg);
    3258                 :            : 
    3259                 :            :         // emit instructions
    3260                 :            :         if (op == MP_QSTR_label) {
    3261                 :            :             if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
    3262                 :            :                 compile_syntax_error(comp, nodes[i], MP_ERROR_TEXT("'label' requires 1 argument"));
    3263                 :            :                 return;
    3264                 :            :             }
    3265                 :            :             uint lab = comp_next_label(comp);
    3266                 :            :             if (pass > MP_PASS_SCOPE) {
    3267                 :            :                 if (!EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]))) {
    3268                 :            :                     compile_syntax_error(comp, nodes[i], MP_ERROR_TEXT("label redefined"));
    3269                 :            :                     return;
    3270                 :            :                 }
    3271                 :            :             }
    3272                 :            :         } else if (op == MP_QSTR_align) {
    3273                 :            :             if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
    3274                 :            :                 compile_syntax_error(comp, nodes[i], MP_ERROR_TEXT("'align' requires 1 argument"));
    3275                 :            :                 return;
    3276                 :            :             }
    3277                 :            :             if (pass > MP_PASS_SCOPE) {
    3278                 :            :                 mp_asm_base_align((mp_asm_base_t *)comp->emit_inline_asm,
    3279                 :            :                     MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));
    3280                 :            :             }
    3281                 :            :         } else if (op == MP_QSTR_data) {
    3282                 :            :             if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
    3283                 :            :                 compile_syntax_error(comp, nodes[i], MP_ERROR_TEXT("'data' requires at least 2 arguments"));
    3284                 :            :                 return;
    3285                 :            :             }
    3286                 :            :             if (pass > MP_PASS_SCOPE) {
    3287                 :            :                 mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
    3288                 :            :                 for (uint j = 1; j < n_args; j++) {
    3289                 :            :                     mp_obj_t int_obj;
    3290                 :            :                     if (!mp_parse_node_get_int_maybe(pn_arg[j], &int_obj)) {
    3291                 :            :                         compile_syntax_error(comp, nodes[i], MP_ERROR_TEXT("'data' requires integer arguments"));
    3292                 :            :                         return;
    3293                 :            :                     }
    3294                 :            :                     mp_asm_base_data((mp_asm_base_t *)comp->emit_inline_asm,
    3295                 :            :                         bytesize, mp_obj_int_get_truncated(int_obj));
    3296                 :            :                 }
    3297                 :            :             }
    3298                 :            :         } else {
    3299                 :            :             if (pass > MP_PASS_SCOPE) {
    3300                 :            :                 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
    3301                 :            :             }
    3302                 :            :         }
    3303                 :            : 
    3304                 :            :         if (comp->compile_error != MP_OBJ_NULL) {
    3305                 :            :             pns = pns2; // this is the parse node that had the error
    3306                 :            :             goto inline_asm_error;
    3307                 :            :         }
    3308                 :            :     }
    3309                 :            : 
    3310                 :            :     if (comp->pass > MP_PASS_SCOPE) {
    3311                 :            :         EMIT_INLINE_ASM_ARG(end_pass, type_sig);
    3312                 :            : 
    3313                 :            :         if (comp->pass == MP_PASS_EMIT) {
    3314                 :            :             void *f = mp_asm_base_get_code((mp_asm_base_t *)comp->emit_inline_asm);
    3315                 :            :             mp_emit_glue_assign_native(comp->scope_cur->raw_code, MP_CODE_NATIVE_ASM,
    3316                 :            :                 f, mp_asm_base_get_code_size((mp_asm_base_t *)comp->emit_inline_asm),
    3317                 :            :                 NULL,
    3318                 :            :                 #if MICROPY_PERSISTENT_CODE_SAVE
    3319                 :            :                 0,
    3320                 :            :                 0,
    3321                 :            :                 #endif
    3322                 :            :                 0, comp->scope_cur->num_pos_args, type_sig);
    3323                 :            :         }
    3324                 :            :     }
    3325                 :            : 
    3326                 :            :     if (comp->compile_error != MP_OBJ_NULL) {
    3327                 :            :         // inline assembler had an error; set line for its exception
    3328                 :            :     inline_asm_error:
    3329                 :            :         comp->compile_error_line = pns->source_line;
    3330                 :            :     }
    3331                 :            : }
    3332                 :            : #endif
    3333                 :            : 
    3334                 :       8816 : STATIC void scope_compute_things(scope_t *scope) {
    3335                 :            :     // in MicroPython we put the *x parameter after all other parameters (except **y)
    3336         [ +  + ]:       8816 :     if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {
    3337                 :         81 :         id_info_t *id_param = NULL;
    3338         [ +  - ]:        305 :         for (int i = scope->id_info_len - 1; i >= 0; i--) {
    3339                 :        305 :             id_info_t *id = &scope->id_info[i];
    3340         [ +  + ]:        305 :             if (id->flags & ID_FLAG_IS_STAR_PARAM) {
    3341         [ +  + ]:         81 :                 if (id_param != NULL) {
    3342                 :            :                     // swap star param with last param
    3343                 :         15 :                     id_info_t temp = *id_param;
    3344                 :         15 :                     *id_param = *id;
    3345                 :         15 :                     *id = temp;
    3346                 :            :                 }
    3347                 :            :                 break;
    3348   [ +  +  +  + ]:        224 :             } else if (id_param == NULL && id->flags == ID_FLAG_IS_PARAM) {
    3349                 :         15 :                 id_param = id;
    3350                 :            :             }
    3351                 :            :         }
    3352                 :            :     }
    3353                 :            : 
    3354                 :            :     // in functions, turn implicit globals into explicit globals
    3355                 :            :     // compute the index of each local
    3356                 :       8816 :     scope->num_locals = 0;
    3357         [ +  + ]:      44764 :     for (int i = 0; i < scope->id_info_len; i++) {
    3358                 :      35948 :         id_info_t *id = &scope->id_info[i];
    3359   [ +  +  +  + ]:      35948 :         if (scope->kind == SCOPE_CLASS && id->qst == MP_QSTR___class__) {
    3360                 :            :             // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
    3361                 :        918 :             continue;
    3362                 :            :         }
    3363   [ +  +  +  + ]:      35030 :         if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
    3364                 :       6374 :             id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
    3365                 :            :         }
    3366                 :            :         #if MICROPY_EMIT_NATIVE
    3367         [ +  + ]:      35030 :         if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) {
    3368                 :            :             // This function makes a reference to a global variable
    3369         [ +  + ]:       6765 :             if (scope->emit_options == MP_EMIT_OPT_VIPER
    3370         [ +  + ]:        162 :                 && mp_native_type_from_qstr(id->qst) >= MP_NATIVE_TYPE_INT) {
    3371                 :            :                 // A casting operator in viper mode, not a real global reference
    3372                 :            :             } else {
    3373                 :       6727 :                 scope->scope_flags |= MP_SCOPE_FLAG_REFGLOBALS;
    3374                 :            :             }
    3375                 :            :         }
    3376                 :            :         #endif
    3377                 :            :         // params always count for 1 local, even if they are a cell
    3378   [ +  +  +  + ]:      35030 :         if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) {
    3379                 :       8474 :             id->local_num = scope->num_locals++;
    3380                 :            :         }
    3381                 :            :     }
    3382                 :            : 
    3383                 :            :     // compute the index of cell vars
    3384         [ +  + ]:      44764 :     for (int i = 0; i < scope->id_info_len; i++) {
    3385                 :      35948 :         id_info_t *id = &scope->id_info[i];
    3386                 :            :         // in MicroPython the cells come right after the fast locals
    3387                 :            :         // parameters are not counted here, since they remain at the start
    3388                 :            :         // of the locals, even if they are cell vars
    3389   [ +  +  +  + ]:      35948 :         if (id->kind == ID_INFO_KIND_CELL && !(id->flags & ID_FLAG_IS_PARAM)) {
    3390                 :        130 :             id->local_num = scope->num_locals;
    3391                 :        130 :             scope->num_locals += 1;
    3392                 :            :         }
    3393                 :            :     }
    3394                 :            : 
    3395                 :            :     // compute the index of free vars
    3396                 :            :     // make sure they are in the order of the parent scope
    3397         [ +  + ]:       8816 :     if (scope->parent != NULL) {
    3398                 :            :         int num_free = 0;
    3399         [ +  + ]:      68848 :         for (int i = 0; i < scope->parent->id_info_len; i++) {
    3400                 :      63364 :             id_info_t *id = &scope->parent->id_info[i];
    3401         [ +  + ]:      63364 :             if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
    3402         [ +  + ]:       1389 :                 for (int j = 0; j < scope->id_info_len; j++) {
    3403                 :       1116 :                     id_info_t *id2 = &scope->id_info[j];
    3404   [ +  +  +  + ]:       1116 :                     if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
    3405         [ -  + ]:        192 :                         assert(!(id2->flags & ID_FLAG_IS_PARAM)); // free vars should not be params
    3406                 :            :                         // in MicroPython the frees come first, before the params
    3407                 :        192 :                         id2->local_num = num_free;
    3408                 :        192 :                         num_free += 1;
    3409                 :            :                     }
    3410                 :            :                 }
    3411                 :            :             }
    3412                 :            :         }
    3413                 :            :         // in MicroPython shift all other locals after the free locals
    3414         [ +  + ]:       5484 :         if (num_free > 0) {
    3415         [ +  + ]:        613 :             for (int i = 0; i < scope->id_info_len; i++) {
    3416                 :        483 :                 id_info_t *id = &scope->id_info[i];
    3417   [ +  +  -  + ]:        483 :                 if (id->kind != ID_INFO_KIND_FREE || (id->flags & ID_FLAG_IS_PARAM)) {
    3418                 :        291 :                     id->local_num += num_free;
    3419                 :            :                 }
    3420                 :            :             }
    3421                 :        130 :             scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function
    3422                 :        130 :             scope->num_locals += num_free;
    3423                 :            :         }
    3424                 :            :     }
    3425                 :       8816 : }
    3426                 :            : 
    3427                 :            : #if !MICROPY_PERSISTENT_CODE_SAVE
    3428                 :            : STATIC
    3429                 :            : #endif
    3430                 :       3560 : mp_compiled_module_t mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl, mp_module_context_t *context) {
    3431                 :            :     // put compiler state on the stack, it's relatively small
    3432                 :       3560 :     compiler_t comp_state = {0};
    3433                 :       3560 :     compiler_t *comp = &comp_state;
    3434                 :            : 
    3435                 :       3560 :     comp->is_repl = is_repl;
    3436                 :       3560 :     comp->break_label = INVALID_LABEL;
    3437                 :       3560 :     comp->continue_label = INVALID_LABEL;
    3438                 :       3560 :     mp_emit_common_init(&comp->emit_common, source_file);
    3439                 :            : 
    3440                 :            :     // create the module scope
    3441                 :            :     #if MICROPY_EMIT_NATIVE
    3442                 :       3560 :     const uint emit_opt = MP_STATE_VM(default_emit_opt);
    3443                 :            :     #else
    3444                 :            :     const uint emit_opt = MP_EMIT_OPT_NONE;
    3445                 :            :     #endif
    3446                 :       3560 :     scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, parse_tree->root, emit_opt);
    3447                 :            : 
    3448                 :            :     // create standard emitter; it's used at least for MP_PASS_SCOPE
    3449                 :       3560 :     emit_t *emit_bc = emit_bc_new(&comp->emit_common);
    3450                 :            : 
    3451                 :            :     // compile MP_PASS_SCOPE
    3452                 :       3560 :     comp->emit = emit_bc;
    3453                 :            :     #if MICROPY_EMIT_NATIVE
    3454                 :       3560 :     comp->emit_method_table = &emit_bc_method_table;
    3455                 :            :     #endif
    3456                 :       3560 :     uint max_num_labels = 0;
    3457   [ +  +  +  + ]:      12658 :     for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
    3458                 :            :         #if MICROPY_EMIT_INLINE_ASM
    3459                 :            :         if (s->emit_options == MP_EMIT_OPT_ASM) {
    3460                 :            :             compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);
    3461                 :            :         } else
    3462                 :            :         #endif
    3463                 :            :         {
    3464                 :       9102 :             compile_scope(comp, s, MP_PASS_SCOPE);
    3465                 :            : 
    3466                 :            :             // Check if any implicitly declared variables should be closed over
    3467         [ +  + ]:      45252 :             for (size_t i = 0; i < s->id_info_len; ++i) {
    3468                 :      36149 :                 id_info_t *id = &s->id_info[i];
    3469         [ +  + ]:      36149 :                 if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
    3470                 :      14840 :                     scope_check_to_close_over(s, id);
    3471                 :            :                 }
    3472                 :            :             }
    3473                 :            :         }
    3474                 :            : 
    3475                 :            :         // update maximim number of labels needed
    3476         [ +  + ]:       9098 :         if (comp->next_label > max_num_labels) {
    3477                 :       2903 :             max_num_labels = comp->next_label;
    3478                 :            :         }
    3479                 :            :     }
    3480                 :            : 
    3481                 :            :     // compute some things related to scope and identifiers
    3482   [ +  +  +  + ]:      12372 :     for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
    3483                 :       8816 :         scope_compute_things(s);
    3484                 :            :     }
    3485                 :            : 
    3486                 :            :     // set max number of labels now that it's calculated
    3487                 :       3556 :     emit_bc_set_max_num_labels(emit_bc, max_num_labels);
    3488                 :            : 
    3489                 :            :     // compile MP_PASS_STACK_SIZE, MP_PASS_CODE_SIZE, MP_PASS_EMIT
    3490                 :            :     #if MICROPY_EMIT_NATIVE
    3491                 :       3556 :     emit_t *emit_native = NULL;
    3492                 :            :     #endif
    3493   [ +  +  +  + ]:      12354 :     for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
    3494                 :            :         #if MICROPY_EMIT_INLINE_ASM
    3495                 :            :         if (s->emit_options == MP_EMIT_OPT_ASM) {
    3496                 :            :             // inline assembly
    3497                 :            :             if (comp->emit_inline_asm == NULL) {
    3498                 :            :                 comp->emit_inline_asm = ASM_EMITTER(new)(max_num_labels);
    3499                 :            :             }
    3500                 :            :             comp->emit = NULL;
    3501                 :            :             comp->emit_inline_asm_method_table = ASM_EMITTER_TABLE;
    3502                 :            :             compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
    3503                 :            :             #if MICROPY_EMIT_INLINE_XTENSA
    3504                 :            :             // Xtensa requires an extra pass to compute size of l32r const table
    3505                 :            :             // TODO this can be improved by calculating it during SCOPE pass
    3506                 :            :             // but that requires some other structural changes to the asm emitters
    3507                 :            :             #if MICROPY_DYNAMIC_COMPILER
    3508                 :            :             if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_XTENSA)
    3509                 :            :             #endif
    3510                 :            :             {
    3511                 :            :                 compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
    3512                 :            :             }
    3513                 :            :             #endif
    3514                 :            :             if (comp->compile_error == MP_OBJ_NULL) {
    3515                 :            :                 compile_scope_inline_asm(comp, s, MP_PASS_EMIT);
    3516                 :            :             }
    3517                 :            :         } else
    3518                 :            :         #endif
    3519                 :            :         {
    3520                 :            : 
    3521                 :            :             // choose the emit type
    3522                 :            : 
    3523         [ +  + ]:       8816 :             switch (s->emit_options) {
    3524                 :            : 
    3525                 :            :                 #if MICROPY_EMIT_NATIVE
    3526                 :       3978 :                 case MP_EMIT_OPT_NATIVE_PYTHON:
    3527                 :            :                 case MP_EMIT_OPT_VIPER:
    3528         [ +  + ]:       3978 :                     if (emit_native == NULL) {
    3529                 :       1367 :                         emit_native = NATIVE_EMITTER(new)(&comp->emit_common, &comp->compile_error, &comp->next_label, max_num_labels);
    3530                 :            :                     }
    3531                 :       3978 :                     comp->emit_method_table = NATIVE_EMITTER_TABLE;
    3532                 :       3978 :                     comp->emit = emit_native;
    3533                 :       3978 :                     break;
    3534                 :            :                 #endif // MICROPY_EMIT_NATIVE
    3535                 :            : 
    3536                 :       4838 :                 default:
    3537                 :       4838 :                     comp->emit = emit_bc;
    3538                 :            :                     #if MICROPY_EMIT_NATIVE
    3539                 :       4838 :                     comp->emit_method_table = &emit_bc_method_table;
    3540                 :            :                     #endif
    3541                 :       4838 :                     break;
    3542                 :            :             }
    3543                 :            : 
    3544                 :            :             // need a pass to compute stack size
    3545                 :       8816 :             compile_scope(comp, s, MP_PASS_STACK_SIZE);
    3546                 :            : 
    3547                 :            :             // second last pass: compute code size
    3548         [ +  + ]:       8800 :             if (comp->compile_error == MP_OBJ_NULL) {
    3549                 :       8720 :                 compile_scope(comp, s, MP_PASS_CODE_SIZE);
    3550                 :            :             }
    3551                 :            : 
    3552                 :            :             // final pass: emit code
    3553                 :            :             // the emitter can request multiple of these passes
    3554         [ +  + ]:       8800 :             if (comp->compile_error == MP_OBJ_NULL) {
    3555         [ +  + ]:       8848 :                 while (!compile_scope(comp, s, MP_PASS_EMIT)) {
    3556                 :       8850 :                 }
    3557                 :            :             }
    3558                 :            :         }
    3559                 :            :     }
    3560                 :            : 
    3561         [ +  + ]:       3538 :     if (comp->compile_error != MP_OBJ_NULL) {
    3562                 :            :         // if there is no line number for the error then use the line
    3563                 :            :         // number for the start of this scope
    3564                 :        304 :         compile_error_set_line(comp, comp->scope_cur->pn);
    3565                 :            :         // add a traceback to the exception using relevant source info
    3566                 :        304 :         mp_obj_exception_add_traceback(comp->compile_error, source_file,
    3567                 :        304 :             comp->compile_error_line, comp->scope_cur->simple_name);
    3568                 :            :     }
    3569                 :            : 
    3570                 :            :     // construct the global qstr/const table for this module
    3571                 :       3538 :     mp_compiled_module_t cm;
    3572                 :       3538 :     cm.rc = module_scope->raw_code;
    3573                 :       3538 :     cm.context = context;
    3574                 :            :     #if MICROPY_PERSISTENT_CODE_SAVE
    3575                 :            :     cm.has_native = false;
    3576                 :            :     #if MICROPY_EMIT_NATIVE
    3577                 :            :     if (emit_native != NULL) {
    3578                 :            :         cm.has_native = true;
    3579                 :            :     }
    3580                 :            :     #endif
    3581                 :            :     #if MICROPY_EMIT_INLINE_ASM
    3582                 :            :     if (comp->emit_inline_asm != NULL) {
    3583                 :            :         cm.has_native = true;
    3584                 :            :     }
    3585                 :            :     #endif
    3586                 :            :     cm.n_qstr = comp->emit_common.qstr_map.used;
    3587                 :            :     cm.n_obj = comp->emit_common.const_obj_list.len;
    3588                 :            :     #endif
    3589         [ +  + ]:       3538 :     if (comp->compile_error == MP_OBJ_NULL) {
    3590                 :       3234 :         mp_emit_common_populate_module_context(&comp->emit_common, source_file, context);
    3591                 :            : 
    3592                 :            :         #if MICROPY_DEBUG_PRINTERS
    3593                 :            :         // now that the module context is valid, the raw codes can be printed
    3594         [ +  + ]:       3234 :         if (mp_verbose_flag >= 2) {
    3595         [ +  + ]:         52 :             for (scope_t *s = comp->scope_head; s != NULL; s = s->next) {
    3596                 :         42 :                 mp_raw_code_t *rc = s->raw_code;
    3597         [ +  - ]:         42 :                 if (rc->kind == MP_CODE_BYTECODE) {
    3598                 :         42 :                     mp_bytecode_print(&mp_plat_print, rc, &cm.context->constants);
    3599                 :            :                 }
    3600                 :            :             }
    3601                 :            :         }
    3602                 :            :         #endif
    3603                 :            :     }
    3604                 :            : 
    3605                 :            :     // free the emitters
    3606                 :            : 
    3607                 :       3538 :     emit_bc_free(emit_bc);
    3608                 :            :     #if MICROPY_EMIT_NATIVE
    3609         [ +  + ]:       3538 :     if (emit_native != NULL) {
    3610                 :       1351 :         NATIVE_EMITTER(free)(emit_native);
    3611                 :            :     }
    3612                 :            :     #endif
    3613                 :            :     #if MICROPY_EMIT_INLINE_ASM
    3614                 :            :     if (comp->emit_inline_asm != NULL) {
    3615                 :            :         ASM_EMITTER(free)(comp->emit_inline_asm);
    3616                 :            :     }
    3617                 :            :     #endif
    3618                 :            : 
    3619                 :            :     // free the parse tree
    3620                 :       3538 :     mp_parse_tree_clear(parse_tree);
    3621                 :            : 
    3622                 :            :     // free the scopes
    3623         [ +  + ]:      12614 :     for (scope_t *s = module_scope; s;) {
    3624                 :       9076 :         scope_t *next = s->next;
    3625                 :       9076 :         scope_free(s);
    3626                 :       9076 :         s = next;
    3627                 :            :     }
    3628                 :            : 
    3629         [ +  + ]:       3538 :     if (comp->compile_error != MP_OBJ_NULL) {
    3630                 :        304 :         nlr_raise(comp->compile_error);
    3631                 :            :     }
    3632                 :            : 
    3633                 :       3234 :     return cm;
    3634                 :            : }
    3635                 :            : 
    3636                 :       3560 : mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) {
    3637                 :       3560 :     mp_module_context_t *context = m_new_obj(mp_module_context_t);
    3638                 :       3560 :     context->module.globals = mp_globals_get();
    3639                 :       3560 :     mp_compiled_module_t cm = mp_compile_to_raw_code(parse_tree, source_file, is_repl, context);
    3640                 :            :     // return function that executes the outer module
    3641                 :       3234 :     return mp_make_function_from_raw_code(cm.rc, cm.context, NULL);
    3642                 :            : }
    3643                 :            : 
    3644                 :            : #endif // MICROPY_ENABLE_COMPILER

Generated by: LCOV version 1.15-5-g462f71d