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 : 3895 : static void mp_emit_common_init(mp_emit_common_t *emit, qstr source_file) {
214 : : #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE
215 : 3895 : mp_map_init(&emit->qstr_map, 1);
216 : :
217 : : // add the source file as the first entry in the qstr table
218 : 3895 : 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 : 3895 : elem->value = MP_OBJ_NEW_SMALL_INT(0);
220 : : #endif
221 : 3895 : mp_obj_list_init(&emit->const_obj_list, 0);
222 : 3895 : }
223 : :
224 : 40695 : static void mp_emit_common_start_pass(mp_emit_common_t *emit, pass_kind_t pass) {
225 : 40695 : emit->pass = pass;
226 [ + + ]: 40695 : if (pass == MP_PASS_CODE_SIZE) {
227 [ + + ]: 10012 : if (emit->ct_cur_child == 0) {
228 : 7823 : emit->children = NULL;
229 : : } else {
230 : 2189 : emit->children = m_new0(mp_raw_code_t *, emit->ct_cur_child);
231 : : }
232 : : }
233 : 40695 : emit->ct_cur_child = 0;
234 : 40695 : }
235 : :
236 : 3556 : 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 : 3556 : size_t qstr_map_used = emit->qstr_map.used;
239 : 3556 : mp_module_context_alloc_tables(context, qstr_map_used, emit->const_obj_list.len);
240 [ + + ]: 47902 : for (size_t i = 0; i < emit->qstr_map.alloc; ++i) {
241 [ + + ]: 44346 : if (mp_map_slot_is_filled(&emit->qstr_map, i)) {
242 : 40097 : size_t idx = MP_OBJ_SMALL_INT_VALUE(emit->qstr_map.table[i].value);
243 : 40097 : qstr qst = MP_OBJ_QSTR_VALUE(emit->qstr_map.table[i].key);
244 : 40097 : 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 [ + + ]: 10124 : for (size_t i = 0; i < emit->const_obj_list.len; ++i) {
253 : 6568 : context->constants.obj_table[i] = emit->const_obj_list.items[i];
254 : : }
255 : 3556 : }
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 : 294011 : static uint comp_next_label(compiler_t *comp) {
280 : 294011 : return comp->next_label++;
281 : : }
282 : :
283 : : #if MICROPY_EMIT_NATIVE
284 : 171730 : static void reserve_labels_for_native(compiler_t *comp, int n) {
285 [ + + ]: 171730 : if (comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {
286 : 31006 : comp->next_label += n;
287 : : }
288 : 171730 : }
289 : : #else
290 : : #define reserve_labels_for_native(comp, n)
291 : : #endif
292 : :
293 : 90000 : static void compile_increase_except_level(compiler_t *comp, uint label, int kind) {
294 : 90000 : EMIT_ARG(setup_block, label, kind);
295 : 90000 : comp->cur_except_level += 1;
296 [ + + ]: 90000 : if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {
297 : 2340 : comp->scope_cur->exc_stack_size = comp->cur_except_level;
298 : : }
299 : 90000 : }
300 : :
301 : 90000 : static void compile_decrease_except_level(compiler_t *comp) {
302 [ - + ]: 90000 : assert(comp->cur_except_level > 0);
303 : 90000 : comp->cur_except_level -= 1;
304 : 90000 : EMIT(end_finally);
305 : 90000 : reserve_labels_for_native(comp, 1);
306 : 90000 : }
307 : :
308 : 10441 : static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
309 : 10441 : scope_t *scope = scope_new(kind, pn, emit_options);
310 : 10441 : scope->parent = comp->scope_cur;
311 : 10441 : scope->next = NULL;
312 [ + + ]: 10441 : if (comp->scope_head == NULL) {
313 : 3895 : comp->scope_head = scope;
314 : : } else {
315 : : scope_t *s = comp->scope_head;
316 [ + + ]: 59829 : while (s->next != NULL) {
317 : : s = s->next;
318 : : }
319 : 6546 : s->next = scope;
320 : : }
321 : 10441 : return scope;
322 : : }
323 : :
324 : : typedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn);
325 : :
326 : 31136 : 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 [ + + + + : 31136 : if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) {
+ + ]
328 : 10511 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
329 : 10511 : int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
330 [ + + ]: 35900 : for (int i = 0; i < num_nodes; i++) {
331 : 25389 : f(comp, pns->nodes[i]);
332 : : }
333 : : } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
334 : 14032 : f(comp, pn);
335 : : }
336 : 31132 : }
337 : :
338 : 80849 : static void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
339 : 80849 : int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
340 [ + + ]: 321136 : for (int i = 0; i < num_nodes; i++) {
341 : 240316 : compile_node(comp, pns->nodes[i]);
342 [ + + ]: 240316 : 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 : 424024 : static void compile_load_id(compiler_t *comp, qstr qst) {
351 [ + + ]: 424024 : if (comp->pass == MP_PASS_SCOPE) {
352 : 83097 : mp_emit_common_get_id_for_load(comp->scope_cur, qst);
353 : : } else {
354 : : #if NEED_METHOD_TABLE
355 : 340927 : 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 : 424023 : }
361 : :
362 : 123995 : static void compile_store_id(compiler_t *comp, qstr qst) {
363 [ + + ]: 123995 : if (comp->pass == MP_PASS_SCOPE) {
364 : 23475 : mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
365 : : } else {
366 : : #if NEED_METHOD_TABLE
367 : 100520 : 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 : 123995 : }
373 : :
374 : 2046 : static void compile_delete_id(compiler_t *comp, qstr qst) {
375 [ + + ]: 2046 : if (comp->pass == MP_PASS_SCOPE) {
376 : 495 : mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
377 : : } else {
378 : : #if NEED_METHOD_TABLE
379 : 1551 : 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 : 2046 : }
385 : :
386 : 4345 : static void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
387 : : // a simple tuple expression
388 : 4345 : size_t num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
389 [ + + ]: 16494 : for (size_t i = 0; i < num_nodes; i++) {
390 : 12149 : compile_node(comp, pns->nodes[i]);
391 : : }
392 : 4345 : EMIT_ARG(build, num_nodes, MP_EMIT_BUILD_TUPLE);
393 : 4345 : }
394 : :
395 : 22680 : static void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
396 [ + + ]: 22680 : if (mp_parse_node_is_const_false(pn)) {
397 [ + + ]: 104 : if (jump_if == false) {
398 : 8 : EMIT_ARG(jump, label);
399 : : }
400 : 104 : return;
401 [ + + ]: 22576 : } 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 [ + - + + ]: 21464 : } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
407 : 18901 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
408 : 18901 : int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
409 [ + + ]: 18901 : if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
410 [ + + ]: 464 : if (jump_if == false) {
411 : 448 : and_or_logic1:;
412 : 484 : uint label2 = comp_next_label(comp);
413 [ + + ]: 976 : for (int i = 0; i < n - 1; i++) {
414 : 492 : c_if_cond(comp, pns->nodes[i], !jump_if, label2);
415 : : }
416 : 484 : c_if_cond(comp, pns->nodes[n - 1], jump_if, label);
417 : 484 : EMIT_ARG(label_assign, label2);
418 : : } else {
419 : 16 : and_or_logic2:
420 [ + + ]: 3983 : for (int i = 0; i < n; i++) {
421 : 2658 : c_if_cond(comp, pns->nodes[i], jump_if, label);
422 : : }
423 : : }
424 : 1809 : return;
425 [ + + ]: 18437 : } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
426 [ + + ]: 1345 : if (jump_if == false) {
427 : 1309 : goto and_or_logic2;
428 : : } else {
429 : 36 : goto and_or_logic1;
430 : : }
431 [ + + ]: 17092 : } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
432 : 2430 : c_if_cond(comp, pns->nodes[0], !jump_if, label);
433 : 2430 : return;
434 : : }
435 : : }
436 : :
437 : : // nothing special, fall back to default compiling for node and jump
438 : 17225 : compile_node(comp, pn);
439 : 17225 : 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 : 11447 : static void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
446 [ + + ]: 11447 : if (assign_kind != ASSIGN_AUG_STORE) {
447 : 11191 : compile_node(comp, pns->nodes[0]);
448 : : }
449 : :
450 [ + - + - ]: 11447 : if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
451 : 11447 : mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pns->nodes[1];
452 [ + + ]: 11447 : 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 [ + + ]: 11447 : if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
463 [ + + ]: 4138 : if (assign_kind == ASSIGN_AUG_STORE) {
464 : 44 : EMIT(rot_three);
465 : 44 : EMIT_ARG(subscr, MP_EMIT_SUBSCR_STORE);
466 : : } else {
467 : 4094 : compile_node(comp, pns1->nodes[0]);
468 [ + + ]: 4094 : if (assign_kind == ASSIGN_AUG_LOAD) {
469 : 44 : EMIT(dup_top_two);
470 : 44 : EMIT_ARG(subscr, MP_EMIT_SUBSCR_LOAD);
471 : : } else {
472 : 4050 : EMIT_ARG(subscr, MP_EMIT_SUBSCR_STORE);
473 : : }
474 : : }
475 : 4138 : return;
476 [ + + ]: 7309 : } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
477 [ - + ]: 7305 : assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
478 [ + + ]: 7305 : if (assign_kind == ASSIGN_AUG_LOAD) {
479 : 212 : EMIT(dup_top);
480 : 212 : EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_LOAD);
481 : : } else {
482 [ + + ]: 7093 : if (assign_kind == ASSIGN_AUG_STORE) {
483 : 212 : EMIT(rot_two);
484 : : }
485 : 7093 : EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]), MP_EMIT_ATTR_STORE);
486 : : }
487 : 7305 : 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 : 1504 : static void c_assign_tuple(compiler_t *comp, uint num_tail, mp_parse_node_t *nodes_tail) {
495 : : // look for star expression
496 : 1504 : uint have_star_index = -1;
497 [ + + ]: 5030 : for (uint i = 0; i < num_tail; i++) {
498 [ + - + + : 3530 : 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 [ + + ]: 1500 : if (have_star_index == (uint)-1) {
509 : 1228 : EMIT_ARG(unpack_sequence, num_tail);
510 : : }
511 [ + + ]: 5022 : for (uint i = 0; i < num_tail; i++) {
512 [ + + ]: 3522 : 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 : 3250 : c_assign(comp, nodes_tail[i], ASSIGN_STORE);
516 : : }
517 : : }
518 : : }
519 : :
520 : : // assigns top of stack to pn
521 : 93943 : static void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
522 [ - + ]: 93943 : assert(!MP_PARSE_NODE_IS_NULL(pn));
523 [ + + ]: 93943 : if (MP_PARSE_NODE_IS_LEAF(pn)) {
524 [ + + ]: 80948 : if (MP_PARSE_NODE_IS_ID(pn)) {
525 : 80936 : qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);
526 [ + + ]: 80936 : switch (assign_kind) {
527 : 79219 : case ASSIGN_STORE:
528 : : case ASSIGN_AUG_STORE:
529 : 79219 : compile_store_id(comp, arg);
530 : 79219 : break;
531 : 1717 : case ASSIGN_AUG_LOAD:
532 : : default:
533 : 1717 : compile_load_id(comp, arg);
534 : 1717 : break;
535 : : }
536 : : } else {
537 : 12 : goto cannot_assign;
538 : : }
539 : : } else {
540 : : // pn must be a struct
541 : 12995 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
542 [ + + + + : 12995 : switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
+ ]
543 : 11447 : case PN_atom_expr_normal:
544 : : // lhs is an index or attribute
545 : 11447 : c_assign_atom_expr(comp, pns, assign_kind);
546 : 11447 : break;
547 : :
548 : 1408 : case PN_testlist_star_expr:
549 : : case PN_exprlist:
550 : : // lhs is a tuple
551 [ + + ]: 1408 : if (assign_kind != ASSIGN_STORE) {
552 : 8 : goto cannot_assign;
553 : : }
554 : 1400 : c_assign_tuple(comp, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
555 : 1400 : 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 : 12871 : 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 : 25954 : static void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
613 [ - + ]: 25954 : assert(n_pos_defaults >= 0);
614 [ - + ]: 25954 : assert(n_kw_defaults >= 0);
615 : :
616 : : // set flags
617 [ + + ]: 25954 : if (n_kw_defaults > 0) {
618 : 120 : this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS;
619 : : }
620 : 25954 : 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 : 25954 : 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 : 25954 : int nfree = 0;
630 [ + + ]: 25954 : if (comp->scope_cur->kind != SCOPE_MODULE) {
631 [ + + ]: 124707 : for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
632 : 113197 : id_info_t *id = &comp->scope_cur->id_info[i];
633 [ + + ]: 113197 : if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
634 [ + + ]: 6639 : for (int j = 0; j < this_scope->id_info_len; j++) {
635 : 5313 : id_info_t *id2 = &this_scope->id_info[j];
636 [ + + + + ]: 5313 : if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
637 : : // in MicroPython we load closures using LOAD_FAST
638 : 825 : EMIT_LOAD_FAST(id->qst, id->local_num);
639 : 825 : nfree += 1;
640 : : }
641 : : }
642 : : }
643 : : }
644 : : }
645 : :
646 : : // make the function/closure
647 [ + + ]: 11510 : if (nfree == 0) {
648 : 25419 : EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);
649 : : } else {
650 : 535 : EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);
651 : : }
652 : 25954 : }
653 : :
654 : 26802 : 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 : 26802 : int pn_kind;
657 [ + + ]: 26802 : if (MP_PARSE_NODE_IS_ID(pn)) {
658 : : pn_kind = -1;
659 : : } else {
660 [ + - - + ]: 4181 : assert(MP_PARSE_NODE_IS_STRUCT(pn));
661 : 4181 : pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pn);
662 : : }
663 : :
664 [ + + - + : 26802 : if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) {
+ + ]
665 : 566 : 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 : 3390 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
692 : 3390 : pn_id = pns->nodes[0];
693 : : // pn_colon = pns->nodes[1]; // unused
694 : 3390 : 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 [ + + ]: 3414 : 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 [ + + + + ]: 23997 : 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 [ + + ]: 2038 : 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 : 1902 : comp->num_default_params += 1;
739 : 1902 : compile_node(comp, pn_equal);
740 : : }
741 : : }
742 : : }
743 : : }
744 : :
745 : 20895 : 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 : 20895 : bool orig_have_star = comp->have_star;
750 : 20895 : uint16_t orig_num_dict_params = comp->num_dict_params;
751 : 20895 : uint16_t orig_num_default_params = comp->num_default_params;
752 : :
753 : : // compile default parameters
754 : 20895 : comp->have_star = false;
755 : 20895 : comp->num_dict_params = 0;
756 : 20895 : comp->num_default_params = 0;
757 : 20895 : apply_to_single_or_list(comp, pn_params, pn_list_kind, compile_funcdef_lambdef_param);
758 : :
759 [ + + ]: 20895 : 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 [ + + + + ]: 20878 : if (comp->num_default_params > 0 && comp->num_dict_params == 0) {
766 : 1450 : EMIT_ARG(build, comp->num_default_params, MP_EMIT_BUILD_TUPLE);
767 : 1450 : EMIT(load_null); // sentinel indicating empty default keyword args
768 : : }
769 : :
770 : : // make the function
771 : 20878 : close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);
772 : :
773 : : // restore state
774 : 20878 : comp->have_star = orig_have_star;
775 : 20878 : comp->num_dict_params = orig_num_dict_params;
776 : 20878 : comp->num_default_params = orig_num_default_params;
777 : : }
778 : :
779 : : // leaves function object on stack
780 : : // returns function name
781 : 20270 : static qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
782 [ + + ]: 20270 : if (comp->pass == MP_PASS_SCOPE) {
783 : : // create a new scope for this function
784 : 5107 : 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 : 5107 : pns->nodes[4] = (mp_parse_node_t)s;
787 : : }
788 : :
789 : : // get the scope for this function
790 : 20270 : scope_t *fscope = (scope_t *)pns->nodes[4];
791 : :
792 : : // compile the function definition
793 : 20270 : compile_funcdef_lambdef(comp, fscope, pns->nodes[1], PN_typedargslist);
794 : :
795 : : // return its name (the 'f' in "def f(...):")
796 : 20270 : return fscope->simple_name;
797 : : }
798 : :
799 : : // leaves class object on stack
800 : : // returns class name
801 : 4233 : static qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
802 [ + + ]: 4233 : if (comp->pass == MP_PASS_SCOPE) {
803 : : // create a new scope for this class
804 : 1057 : 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 : 1057 : pns->nodes[3] = (mp_parse_node_t)s;
807 : : }
808 : :
809 : 4233 : EMIT(load_build_class);
810 : :
811 : : // scope for this class
812 : 4233 : scope_t *cscope = (scope_t *)pns->nodes[3];
813 : :
814 : : // compile the class
815 : 4233 : close_over_variables_etc(comp, cscope, 0, 0);
816 : :
817 : : // get its name
818 : 4233 : 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 : 4233 : mp_parse_node_t parents = pns->nodes[1];
823 [ + + + + : 4233 : if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
+ + ]
824 : 48 : parents = MP_PARSE_NODE_NULL;
825 : : }
826 : 4233 : compile_trailer_paren_helper(comp, parents, false, 2);
827 : :
828 : : // return its name (the 'C' in class C(...):")
829 : 4233 : 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 : 18513 : static void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
951 : 18513 : qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
952 : : // store function object into function name
953 : 18513 : compile_store_id(comp, fname);
954 : 18513 : }
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 : 1160 : static void compile_break_cont_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1017 : 1160 : uint16_t label;
1018 [ + + ]: 1160 : if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_break_stmt) {
1019 : 928 : label = comp->break_label;
1020 : : } else {
1021 : 232 : label = comp->continue_label;
1022 : : }
1023 [ + + ]: 1160 : if (label == INVALID_LABEL) {
1024 : 8 : compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'break'/'continue' outside loop"));
1025 : : }
1026 [ - + ]: 1160 : assert(comp->cur_except_level >= comp->break_continue_except_level);
1027 : 1160 : EMIT_ARG(unwind_jump, label, comp->cur_except_level - comp->break_continue_except_level);
1028 : 1160 : }
1029 : :
1030 : 9464 : static void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1031 : : #if MICROPY_CPYTHON_COMPAT
1032 [ + + ]: 9464 : 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 [ + + ]: 9460 : if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
1038 : : // no argument to 'return', so return None
1039 : 656 : EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1040 : 8804 : } else if (MICROPY_COMP_RETURN_IF_EXPR
1041 [ + + + + ]: 9060 : && 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 : 8548 : compile_node(comp, pns->nodes[0]);
1054 : : }
1055 : 9460 : 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 : 7161 : static void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1064 [ + + ]: 7161 : if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
1065 : : // raise
1066 : 54 : EMIT_ARG(raise_varargs, 0);
1067 [ + + + + ]: 7107 : } 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 : 7099 : compile_node(comp, pns->nodes[0]);
1076 : 7099 : EMIT_ARG(raise_varargs, 1);
1077 : : }
1078 : 7161 : }
1079 : :
1080 : : // q_base holds the base of the name
1081 : : // eg a -> q_base=a
1082 : : // a.b.c -> q_base=a
1083 : 7166 : static void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
1084 : 7166 : bool is_as = false;
1085 [ + + + + : 7166 : 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 [ + + ]: 6998 : } else if (MP_PARSE_NODE_IS_ID(pn)) {
1097 : : // just a simple name
1098 : 6746 : qstr q_full = MP_PARSE_NODE_LEAF_ARG(pn);
1099 [ + + ]: 6746 : if (!is_as) {
1100 : 6694 : *q_base = q_full;
1101 : : }
1102 : 6746 : 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 : 7162 : }
1143 : :
1144 : 5098 : static void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
1145 : 5098 : EMIT_ARG(load_const_small_int, 0); // level 0 import
1146 : 5098 : EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything
1147 : 5098 : qstr q_base;
1148 : 5098 : do_import_name(comp, pn, &q_base);
1149 : 5094 : compile_store_id(comp, q_base);
1150 : 5094 : }
1151 : :
1152 : 4210 : static void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
1153 : 4210 : apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1154 : 4206 : }
1155 : :
1156 : 2072 : static void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
1157 : 2072 : 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 : 2072 : uint import_level = 0;
1161 : 4144 : do {
1162 : 2072 : mp_parse_node_t pn_rel;
1163 [ + + + - : 2072 : if (MP_PARSE_NODE_IS_TOKEN(pn_import_source) || MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_one_or_more_period_or_ellipsis)) {
+ + + + ]
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 [ + + + + ]: 1904 : } 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 [ + + ]: 2072 : 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 : 1730 : EMIT_ARG(load_const_small_int, import_level);
1214 : :
1215 : : // build the "fromlist" tuple
1216 : 1730 : mp_parse_node_t *pn_nodes;
1217 : 1730 : size_t n = mp_parse_node_extract_list(&pns->nodes[1], PN_import_as_names, &pn_nodes);
1218 [ + + ]: 4557 : for (size_t i = 0; i < n; i++) {
1219 [ + - + - : 2827 : assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
- + ]
1220 : 2827 : mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t *)pn_nodes[i];
1221 : 2827 : qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
1222 : 2827 : EMIT_ARG(load_const_str, id2);
1223 : : }
1224 : 1730 : EMIT_ARG(build, n, MP_EMIT_BUILD_TUPLE);
1225 : :
1226 : : // do the import
1227 : 1730 : qstr dummy_q;
1228 : 1730 : do_import_name(comp, pn_import_source, &dummy_q);
1229 [ + + ]: 4557 : for (size_t i = 0; i < n; i++) {
1230 [ + - + - : 2827 : assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
- + ]
1231 : 2827 : mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t *)pn_nodes[i];
1232 : 2827 : qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
1233 : 2827 : EMIT_ARG(import, id2, MP_EMIT_IMPORT_FROM);
1234 [ + + ]: 2827 : if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
1235 : 2563 : compile_store_id(comp, id2);
1236 : : } else {
1237 : 264 : compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
1238 : : }
1239 : : }
1240 : 1730 : EMIT(pop_top);
1241 : : }
1242 : : }
1243 : :
1244 : 399 : static void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) {
1245 [ + + ]: 399 : 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 : 387 : 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 : 387 : id_info = scope_find_global(comp->scope_cur, id_info->qst);
1253 [ + + ]: 387 : if (id_info != NULL) {
1254 : 245 : 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 : 465 : static void compile_declare_global_or_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info, bool is_global) {
1271 [ + + ]: 465 : if (is_global) {
1272 : 399 : compile_declare_global(comp, pn, id_info);
1273 : : } else {
1274 : 66 : compile_declare_nonlocal(comp, pn, id_info);
1275 : : }
1276 : 465 : }
1277 : :
1278 : 1435 : static void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1279 [ + + ]: 1435 : if (comp->pass == MP_PASS_SCOPE) {
1280 : 366 : bool is_global = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_global_stmt;
1281 : :
1282 [ + + + + ]: 366 : 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 : 362 : mp_parse_node_t *nodes;
1288 : 362 : size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
1289 [ + + ]: 797 : for (size_t i = 0; i < n; i++) {
1290 : 435 : qstr qst = MP_PARSE_NODE_LEAF_ARG(nodes[i]);
1291 : 435 : id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, ID_INFO_KIND_UNDECIDED);
1292 : 435 : compile_declare_global_or_nonlocal(comp, (mp_parse_node_t)pns, id_info, is_global);
1293 : : }
1294 : : }
1295 : : }
1296 : :
1297 : 2209 : static void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1298 : : // with optimisations enabled we don't compile assertions
1299 [ + + ]: 2209 : if (MP_STATE_VM(mp_optimise_value) != 0) {
1300 : : return;
1301 : : }
1302 : :
1303 : 2185 : uint l_end = comp_next_label(comp);
1304 : 2185 : c_if_cond(comp, pns->nodes[0], true, l_end);
1305 : 2185 : EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
1306 [ + + ]: 2185 : if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
1307 : : // assertion message
1308 : 208 : compile_node(comp, pns->nodes[1]);
1309 : 208 : EMIT_ARG(call_function, 1, 0, 0);
1310 : : }
1311 : 2185 : EMIT_ARG(raise_varargs, 1);
1312 : 2185 : EMIT_ARG(label_assign, l_end);
1313 : : }
1314 : :
1315 : 10273 : static void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1316 : 10273 : uint l_end = comp_next_label(comp);
1317 : :
1318 : : // optimisation: don't emit anything when "if False"
1319 [ + + ]: 10273 : if (!mp_parse_node_is_const_false(pns->nodes[0])) {
1320 : 10161 : uint l_fail = comp_next_label(comp);
1321 : 10161 : c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
1322 : :
1323 : 10161 : compile_node(comp, pns->nodes[1]); // if block
1324 : :
1325 : : // optimisation: skip everything else when "if True"
1326 [ + + ]: 10161 : 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 [ + + + + ]: 9977 : if (!(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))) {
1332 : : // jump over elif/else blocks
1333 : 3351 : EMIT_ARG(jump, l_end);
1334 : : }
1335 : :
1336 : 9977 : EMIT_ARG(label_assign, l_fail);
1337 : : }
1338 : :
1339 : : // compile elif blocks (if any)
1340 : 10089 : mp_parse_node_t *pn_elif;
1341 : 10089 : size_t n_elif = mp_parse_node_extract_list(&pns->nodes[2], PN_if_stmt_elif_list, &pn_elif);
1342 [ + + ]: 11770 : for (size_t i = 0; i < n_elif; i++) {
1343 [ + - + - : 1689 : assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_elif[i], PN_if_stmt_elif)); // should be
- + ]
1344 : 1689 : 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 [ + + ]: 1689 : if (!mp_parse_node_is_const_false(pns_elif->nodes[0])) {
1348 : 1681 : uint l_fail = comp_next_label(comp);
1349 : 1681 : c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
1350 : :
1351 : 1681 : compile_node(comp, pns_elif->nodes[1]); // elif block
1352 : :
1353 : : // optimisation: skip everything else when "elif True"
1354 [ + + ]: 1681 : if (mp_parse_node_is_const_true(pns_elif->nodes[0])) {
1355 : 8 : goto done;
1356 : : }
1357 : :
1358 : 1673 : EMIT_ARG(jump, l_end);
1359 : 1673 : EMIT_ARG(label_assign, l_fail);
1360 : : }
1361 : : }
1362 : :
1363 : : // compile else block
1364 : 10081 : compile_node(comp, pns->nodes[3]); // can be null
1365 : :
1366 : 10273 : done:
1367 : 10273 : EMIT_ARG(label_assign, l_end);
1368 : 10273 : }
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 : 1915 : static void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1386 : 1915 : START_BREAK_CONTINUE_BLOCK
1387 : :
1388 [ + + ]: 1915 : if (!mp_parse_node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False"
1389 : 1875 : uint top_label = comp_next_label(comp);
1390 [ + + ]: 1875 : if (!mp_parse_node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for "while True"
1391 : 971 : EMIT_ARG(jump, continue_label);
1392 : : }
1393 : 1875 : EMIT_ARG(label_assign, top_label);
1394 : 1875 : compile_node(comp, pns->nodes[1]); // body
1395 : 1875 : EMIT_ARG(label_assign, continue_label);
1396 : 1875 : 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 : 1915 : END_BREAK_CONTINUE_BLOCK
1401 : :
1402 : 1915 : compile_node(comp, pns->nodes[2]); // else
1403 : :
1404 : 1915 : EMIT_ARG(label_assign, break_label);
1405 : 1915 : }
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 : 2428 : static void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) {
1424 : 2428 : START_BREAK_CONTINUE_BLOCK
1425 : :
1426 : 2428 : uint top_label = comp_next_label(comp);
1427 : 2428 : 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 : 2428 : bool end_on_stack = !MP_PARSE_NODE_IS_SMALL_INT(pn_end);
1431 [ + + ]: 2428 : if (end_on_stack) {
1432 : 1151 : compile_node(comp, pn_end);
1433 : : }
1434 : :
1435 : : // compile: start
1436 : 2428 : compile_node(comp, pn_start);
1437 : :
1438 : 2428 : EMIT_ARG(jump, entry_label);
1439 : 2428 : EMIT_ARG(label_assign, top_label);
1440 : :
1441 : : // duplicate next value and store it to var
1442 : 2428 : EMIT(dup_top);
1443 : 2428 : c_assign(comp, pn_var, ASSIGN_STORE);
1444 : :
1445 : : // compile body
1446 : 2428 : compile_node(comp, pn_body);
1447 : :
1448 : 2428 : EMIT_ARG(label_assign, continue_label);
1449 : :
1450 : : // compile: var + step
1451 : 2428 : compile_node(comp, pn_step);
1452 : 2428 : EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);
1453 : :
1454 : 2428 : EMIT_ARG(label_assign, entry_label);
1455 : :
1456 : : // compile: if var <cond> end: goto top
1457 [ + + ]: 2428 : if (end_on_stack) {
1458 : 1151 : EMIT(dup_top_two);
1459 : 1151 : EMIT(rot_two);
1460 : : } else {
1461 : 1277 : EMIT(dup_top);
1462 : 1277 : compile_node(comp, pn_end);
1463 : : }
1464 [ - + ]: 2428 : assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
1465 [ + + ]: 2428 : if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
1466 : 2411 : EMIT_ARG(binary_op, MP_BINARY_OP_LESS);
1467 : : } else {
1468 : 17 : EMIT_ARG(binary_op, MP_BINARY_OP_MORE);
1469 : : }
1470 : 2428 : EMIT_ARG(pop_jump_if, true, top_label);
1471 : :
1472 : : // break/continue apply to outer loop (if any) in the else block
1473 : 2428 : 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 : 2428 : uint end_label = 0;
1478 [ + + ]: 2428 : 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 : 2428 : EMIT_ARG(label_assign, break_label);
1491 : :
1492 : : // discard final value of var that failed the loop condition
1493 : 2428 : EMIT(pop_top);
1494 : :
1495 : : // discard <end> value if it's on the stack
1496 [ + + ]: 2428 : if (end_on_stack) {
1497 : 1151 : EMIT(pop_top);
1498 : : }
1499 : :
1500 [ + + ]: 2428 : if (!MP_PARSE_NODE_IS_NULL(pn_else)) {
1501 : 32 : EMIT_ARG(label_assign, end_label);
1502 : : }
1503 : 2428 : }
1504 : :
1505 : 5583 : 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 [ + + + - : 5583 : 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 : 3072 : mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t *)pns->nodes[1];
1511 [ + - ]: 3072 : if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
1512 [ + + ]: 3072 : && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
1513 [ + - ]: 2552 : && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t *)pns_it->nodes[1]) == PN_trailer_paren) {
1514 : 2552 : mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t *)pns_it->nodes[1])->nodes[0];
1515 : 2552 : mp_parse_node_t *args;
1516 : 2552 : size_t n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args);
1517 : 2552 : mp_parse_node_t pn_range_start;
1518 : 2552 : mp_parse_node_t pn_range_end;
1519 : 2552 : mp_parse_node_t pn_range_step;
1520 : 2552 : bool optimize = false;
1521 [ + - ]: 2552 : if (1 <= n_args && n_args <= 3) {
1522 : 2552 : optimize = true;
1523 [ + + ]: 2552 : if (n_args == 1) {
1524 : 1981 : pn_range_start = mp_parse_node_new_small_int(0);
1525 : 1981 : pn_range_end = args[0];
1526 : 1981 : 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 [ + + + + ]: 2552 : 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 [ + + + + ]: 2552 : 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 [ + + ]: 2552 : if (optimize) {
1556 : 2428 : compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1557 : 2428 : return;
1558 : : }
1559 : : }
1560 : : }
1561 : :
1562 : 3155 : START_BREAK_CONTINUE_BLOCK
1563 : 3155 : comp->break_label |= MP_EMIT_BREAK_FROM_FOR;
1564 : :
1565 : 3155 : uint pop_label = comp_next_label(comp);
1566 : :
1567 : 3155 : compile_node(comp, pns->nodes[1]); // iterator
1568 : 3155 : EMIT_ARG(get_iter, true);
1569 : 3155 : EMIT_ARG(label_assign, continue_label);
1570 : 3155 : EMIT_ARG(for_iter, pop_label);
1571 : 3155 : c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1572 : 3155 : compile_node(comp, pns->nodes[2]); // body
1573 : 3155 : EMIT_ARG(jump, continue_label);
1574 : 3155 : EMIT_ARG(label_assign, pop_label);
1575 : 3155 : EMIT(for_iter_end);
1576 : :
1577 : : // break/continue apply to outer loop (if any) in the else block
1578 : 3155 : END_BREAK_CONTINUE_BLOCK
1579 : :
1580 : 3155 : compile_node(comp, pns->nodes[3]); // else (may be empty)
1581 : :
1582 : 3155 : 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 [ + + ]: 1468 : 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 : 48611 : mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1622 [ + + ]: 48611 : if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1623 : 2536 : mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t *)pns_exception_expr;
1624 [ + + ]: 2536 : if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
1625 : : // handler binds the exception to a local
1626 : 1882 : pns_exception_expr = pns3->nodes[0];
1627 : 1882 : qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
1628 : : }
1629 : : }
1630 : 48611 : EMIT(dup_top);
1631 : 48611 : compile_node(comp, pns_exception_expr);
1632 : 48611 : EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
1633 : 48611 : EMIT_ARG(pop_jump_if, false, end_finally_label);
1634 : : }
1635 : :
1636 : : // either discard or store the exception instance
1637 [ + + ]: 48611 : if (qstr_exception_local == 0) {
1638 : 48193 : EMIT(pop_top);
1639 : : } else {
1640 : 1882 : 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 : 1882 : l3 = comp_next_label(comp);
1655 : 1882 : 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 : 1882 : EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1660 : 1882 : EMIT_ARG(label_assign, l3);
1661 : 1882 : EMIT_ARG(adjust_stack_size, 1); // stack adjust for possible return value
1662 : 1882 : EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1663 : 1882 : compile_store_id(comp, qstr_exception_local);
1664 : 1882 : compile_delete_id(comp, qstr_exception_local);
1665 : 1882 : EMIT_ARG(adjust_stack_size, -1);
1666 : 1882 : 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 : 1039 : 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 : 1039 : uint l_finally_block = comp_next_label(comp);
1684 : :
1685 : 1039 : compile_increase_except_level(comp, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY);
1686 : :
1687 [ + + ]: 1039 : if (n_except == 0) {
1688 [ - + ]: 939 : assert(MP_PARSE_NODE_IS_NULL(pn_else));
1689 : 939 : EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state
1690 : 939 : compile_node(comp, pn_body);
1691 : 939 : EMIT_ARG(adjust_stack_size, -3);
1692 : : } else {
1693 : 100 : 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 : 1039 : 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 : 1039 : EMIT_ARG(label_assign, l_finally_block);
1704 : 1039 : EMIT_ARG(adjust_stack_size, 1);
1705 : 1039 : compile_node(comp, pn_finally);
1706 : 1039 : EMIT_ARG(adjust_stack_size, -1);
1707 : :
1708 : 1039 : compile_decrease_except_level(comp);
1709 : 1039 : }
1710 : :
1711 : 50892 : static void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1712 [ + - - + ]: 50892 : assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should be
1713 : : {
1714 : 50892 : mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t *)pns->nodes[1];
1715 [ + + ]: 50892 : if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
1716 : : // just try-finally
1717 : 939 : 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 : 480 : mp_parse_node_t *pn_excepts;
1721 : 480 : size_t n_except = mp_parse_node_extract_list(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
1722 [ + + ]: 480 : if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
1723 : : // no finally
1724 : 380 : compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1725 : : } else {
1726 : : // have finally
1727 : 100 : 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 : 49473 : mp_parse_node_t *pn_excepts;
1732 : 49473 : size_t n_except = mp_parse_node_extract_list(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
1733 : 49473 : compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
1734 : : }
1735 : : }
1736 : 50892 : }
1737 : :
1738 : 73948 : static void compile_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_node_t *nodes, mp_parse_node_t body) {
1739 [ + + ]: 73948 : if (n == 0) {
1740 : : // no more pre-bits, compile the body of the with
1741 : 36974 : compile_node(comp, body);
1742 : : } else {
1743 : 36974 : uint l_end = comp_next_label(comp);
1744 [ + - + + : 73678 : 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 : 270 : compile_node(comp, nodes[0]);
1753 : 270 : compile_increase_except_level(comp, l_end, MP_EMIT_SETUP_BLOCK_WITH);
1754 : 270 : EMIT(pop_top);
1755 : : }
1756 : : // compile additional pre-bits and the body
1757 : 36974 : compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1758 : : // finish this with block
1759 : 36974 : EMIT_ARG(with_cleanup, l_end);
1760 : 36974 : reserve_labels_for_native(comp, 3); // used by native's with_cleanup
1761 : 36974 : compile_decrease_except_level(comp);
1762 : : }
1763 : 73948 : }
1764 : :
1765 : 36974 : 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 : 36974 : mp_parse_node_t *nodes;
1768 : 36974 : size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);
1769 [ - + ]: 36974 : assert(n > 0);
1770 : :
1771 : : // compile in a nested fashion
1772 : 36974 : compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1773 : 36974 : }
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 : 183043 : static void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
2000 : 183043 : mp_parse_node_t pn_rhs = pns->nodes[1];
2001 [ + + ]: 183043 : if (MP_PARSE_NODE_IS_NULL(pn_rhs)) {
2002 [ + + + + ]: 138119 : 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 [ + + + - ]: 137663 : if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
2012 [ + - + + : 137663 : || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
+ - ]
2013 : : // do nothing with a lonely constant
2014 : : } else {
2015 : 137663 : compile_node(comp, pns->nodes[0]); // just an expression
2016 : 137650 : EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
2017 : : }
2018 : : }
2019 [ + + ]: 44924 : } else if (MP_PARSE_NODE_IS_STRUCT(pn_rhs)) {
2020 : 27065 : mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pn_rhs;
2021 : 27065 : int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
2022 [ + + ]: 27065 : 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 [ + + ]: 27045 : } else if (kind == PN_expr_stmt_augassign) {
2039 : 1985 : c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
2040 : 1985 : compile_node(comp, pns1->nodes[1]); // rhs
2041 [ - + ]: 1985 : assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
2042 : 1985 : mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]);
2043 : 1985 : mp_binary_op_t op = MP_BINARY_OP_INPLACE_OR + (tok - MP_TOKEN_DEL_PIPE_EQUAL);
2044 : 1985 : EMIT_ARG(binary_op, op);
2045 : 1985 : c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
2046 [ + + ]: 25060 : } 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 : 24948 : plain_assign:
2062 : : #if MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
2063 [ + - + + : 42815 : 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 : 42738 : compile_node(comp, pn_rhs); // rhs
2107 : 42738 : c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
2108 : : }
2109 : : } else {
2110 : 17859 : 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 : 625 : static void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
2130 [ + + ]: 625 : if (comp->pass == MP_PASS_SCOPE) {
2131 : : // create a new scope for this lambda
2132 : 162 : 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 : 162 : pns->nodes[2] = (mp_parse_node_t)s;
2135 : : }
2136 : :
2137 : : // get the scope for this lambda
2138 : 625 : scope_t *this_scope = (scope_t *)pns->nodes[2];
2139 : :
2140 : : // compile the lambda definition
2141 : 625 : compile_funcdef_lambdef(comp, this_scope, pns->nodes[0], PN_varargslist);
2142 : 625 : }
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 : 558 : static void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
2183 : 558 : bool cond = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test;
2184 : 558 : uint l_end = comp_next_label(comp);
2185 : 558 : int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
2186 [ + + ]: 1674 : for (int i = 0; i < n; i += 1) {
2187 : 1116 : compile_node(comp, pns->nodes[i]);
2188 [ + + ]: 1116 : if (i + 1 < n) {
2189 : 558 : EMIT_ARG(jump_if_or_pop, cond, l_end);
2190 : : }
2191 : : }
2192 : 558 : EMIT_ARG(label_assign, l_end);
2193 : 558 : }
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 : 18329 : static void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
2201 : 18329 : int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
2202 : 18329 : compile_node(comp, pns->nodes[0]);
2203 : 18329 : bool multi = (num_nodes > 3);
2204 : 18329 : uint l_fail = 0;
2205 [ + + ]: 18329 : if (multi) {
2206 : 247 : l_fail = comp_next_label(comp);
2207 : : }
2208 [ + + ]: 36913 : for (int i = 1; i + 1 < num_nodes; i += 2) {
2209 : 18584 : compile_node(comp, pns->nodes[i + 1]);
2210 [ + + ]: 18584 : if (i + 2 < num_nodes) {
2211 : 255 : EMIT(dup_top);
2212 : 255 : EMIT(rot_three);
2213 : : }
2214 [ + + ]: 18584 : if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
2215 : 12082 : mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]);
2216 : 12082 : mp_binary_op_t op;
2217 [ + + ]: 12082 : if (tok == MP_TOKEN_KW_IN) {
2218 : : op = MP_BINARY_OP_IN;
2219 : : } else {
2220 : 10873 : op = MP_BINARY_OP_LESS + (tok - MP_TOKEN_OP_LESS);
2221 : : }
2222 : 12082 : EMIT_ARG(binary_op, op);
2223 : : } else {
2224 [ + - - + ]: 6502 : assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])); // should be
2225 : 6502 : mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t *)pns->nodes[i];
2226 : 6502 : int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
2227 [ + + ]: 6502 : if (kind == PN_comp_op_not_in) {
2228 : 416 : EMIT_ARG(binary_op, MP_BINARY_OP_NOT_IN);
2229 : : } else {
2230 [ - + ]: 6086 : assert(kind == PN_comp_op_is); // should be
2231 [ + + ]: 6086 : if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
2232 : 4310 : EMIT_ARG(binary_op, MP_BINARY_OP_IS);
2233 : : } else {
2234 : 1776 : EMIT_ARG(binary_op, MP_BINARY_OP_IS_NOT);
2235 : : }
2236 : : }
2237 : : }
2238 [ + + ]: 18584 : if (i + 2 < num_nodes) {
2239 : 255 : EMIT_ARG(jump_if_or_pop, false, l_fail);
2240 : : }
2241 : : }
2242 [ + + ]: 18329 : 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 : 18329 : }
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 : 11896 : static void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
2270 : 11896 : int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
2271 : 11896 : compile_node(comp, pns->nodes[0]);
2272 [ + + ]: 24941 : for (int i = 1; i + 1 < num_nodes; i += 2) {
2273 : 13045 : compile_node(comp, pns->nodes[i + 1]);
2274 : 13045 : mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]);
2275 : 13045 : mp_binary_op_t op = MP_BINARY_OP_LSHIFT + (tok - MP_TOKEN_OP_DBL_LESS);
2276 : 13045 : EMIT_ARG(binary_op, op);
2277 : : }
2278 : 11896 : }
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 : 266361 : static void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) {
2294 : : // compile the subject of the expression
2295 : 266361 : compile_node(comp, pns->nodes[0]);
2296 : :
2297 : : // compile_atom_expr_await may call us with a NULL node
2298 [ + + ]: 266362 : 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 : 265958 : size_t num_trail = 1;
2304 : 265958 : mp_parse_node_struct_t **pns_trail = (mp_parse_node_struct_t **)&pns->nodes[1];
2305 [ + + ]: 265958 : if (MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_atom_expr_trailers) {
2306 : 121017 : num_trail = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_trail[0]);
2307 : 121017 : pns_trail = (mp_parse_node_struct_t **)&pns_trail[0]->nodes[0];
2308 : : }
2309 : :
2310 : : // the current index into the array of trailers
2311 : 265958 : size_t i = 0;
2312 : :
2313 : : // handle special super() call
2314 [ + + ]: 265958 : if (comp->scope_cur->kind == SCOPE_FUNCTION
2315 [ + + ]: 62715 : && MP_PARSE_NODE_IS_ID(pns->nodes[0])
2316 [ + + ]: 62130 : && 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 [ + + ]: 265764 : } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])
2359 [ + + ]: 259187 : && 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 [ + + ]: 687412 : for (; i < num_trail; i++) {
2373 [ + + ]: 421470 : if (i + 1 < num_trail
2374 [ + + ]: 199151 : && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i]) == PN_trailer_period
2375 [ + + ]: 94581 : && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i + 1]) == PN_trailer_paren) {
2376 : : // optimisation for method calls a.f(...), following PyPy
2377 : 43999 : mp_parse_node_struct_t *pns_period = pns_trail[i];
2378 : 43999 : mp_parse_node_struct_t *pns_paren = pns_trail[i + 1];
2379 : 43999 : EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false);
2380 : 43999 : compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
2381 : 43999 : i += 1;
2382 : : } else {
2383 : : // node is one of: trailer_paren, trailer_bracket, trailer_period
2384 : 377471 : 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 : 388261 : 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 : 388261 : mp_parse_node_t *args;
2399 : 388261 : 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 : 388261 : int n_positional = n_positional_extra;
2406 : 388261 : uint n_keyword = 0;
2407 : 388261 : uint star_flags = 0;
2408 : 388261 : mp_uint_t star_args = 0;
2409 [ + + ]: 600273 : for (size_t i = 0; i < n_args; i++) {
2410 [ - + + + ]: 212055 : if (MP_PARSE_NODE_IS_STRUCT(args[i])) {
2411 : 82235 : mp_parse_node_struct_t *pns_arg = (mp_parse_node_struct_t *)args[i];
2412 [ + + ]: 82235 : if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_star) {
2413 [ + + ]: 1118 : 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 [ + + ]: 1110 : 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 : 1092 : star_flags |= MP_EMIT_STAR_FLAG_SINGLE;
2429 : 1092 : star_args |= (mp_uint_t)1 << i;
2430 : 1092 : compile_node(comp, pns_arg->nodes[0]);
2431 : 1092 : n_positional++;
2432 [ + + ]: 81117 : } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_dbl_star) {
2433 : 432 : star_flags |= MP_EMIT_STAR_FLAG_DOUBLE;
2434 : : // double-star args are stored as kw arg with key of None
2435 : 432 : EMIT(load_null);
2436 : 432 : compile_node(comp, pns_arg->nodes[0]);
2437 : 432 : n_keyword++;
2438 [ + + ]: 80685 : } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) {
2439 : : #if MICROPY_PY_ASSIGN_EXPR
2440 [ + - + + : 3623 : 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 [ + - + + : 3607 : if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_comp_for)) {
+ + ]
2446 [ + + ]: 3474 : 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 : 3470 : EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]));
2451 : 3470 : compile_node(comp, pns_arg->nodes[1]);
2452 : 3470 : n_keyword++;
2453 : : } else {
2454 : 133 : compile_comprehension(comp, pns_arg, SCOPE_GEN_EXPR);
2455 : 133 : n_positional++;
2456 : : }
2457 : : } else {
2458 : 77062 : goto normal_argument;
2459 : : }
2460 : : } else {
2461 : 129820 : normal_argument:
2462 [ + + ]: 206882 : 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 [ + + ]: 206878 : 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 : 206874 : compile_node(comp, args[i]);
2471 : 206869 : n_positional++;
2472 : : }
2473 : : }
2474 : :
2475 [ + + ]: 388218 : if (star_flags != 0) {
2476 : : // one extra object that contains the star_args map
2477 : 1272 : EMIT_ARG(load_const_small_int, star_args);
2478 : : }
2479 : :
2480 : : // emit the function/method call
2481 [ + + ]: 388218 : if (is_method_call) {
2482 : 44171 : EMIT_ARG(call_method, n_positional, n_keyword, star_flags);
2483 : : } else {
2484 : 344047 : 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 : 843 : static void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
2490 [ - + ]: 843 : assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2491 [ + - + - : 843 : assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
- + ]
2492 : 843 : mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t *)pns->nodes[1];
2493 : :
2494 [ + + ]: 843 : if (comp->pass == MP_PASS_SCOPE) {
2495 : : // create a new scope for this comprehension
2496 : 220 : 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 : 220 : pns_comp_for->nodes[3] = (mp_parse_node_t)s;
2499 : : }
2500 : :
2501 : : // get the scope for this comprehension
2502 : 843 : scope_t *this_scope = (scope_t *)pns_comp_for->nodes[3];
2503 : :
2504 : : // compile the comprehension
2505 : 843 : close_over_variables_etc(comp, this_scope, 0, 0);
2506 : :
2507 : 843 : compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
2508 [ + + ]: 843 : if (kind == SCOPE_GEN_EXPR) {
2509 : 296 : EMIT_ARG(get_iter, false);
2510 : : }
2511 : 843 : EMIT_ARG(call_function, 1, 0, 0);
2512 : 843 : }
2513 : :
2514 : 5078 : static void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2515 [ + + ]: 5078 : if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
2516 : : // an empty tuple
2517 : 826 : EMIT_ARG(build, 0, MP_EMIT_BUILD_TUPLE);
2518 : : } else {
2519 [ + - - + ]: 4252 : assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
2520 : 4252 : pns = (mp_parse_node_struct_t *)pns->nodes[0];
2521 [ + + + - : 4252 : if (MP_PARSE_NODE_TESTLIST_COMP_HAS_COMP_FOR(pns)) {
+ + + + ]
2522 : : // generator expression
2523 : 163 : compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2524 : : } else {
2525 : : // tuple with N items
2526 : 4089 : compile_generic_tuple(comp, pns);
2527 : : }
2528 : : }
2529 : 5078 : }
2530 : :
2531 : 6133 : static void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
2532 [ + + ]: 6133 : if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
2533 : : // empty list
2534 : 1231 : 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 : 6133 : }
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 : 339854 : static void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
2659 : 339854 : compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
2660 : 339841 : }
2661 : :
2662 : 11385 : 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 : 11385 : compile_node(comp, pns->nodes[0]); // the index
2665 : 11385 : EMIT_ARG(subscr, MP_EMIT_SUBSCR_LOAD);
2666 : 11385 : }
2667 : :
2668 : 28037 : 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 : 28037 : EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]), MP_EMIT_ATTR_LOAD); // attribute to get
2671 : 28037 : }
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 : 4225 : static void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
2736 : 4225 : qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
2737 : : // store class object into class name
2738 : 4225 : compile_store_id(comp, cname);
2739 : 4225 : }
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 : 31488 : static mp_obj_t get_const_object(mp_parse_node_struct_t *pns) {
2778 : 31488 : return mp_parse_node_extract_const_object(pns);
2779 : : }
2780 : :
2781 : 31488 : static void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
2782 : 31488 : EMIT_ARG(load_const_obj, get_const_object(pns));
2783 : 31488 : }
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 : 1816101 : static void compile_node(compiler_t *comp, mp_parse_node_t pn) {
2799 [ + + ]: 1816101 : if (MP_PARSE_NODE_IS_NULL(pn)) {
2800 : : // pass
2801 [ + + ]: 1754188 : } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
2802 : 96100 : mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
2803 : 96100 : EMIT_ARG(load_const_small_int, arg);
2804 [ + + ]: 1658088 : } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
2805 : 497623 : uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
2806 [ + + + ]: 497623 : switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
2807 : 416410 : case MP_PARSE_NODE_ID:
2808 : 416410 : compile_load_id(comp, arg);
2809 : 416410 : break;
2810 : 55743 : case MP_PARSE_NODE_STRING:
2811 : 55743 : EMIT_ARG(load_const_str, arg);
2812 : 55743 : break;
2813 : 25470 : case MP_PARSE_NODE_TOKEN:
2814 : : default:
2815 [ + + ]: 25470 : 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 : 18643 : EMIT_ARG(load_const_tok, arg);
2821 : : }
2822 : : break;
2823 : : }
2824 : : } else {
2825 : 1160465 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
2826 : 1160465 : EMIT_ARG(set_source_line, pns->source_line);
2827 [ - + ]: 1160465 : assert(MP_PARSE_NODE_STRUCT_KIND(pns) <= PN_const_object);
2828 : 1160465 : compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
2829 : 1160465 : f(comp, pns);
2830 : : }
2831 : 1816040 : }
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 : 6742 : 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 : 6742 : (void)pn_dbl_star;
2854 : :
2855 : : // check that **kw is last
2856 [ + + ]: 6742 : 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 : 6734 : qstr param_name = MP_QSTRnull;
2862 : 6734 : uint param_flag = ID_FLAG_IS_PARAM;
2863 : 6734 : mp_parse_node_struct_t *pns = NULL;
2864 [ + + ]: 6734 : if (MP_PARSE_NODE_IS_ID(pn)) {
2865 : 5662 : param_name = MP_PARSE_NODE_LEAF_ARG(pn);
2866 [ + + ]: 5662 : 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 : 5634 : comp->scope_cur->num_pos_args += 1;
2872 : : }
2873 : : } else {
2874 [ + - - + ]: 1072 : assert(MP_PARSE_NODE_IS_STRUCT(pn));
2875 : 1072 : pns = (mp_parse_node_struct_t *)pn;
2876 [ + + ]: 1072 : if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2877 : : // named parameter with possible annotation
2878 : 858 : param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2879 [ + + ]: 858 : 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 : 824 : comp->scope_cur->num_pos_args += 1;
2885 : : }
2886 [ + + ]: 214 : } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
2887 [ + + ]: 158 : 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 : 150 : comp->have_star = true;
2893 : 150 : param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM;
2894 [ + + ]: 150 : 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 [ + + ]: 126 : } 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 [ + - - + ]: 106 : assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)); // should be
2906 : : // named star with possible annotation
2907 : 106 : comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
2908 : 106 : pns = (mp_parse_node_struct_t *)pns->nodes[0];
2909 : 106 : param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2910 : : }
2911 : : } else {
2912 : : // double star with possible annotation
2913 [ - + ]: 56 : assert(MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star); // should be
2914 : 56 : param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2915 : 56 : param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM;
2916 : 56 : comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
2917 : : }
2918 : : }
2919 : :
2920 [ + + ]: 6726 : if (param_name != MP_QSTRnull) {
2921 : 6702 : id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, ID_INFO_KIND_UNDECIDED);
2922 [ + + ]: 6702 : 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 : 6698 : id_info->kind = ID_INFO_KIND_LOCAL;
2927 : 6698 : id_info->flags = param_flag;
2928 : :
2929 : : #if MICROPY_EMIT_NATIVE
2930 [ + + + + ]: 6698 : 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 : 6586 : static void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
2940 : 6586 : compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star);
2941 : 6586 : }
2942 : :
2943 : 156 : static void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
2944 : 156 : compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star);
2945 : 156 : }
2946 : :
2947 : 840 : 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 : 840 : uint l_top = comp_next_label(comp);
2949 : 840 : uint l_end = comp_next_label(comp);
2950 : 840 : EMIT_ARG(label_assign, l_top);
2951 : 840 : EMIT_ARG(for_iter, l_end);
2952 : 840 : c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2953 : 840 : mp_parse_node_t pn_iter = pns_comp_for->nodes[2];
2954 : :
2955 : 896 : tail_recursion:
2956 [ + + ]: 896 : if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
2957 : : // no more nested if/for; compile inner expression
2958 : 832 : compile_node(comp, pn_inner_expr);
2959 [ + + ]: 832 : if (comp->scope_cur->kind == SCOPE_GEN_EXPR) {
2960 : 292 : EMIT_ARG(yield, MP_EMIT_YIELD_VALUE);
2961 : 292 : reserve_labels_for_native(comp, 1);
2962 : 292 : 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 : 840 : EMIT_ARG(jump, l_top);
2982 : 840 : EMIT_ARG(label_assign, l_end);
2983 : 840 : EMIT(for_iter_end);
2984 : 840 : }
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 : 40695 : static bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
3032 : 40695 : comp->pass = pass;
3033 : 40695 : comp->scope_cur = scope;
3034 : 40695 : comp->next_label = 0;
3035 : 40695 : mp_emit_common_start_pass(&comp->emit_common, pass);
3036 : 40695 : EMIT_ARG(start_pass, pass, scope);
3037 : 40698 : reserve_labels_for_native(comp, 6); // used by native's start_pass
3038 : :
3039 [ + + ]: 40698 : if (comp->pass == MP_PASS_SCOPE) {
3040 : : // reset maximum stack sizes in scope
3041 : : // they will be computed in this first pass
3042 : 10424 : scope->stack_size = 0;
3043 : 10424 : scope->exc_stack_size = 0;
3044 : : }
3045 : :
3046 : : // compile
3047 [ + - + + : 41932 : 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 [ + + + + : 39464 : } else if (scope->kind == SCOPE_MODULE) {
- + ]
3053 : 13707 : if (!comp->is_repl) {
3054 : 13707 : check_for_doc_string(comp, scope->pn);
3055 : : }
3056 : 13707 : compile_node(comp, scope->pn);
3057 : 13698 : EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
3058 : 13699 : EMIT(return_value);
3059 : : } else if (scope->kind == SCOPE_FUNCTION) {
3060 [ + - - + ]: 20079 : assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
3061 : 20079 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
3062 [ - + ]: 20079 : 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 [ + + ]: 20079 : if (comp->pass == MP_PASS_SCOPE) {
3067 : 5090 : comp->have_star = false;
3068 : 5090 : apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
3069 : :
3070 : : #if MICROPY_EMIT_NATIVE
3071 [ + + ]: 5090 : 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 : 20079 : compile_node(comp, pns->nodes[3]); // 3 is function body
3079 : 20063 : EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
3080 : 20063 : EMIT(return_value);
3081 : : } else if (scope->kind == SCOPE_LAMBDA) {
3082 [ + - - + ]: 624 : assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
3083 : 624 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
3084 [ - + ]: 624 : assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
3085 : :
3086 : : // Set the source line number for the start of the lambda
3087 : 624 : 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 [ + + ]: 624 : if (comp->pass == MP_PASS_SCOPE) {
3092 : 162 : comp->have_star = false;
3093 : 162 : apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
3094 : : }
3095 : :
3096 : 624 : 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 [ + + ]: 624 : 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 : 624 : EMIT(return_value);
3104 : : } else if (SCOPE_IS_COMP_LIKE(scope->kind)) {
3105 : : // a bit of a hack at the moment
3106 : :
3107 [ + - - + ]: 832 : assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
3108 : 832 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
3109 [ - + ]: 832 : assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
3110 [ + - + - : 832 : assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
- + ]
3111 : 832 : 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 : 832 : qstr qstr_arg = MP_QSTR_;
3118 [ + + ]: 832 : if (comp->pass == MP_PASS_SCOPE) {
3119 : 220 : scope_find_or_add_id(comp->scope_cur, qstr_arg, ID_INFO_KIND_LOCAL);
3120 : 220 : scope->num_pos_args = 1;
3121 : : }
3122 : :
3123 : : // Set the source line number for the start of the comprehension
3124 : 832 : EMIT_ARG(set_source_line, pns->source_line);
3125 : :
3126 [ + + ]: 832 : if (scope->kind == SCOPE_LIST_COMP) {
3127 : 460 : EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST);
3128 [ + + ]: 372 : } else if (scope->kind == SCOPE_DICT_COMP) {
3129 : 72 : EMIT_ARG(build, 0, MP_EMIT_BUILD_MAP);
3130 : : #if MICROPY_PY_BUILTINS_SET
3131 [ + + ]: 300 : } 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 [ + + ]: 832 : if (scope->kind == SCOPE_GEN_EXPR) {
3139 : 292 : MP_STATIC_ASSERT(MP_OBJ_ITER_BUF_NSLOTS == 4);
3140 : 292 : EMIT(load_null);
3141 : 292 : compile_load_id(comp, qstr_arg);
3142 : 292 : EMIT(load_null);
3143 : 292 : EMIT(load_null);
3144 : : } else {
3145 : 540 : compile_load_id(comp, qstr_arg);
3146 : 540 : EMIT_ARG(get_iter, true);
3147 : : }
3148 : :
3149 : 832 : compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0);
3150 : :
3151 [ + + ]: 832 : if (scope->kind == SCOPE_GEN_EXPR) {
3152 : 292 : EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
3153 : : }
3154 : 832 : EMIT(return_value);
3155 : : } else {
3156 : 0 : assert(scope->kind == SCOPE_CLASS);
3157 [ + - - + ]: 4222 : assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
3158 : 4222 : mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)scope->pn;
3159 [ - + ]: 4222 : assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
3160 : :
3161 [ + + ]: 4222 : if (comp->pass == MP_PASS_SCOPE) {
3162 : 1057 : 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 : 4222 : compile_load_id(comp, MP_QSTR___name__);
3169 : 4222 : compile_store_id(comp, MP_QSTR___module__);
3170 : 4222 : EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
3171 : 4222 : compile_store_id(comp, MP_QSTR___qualname__);
3172 : :
3173 : 4222 : check_for_doc_string(comp, pns->nodes[2]);
3174 : 4222 : compile_node(comp, pns->nodes[2]); // 2 is class body
3175 : :
3176 : 4222 : id_info_t *id = scope_find(scope, MP_QSTR___class__);
3177 [ - + ]: 4222 : assert(id != NULL);
3178 [ + + ]: 4222 : if (id->kind == ID_INFO_KIND_LOCAL) {
3179 : 4096 : EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
3180 : : } else {
3181 : 126 : EMIT_LOAD_FAST(MP_QSTR___class__, id->local_num);
3182 : : }
3183 : 4222 : EMIT(return_value);
3184 : : }
3185 : :
3186 : 40675 : bool pass_complete = EMIT(end_pass);
3187 : :
3188 : : // make sure we match all the exception levels
3189 [ - + ]: 40675 : assert(comp->cur_except_level == 0);
3190 : :
3191 : 40675 : 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 : 10105 : static void scope_compute_things(scope_t *scope) {
3372 : : // in MicroPython we put the *x parameter after all other parameters (except **y)
3373 [ + + ]: 10105 : if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {
3374 : 110 : id_info_t *id_param = NULL;
3375 [ + - ]: 514 : for (int i = scope->id_info_len - 1; i >= 0; i--) {
3376 : 514 : id_info_t *id = &scope->id_info[i];
3377 [ + + ]: 514 : if (id->flags & ID_FLAG_IS_STAR_PARAM) {
3378 [ + + ]: 110 : 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 [ + + + + ]: 404 : } 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 : 10105 : scope->num_locals = 0;
3394 [ + + ]: 52637 : for (int i = 0; i < scope->id_info_len; i++) {
3395 : 42532 : id_info_t *id = &scope->id_info[i];
3396 [ + + + + ]: 42532 : 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 : 1055 : continue;
3399 : : }
3400 [ + + + + ]: 41477 : if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
3401 : 7802 : id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
3402 : : }
3403 : : #if MICROPY_EMIT_NATIVE
3404 [ + + ]: 41477 : if (id->kind == ID_INFO_KIND_GLOBAL_EXPLICIT) {
3405 : : // This function makes a reference to a global variable
3406 [ + + ]: 8361 : 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 : 8323 : 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 [ + + + + ]: 41477 : if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) {
3416 : 10354 : id->local_num = scope->num_locals++;
3417 : : }
3418 : : }
3419 : :
3420 : : // compute the index of cell vars
3421 [ + + ]: 52637 : for (int i = 0; i < scope->id_info_len; i++) {
3422 : 42532 : 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 [ + + + + ]: 42532 : if (id->kind == ID_INFO_KIND_CELL && !(id->flags & ID_FLAG_IS_PARAM)) {
3427 : 177 : id->local_num = scope->num_locals;
3428 : 177 : 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 [ + + ]: 10105 : if (scope->parent != NULL) {
3435 : : int num_free = 0;
3436 [ + + ]: 83556 : for (int i = 0; i < scope->parent->id_info_len; i++) {
3437 : 77101 : id_info_t *id = &scope->parent->id_info[i];
3438 [ + + ]: 77101 : if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3439 [ + + ]: 2113 : for (int j = 0; j < scope->id_info_len; j++) {
3440 : 1687 : id_info_t *id2 = &scope->id_info[j];
3441 [ + + + + ]: 1687 : if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
3442 [ - + ]: 268 : assert(!(id2->flags & ID_FLAG_IS_PARAM)); // free vars should not be params
3443 : : // in MicroPython the frees come first, before the params
3444 : 268 : id2->local_num = num_free;
3445 : 268 : num_free += 1;
3446 : : }
3447 : : }
3448 : : }
3449 : : }
3450 : : // in MicroPython shift all other locals after the free locals
3451 [ + + ]: 6455 : if (num_free > 0) {
3452 [ + + ]: 855 : for (int i = 0; i < scope->id_info_len; i++) {
3453 : 679 : id_info_t *id = &scope->id_info[i];
3454 [ + + - + ]: 679 : if (id->kind != ID_INFO_KIND_FREE || (id->flags & ID_FLAG_IS_PARAM)) {
3455 : 411 : id->local_num += num_free;
3456 : : }
3457 : : }
3458 : 176 : scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function
3459 : 176 : scope->num_locals += num_free;
3460 : : }
3461 : : }
3462 : 10105 : }
3463 : :
3464 : : #if !MICROPY_PERSISTENT_CODE_SAVE
3465 : : static
3466 : : #endif
3467 : 3895 : 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 : 3895 : compiler_t comp_state = {0};
3470 : 3895 : compiler_t *comp = &comp_state;
3471 : :
3472 : 3895 : comp->is_repl = is_repl;
3473 : 3895 : comp->break_label = INVALID_LABEL;
3474 : 3895 : comp->continue_label = INVALID_LABEL;
3475 : 3895 : mp_emit_common_init(&comp->emit_common, source_file);
3476 : :
3477 : : // create the module scope
3478 : : #if MICROPY_EMIT_NATIVE
3479 : 3895 : const uint emit_opt = MP_STATE_VM(default_emit_opt);
3480 : : #else
3481 : : const uint emit_opt = MP_EMIT_OPT_NONE;
3482 : : #endif
3483 : 3895 : 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 : 3895 : emit_t *emit_bc = emit_bc_new(&comp->emit_common);
3487 : :
3488 : : // compile MP_PASS_SCOPE
3489 : 3895 : comp->emit = emit_bc;
3490 : : #if MICROPY_EMIT_NATIVE
3491 : 3895 : comp->emit_method_table = &emit_bc_method_table;
3492 : : #endif
3493 : 3895 : uint max_num_labels = 0;
3494 [ + + + + ]: 14315 : 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 : 10424 : compile_scope(comp, s, MP_PASS_SCOPE);
3502 : :
3503 : : // Check if any implicitly declared variables should be closed over
3504 [ + + ]: 53224 : for (size_t i = 0; i < s->id_info_len; ++i) {
3505 : 42800 : id_info_t *id = &s->id_info[i];
3506 [ + + ]: 42800 : if (id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
3507 : 17210 : scope_check_to_close_over(s, id);
3508 : : }
3509 : : }
3510 : : }
3511 : :
3512 : : // update maximum number of labels needed
3513 [ + + ]: 10420 : if (comp->next_label > max_num_labels) {
3514 : 3198 : max_num_labels = comp->next_label;
3515 : : }
3516 : : }
3517 : :
3518 : : // compute some things related to scope and identifiers
3519 [ + + + + ]: 13996 : for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
3520 : 10105 : scope_compute_things(s);
3521 : : }
3522 : :
3523 : : // set max number of labels now that it's calculated
3524 : 3891 : 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 : 3891 : emit_t *emit_native = NULL;
3529 : : #endif
3530 [ + + + + ]: 13978 : 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 [ + + ]: 10105 : switch (s->emit_options) {
3561 : :
3562 : : #if MICROPY_EMIT_NATIVE
3563 : 4691 : case MP_EMIT_OPT_NATIVE_PYTHON:
3564 : : case MP_EMIT_OPT_VIPER:
3565 [ + + ]: 4691 : if (emit_native == NULL) {
3566 : 1483 : emit_native = NATIVE_EMITTER(new)(&comp->emit_common, &comp->compile_error, &comp->next_label, max_num_labels);
3567 : : }
3568 : 4691 : comp->emit_method_table = NATIVE_EMITTER_TABLE;
3569 : 4691 : comp->emit = emit_native;
3570 : 4691 : break;
3571 : : #endif // MICROPY_EMIT_NATIVE
3572 : :
3573 : 5414 : default:
3574 : 5414 : comp->emit = emit_bc;
3575 : : #if MICROPY_EMIT_NATIVE
3576 : 5414 : comp->emit_method_table = &emit_bc_method_table;
3577 : : #endif
3578 : 5414 : break;
3579 : : }
3580 : :
3581 : : // need a pass to compute stack size
3582 : 10105 : compile_scope(comp, s, MP_PASS_STACK_SIZE);
3583 : :
3584 : : // second last pass: compute code size
3585 [ + + ]: 10088 : if (comp->compile_error == MP_OBJ_NULL) {
3586 : 10012 : 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 [ + + ]: 10089 : if (comp->compile_error == MP_OBJ_NULL) {
3592 [ + + ]: 10154 : while (!compile_scope(comp, s, MP_PASS_EMIT)) {
3593 : 10156 : }
3594 : : }
3595 : : }
3596 : : }
3597 : :
3598 [ + + ]: 3873 : 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 : 3873 : 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 [ + + ]: 3873 : if (comp->compile_error == MP_OBJ_NULL) {
3625 : 3556 : 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 [ + + ]: 3556 : 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 : 3873 : emit_bc_free(emit_bc);
3643 : : #if MICROPY_EMIT_NATIVE
3644 [ + + ]: 3873 : if (emit_native != NULL) {
3645 : 1467 : 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 : 3873 : mp_parse_tree_clear(parse_tree);
3656 : :
3657 : : // free the scopes
3658 [ + + ]: 14276 : for (scope_t *s = module_scope; s;) {
3659 : 10403 : scope_t *next = s->next;
3660 : 10403 : scope_free(s);
3661 : 10403 : s = next;
3662 : : }
3663 : :
3664 [ + + ]: 3873 : if (comp->compile_error != MP_OBJ_NULL) {
3665 : 317 : nlr_raise(comp->compile_error);
3666 : : }
3667 : 3556 : }
3668 : :
3669 : 3895 : mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) {
3670 : 3895 : mp_compiled_module_t cm;
3671 : 3895 : cm.context = m_new_obj(mp_module_context_t);
3672 : 3895 : cm.context->module.globals = mp_globals_get();
3673 : 3895 : mp_compile_to_raw_code(parse_tree, source_file, is_repl, &cm);
3674 : : // return function that executes the outer module
3675 : 3556 : return mp_make_function_from_proto_fun(cm.rc, cm.context, NULL);
3676 : : }
3677 : :
3678 : : #endif // MICROPY_ENABLE_COMPILER
|