LCOV - code coverage report
Current view: top level - py - compile.c (source / functions) Hit Total Coverage
Test: unix_coverage_v1.22.0-344-ge60e8079a.info Lines: 1762 1766 99.8 %
Date: 2024-04-26 14:58:11 Functions: 98 98 100.0 %
Branches: 990 1148 86.2 %

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

Generated by: LCOV version 1.15-5-g462f71d