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

Generated by: LCOV version 1.15-5-g462f71d