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

Generated by: LCOV version 1.15-5-g462f71d