blob: 4e704abfbbadd27831d5897225fcd4d7c246b613 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
Alexander Steffen55f33242017-06-30 09:22:17 +02002 * This file is part of the MicroPython project, http://micropython.org/
Damien George04b91472014-05-03 23:27:38 +01003 *
4 * The MIT License (MIT)
5 *
Damien George9d5e5c02015-09-24 13:15:57 +01006 * Copyright (c) 2013-2015 Damien P. George
Damien George04b91472014-05-03 23:27:38 +01007 *
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
xbeefe34222014-03-16 00:14:26 -070027#include <stdbool.h>
Damien429d7192013-10-04 19:53:11 +010028#include <stdint.h>
29#include <stdio.h>
30#include <string.h>
31#include <assert.h>
32
Damien George51dfcb42015-01-01 20:27:54 +000033#include "py/scope.h"
34#include "py/emit.h"
35#include "py/compile.h"
Damien George51dfcb42015-01-01 20:27:54 +000036#include "py/runtime.h"
Damien Georgedd53b122016-12-09 20:54:54 +110037#include "py/asmbase.h"
Damien429d7192013-10-04 19:53:11 +010038
Damien Georgedd5353a2015-12-18 12:35:44 +000039#if MICROPY_ENABLE_COMPILER
40
Damien429d7192013-10-04 19:53:11 +010041// TODO need to mangle __attr names
42
Damien Georged94bc672017-06-22 15:05:58 +100043#define INVALID_LABEL (0xffff)
44
Damien429d7192013-10-04 19:53:11 +010045typedef enum {
Damien George71019ae2017-02-15 10:58:05 +110046// define rules with a compile function
Damien George00208ce2014-01-23 00:00:53 +000047#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
Damien George71019ae2017-02-15 10:58:05 +110048#define DEF_RULE_NC(rule, kind, ...)
Damien George51dfcb42015-01-01 20:27:54 +000049#include "py/grammar.h"
Damien429d7192013-10-04 19:53:11 +010050#undef DEF_RULE
Damien George71019ae2017-02-15 10:58:05 +110051#undef DEF_RULE_NC
Damien George7d414a12015-02-08 01:57:40 +000052 PN_const_object, // special node for a constant, generic Python object
Damien George71019ae2017-02-15 10:58:05 +110053// define rules without a compile function
54#define DEF_RULE(rule, comp, kind, ...)
55#define DEF_RULE_NC(rule, kind, ...) PN_##rule,
56#include "py/grammar.h"
57#undef DEF_RULE
58#undef DEF_RULE_NC
Damien429d7192013-10-04 19:53:11 +010059} pn_kind_t;
60
Damien George65dc9602015-08-14 12:24:11 +010061#define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE
Damien George41125902015-03-26 16:44:14 +000062
63#if NEED_METHOD_TABLE
64
65// we need a method table to do the lookup for the emitter functions
Damien Georgeb9791222014-01-23 00:34:21 +000066#define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
67#define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
Damien George542bd6b2015-03-26 14:42:40 +000068#define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.fast(comp->emit, qst, local_num))
69#define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst))
Damien429d7192013-10-04 19:53:11 +010070
Damien George41125902015-03-26 16:44:14 +000071#else
72
73// if we only have the bytecode emitter enabled then we can do a direct call to the functions
74#define EMIT(fun) (mp_emit_bc_##fun(comp->emit))
75#define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__))
76#define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_fast(comp->emit, qst, local_num))
77#define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst))
78
79#endif
80
Damien George080a78b2016-12-07 11:17:17 +110081#if MICROPY_EMIT_NATIVE
82// define a macro to access external native emitter
83#if MICROPY_EMIT_X64
84#define NATIVE_EMITTER(f) emit_native_x64_##f
85#elif MICROPY_EMIT_X86
86#define NATIVE_EMITTER(f) emit_native_x86_##f
87#elif MICROPY_EMIT_THUMB
88#define NATIVE_EMITTER(f) emit_native_thumb_##f
89#elif MICROPY_EMIT_ARM
90#define NATIVE_EMITTER(f) emit_native_arm_##f
Damien George8e5aced2016-12-09 16:39:39 +110091#elif MICROPY_EMIT_XTENSA
92#define NATIVE_EMITTER(f) emit_native_xtensa_##f
Damien George080a78b2016-12-07 11:17:17 +110093#else
94#error "unknown native emitter"
95#endif
96#endif
97
Damien Georgead297a12016-12-09 13:17:49 +110098#if MICROPY_EMIT_INLINE_ASM
99// define macros for inline assembler
100#if MICROPY_EMIT_INLINE_THUMB
101#define ASM_DECORATOR_QSTR MP_QSTR_asm_thumb
102#define ASM_EMITTER(f) emit_inline_thumb_##f
Damien Georgef76b1bf2016-12-09 17:03:33 +1100103#elif MICROPY_EMIT_INLINE_XTENSA
104#define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa
105#define ASM_EMITTER(f) emit_inline_xtensa_##f
Damien Georgead297a12016-12-09 13:17:49 +1100106#else
107#error "unknown asm emitter"
108#endif
109#endif
110
Damien George0496de22015-10-03 17:07:54 +0100111#define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
112#define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
113
Damien Georgea91ac202014-10-05 19:01:34 +0100114// elements in this struct are ordered to make it compact
Damien429d7192013-10-04 19:53:11 +0100115typedef struct _compiler_t {
Damien Georgecbd2f742014-01-19 11:48:48 +0000116 qstr source_file;
Damien Georgea91ac202014-10-05 19:01:34 +0100117
Damien George78035b92014-04-09 12:27:39 +0100118 uint8_t is_repl;
119 uint8_t pass; // holds enum type pass_kind_t
Damien Georgea91ac202014-10-05 19:01:34 +0100120 uint8_t have_star;
121
122 // try to keep compiler clean from nlr
Damien Georgecfc4c332015-07-29 22:16:01 +0000123 mp_obj_t compile_error; // set to an exception object if there's an error
Damien George831137b2015-12-17 13:13:18 +0000124 size_t compile_error_line; // set to best guess of line of error
Damien429d7192013-10-04 19:53:11 +0100125
Damien George6f355fd2014-04-10 14:11:31 +0100126 uint next_label;
Damienb05d7072013-10-05 13:37:10 +0100127
Damien George69b89d22014-04-11 13:38:30 +0000128 uint16_t num_dict_params;
129 uint16_t num_default_params;
Damien429d7192013-10-04 19:53:11 +0100130
Damien Georgea91ac202014-10-05 19:01:34 +0100131 uint16_t break_label; // highest bit set indicates we are breaking out of a for loop
132 uint16_t continue_label;
133 uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
Damien George090c9232014-10-17 14:08:49 +0000134 uint16_t break_continue_except_level;
Damien Georgea91ac202014-10-05 19:01:34 +0100135
Damien429d7192013-10-04 19:53:11 +0100136 scope_t *scope_head;
137 scope_t *scope_cur;
138
Damien6cdd3af2013-10-05 18:08:26 +0100139 emit_t *emit; // current emitter
Damien George41125902015-03-26 16:44:14 +0000140 #if NEED_METHOD_TABLE
Damien6cdd3af2013-10-05 18:08:26 +0100141 const emit_method_table_t *emit_method_table; // current emit method table
Damien George41125902015-03-26 16:44:14 +0000142 #endif
Damien826005c2013-10-05 23:17:28 +0100143
Damien Georgead297a12016-12-09 13:17:49 +1100144 #if MICROPY_EMIT_INLINE_ASM
Damien826005c2013-10-05 23:17:28 +0100145 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
146 const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
Damien Georgea77ffe62015-03-14 12:59:31 +0000147 #endif
Damien429d7192013-10-04 19:53:11 +0100148} compiler_t;
149
Damien Georgecfc4c332015-07-29 22:16:01 +0000150STATIC void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) {
151 // if the line of the error is unknown then try to update it from the pn
152 if (comp->compile_error_line == 0 && MP_PARSE_NODE_IS_STRUCT(pn)) {
Damien George831137b2015-12-17 13:13:18 +0000153 comp->compile_error_line = ((mp_parse_node_struct_t*)pn)->source_line;
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100154 }
Damien George84d59c22015-07-27 22:20:00 +0100155}
156
157STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
Damien Georgecfc4c332015-07-29 22:16:01 +0000158 // only register the error if there has been no other error
159 if (comp->compile_error == MP_OBJ_NULL) {
160 comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
161 compile_error_set_line(comp, pn);
162 }
Damien Georgef41fdd02014-03-03 23:19:11 +0000163}
164
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200165STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
Damien George6be0b0a2014-08-15 14:30:52 +0100166STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind);
Damien George8dcc0c72014-03-27 10:55:21 +0000167STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn);
Damien429d7192013-10-04 19:53:11 +0100168
Damien George6f355fd2014-04-10 14:11:31 +0100169STATIC uint comp_next_label(compiler_t *comp) {
Damienb05d7072013-10-05 13:37:10 +0100170 return comp->next_label++;
171}
172
Damien George8dcc0c72014-03-27 10:55:21 +0000173STATIC void compile_increase_except_level(compiler_t *comp) {
174 comp->cur_except_level += 1;
175 if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {
176 comp->scope_cur->exc_stack_size = comp->cur_except_level;
177 }
178}
179
180STATIC void compile_decrease_except_level(compiler_t *comp) {
181 assert(comp->cur_except_level > 0);
182 comp->cur_except_level -= 1;
183}
184
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200185STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
Damien Georgedf8127a2014-04-13 11:04:33 +0100186 scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options);
Damien429d7192013-10-04 19:53:11 +0100187 scope->parent = comp->scope_cur;
188 scope->next = NULL;
189 if (comp->scope_head == NULL) {
190 comp->scope_head = scope;
191 } else {
192 scope_t *s = comp->scope_head;
193 while (s->next != NULL) {
194 s = s->next;
195 }
196 s->next = scope;
197 }
198 return scope;
199}
200
Damien George91bc32d2015-04-09 15:31:53 +0000201typedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn);
202
203STATIC 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) {
Damien George963a5a32015-01-16 17:47:07 +0000204 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) {
Damiend99b0522013-12-21 18:17:45 +0000205 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
206 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100207 for (int i = 0; i < num_nodes; i++) {
208 f(comp, pns->nodes[i]);
209 }
Damiend99b0522013-12-21 18:17:45 +0000210 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +0100211 f(comp, pn);
212 }
213}
214
Damien George969a6b32014-12-10 22:07:04 +0000215STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +0000216 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +0100217 for (int i = 0; i < num_nodes; i++) {
218 compile_node(comp, pns->nodes[i]);
Damien Georgecfc4c332015-07-29 22:16:01 +0000219 if (comp->compile_error != MP_OBJ_NULL) {
220 // add line info for the error in case it didn't have a line number
221 compile_error_set_line(comp, pns->nodes[i]);
222 return;
223 }
Damien429d7192013-10-04 19:53:11 +0100224 }
225}
226
Damien George542bd6b2015-03-26 14:42:40 +0000227STATIC void compile_load_id(compiler_t *comp, qstr qst) {
228 if (comp->pass == MP_PASS_SCOPE) {
229 mp_emit_common_get_id_for_load(comp->scope_cur, qst);
230 } else {
Damien George41125902015-03-26 16:44:14 +0000231 #if NEED_METHOD_TABLE
Damien George542bd6b2015-03-26 14:42:40 +0000232 mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst);
Damien George41125902015-03-26 16:44:14 +0000233 #else
234 mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_load_id_ops, comp->scope_cur, qst);
235 #endif
Damien George542bd6b2015-03-26 14:42:40 +0000236 }
237}
238
239STATIC void compile_store_id(compiler_t *comp, qstr qst) {
240 if (comp->pass == MP_PASS_SCOPE) {
241 mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
242 } else {
Damien George41125902015-03-26 16:44:14 +0000243 #if NEED_METHOD_TABLE
Damien George542bd6b2015-03-26 14:42:40 +0000244 mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst);
Damien George41125902015-03-26 16:44:14 +0000245 #else
246 mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_store_id_ops, comp->scope_cur, qst);
247 #endif
Damien George542bd6b2015-03-26 14:42:40 +0000248 }
249}
250
251STATIC void compile_delete_id(compiler_t *comp, qstr qst) {
252 if (comp->pass == MP_PASS_SCOPE) {
253 mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
254 } else {
Damien George41125902015-03-26 16:44:14 +0000255 #if NEED_METHOD_TABLE
Damien George542bd6b2015-03-26 14:42:40 +0000256 mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst);
Damien George41125902015-03-26 16:44:14 +0000257 #else
258 mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_delete_id_ops, comp->scope_cur, qst);
259 #endif
Damien George542bd6b2015-03-26 14:42:40 +0000260 }
261}
262
Damien George2c0842b2014-04-27 16:46:51 +0100263STATIC void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
Damien3a205172013-10-12 15:01:56 +0100264 int total = 0;
Damiend99b0522013-12-21 18:17:45 +0000265 if (!MP_PARSE_NODE_IS_NULL(pn)) {
Damien3a205172013-10-12 15:01:56 +0100266 compile_node(comp, pn);
267 total += 1;
268 }
269 if (pns_list != NULL) {
Damiend99b0522013-12-21 18:17:45 +0000270 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
Damien3a205172013-10-12 15:01:56 +0100271 for (int i = 0; i < n; i++) {
272 compile_node(comp, pns_list->nodes[i]);
273 }
274 total += n;
275 }
Damien Georgeb9791222014-01-23 00:34:21 +0000276 EMIT_ARG(build_tuple, total);
Damien3a205172013-10-12 15:01:56 +0100277}
Damien429d7192013-10-04 19:53:11 +0100278
Damien George969a6b32014-12-10 22:07:04 +0000279STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100280 // a simple tuple expression
Damiend99b0522013-12-21 18:17:45 +0000281 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +0100282}
283
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200284STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
Damien Georgeb0cbfb02016-11-13 15:32:05 +1100285 if (mp_parse_node_is_const_false(pn)) {
Damien3a205172013-10-12 15:01:56 +0100286 if (jump_if == false) {
Damien Georgeb9791222014-01-23 00:34:21 +0000287 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100288 }
289 return;
Damien Georgeb0cbfb02016-11-13 15:32:05 +1100290 } else if (mp_parse_node_is_const_true(pn)) {
Damien3a205172013-10-12 15:01:56 +0100291 if (jump_if == true) {
Damien Georgeb9791222014-01-23 00:34:21 +0000292 EMIT_ARG(jump, label);
Damien3a205172013-10-12 15:01:56 +0100293 }
294 return;
Damiend99b0522013-12-21 18:17:45 +0000295 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
296 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
297 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
298 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
Damien3a205172013-10-12 15:01:56 +0100299 if (jump_if == false) {
Damien George0b2fd912015-02-28 14:37:54 +0000300 and_or_logic1:;
Damien George6f355fd2014-04-10 14:11:31 +0100301 uint label2 = comp_next_label(comp);
Damien3a205172013-10-12 15:01:56 +0100302 for (int i = 0; i < n - 1; i++) {
Damien George0b2fd912015-02-28 14:37:54 +0000303 c_if_cond(comp, pns->nodes[i], !jump_if, label2);
Damien3a205172013-10-12 15:01:56 +0100304 }
Damien George0b2fd912015-02-28 14:37:54 +0000305 c_if_cond(comp, pns->nodes[n - 1], jump_if, label);
Damien Georgeb9791222014-01-23 00:34:21 +0000306 EMIT_ARG(label_assign, label2);
Damien3a205172013-10-12 15:01:56 +0100307 } else {
Damien George0b2fd912015-02-28 14:37:54 +0000308 and_or_logic2:
Damien3a205172013-10-12 15:01:56 +0100309 for (int i = 0; i < n; i++) {
Damien George0b2fd912015-02-28 14:37:54 +0000310 c_if_cond(comp, pns->nodes[i], jump_if, label);
Damien3a205172013-10-12 15:01:56 +0100311 }
312 }
313 return;
Damiend99b0522013-12-21 18:17:45 +0000314 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
Damien3a205172013-10-12 15:01:56 +0100315 if (jump_if == false) {
Damien George0b2fd912015-02-28 14:37:54 +0000316 goto and_or_logic2;
Damien3a205172013-10-12 15:01:56 +0100317 } else {
Damien George0b2fd912015-02-28 14:37:54 +0000318 goto and_or_logic1;
Damien3a205172013-10-12 15:01:56 +0100319 }
Damiend99b0522013-12-21 18:17:45 +0000320 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
Damien3a205172013-10-12 15:01:56 +0100321 c_if_cond(comp, pns->nodes[0], !jump_if, label);
322 return;
Damien Georgeeb4e18f2014-08-29 20:04:01 +0100323 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_atom_paren) {
324 // cond is something in parenthesis
325 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
326 // empty tuple, acts as false for the condition
327 if (jump_if == false) {
328 EMIT_ARG(jump, label);
329 }
Damien George93b37262016-01-07 13:07:52 +0000330 } else {
331 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
Damien Georgeeb4e18f2014-08-29 20:04:01 +0100332 // non-empty tuple, acts as true for the condition
333 if (jump_if == true) {
334 EMIT_ARG(jump, label);
335 }
Damien Georgeeb4e18f2014-08-29 20:04:01 +0100336 }
337 return;
Damien3a205172013-10-12 15:01:56 +0100338 }
339 }
340
341 // nothing special, fall back to default compiling for node and jump
342 compile_node(comp, pn);
Damien George63f38322015-02-28 15:04:06 +0000343 EMIT_ARG(pop_jump_if, jump_if, label);
Damien429d7192013-10-04 19:53:11 +0100344}
345
346typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
Damien George6be0b0a2014-08-15 14:30:52 +0100347STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
Damien429d7192013-10-04 19:53:11 +0100348
pohmelie81ebba72016-01-27 23:23:11 +0300349STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
Damien429d7192013-10-04 19:53:11 +0100350 if (assign_kind != ASSIGN_AUG_STORE) {
351 compile_node(comp, pns->nodes[0]);
352 }
353
Damiend99b0522013-12-21 18:17:45 +0000354 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
355 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pohmelie81ebba72016-01-27 23:23:11 +0300356 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) {
Damiend99b0522013-12-21 18:17:45 +0000357 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100358 if (assign_kind != ASSIGN_AUG_STORE) {
359 for (int i = 0; i < n - 1; i++) {
360 compile_node(comp, pns1->nodes[i]);
361 }
362 }
Damiend99b0522013-12-21 18:17:45 +0000363 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
364 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100365 }
Damien Georgeaedf5832015-03-25 22:06:47 +0000366 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100367 if (assign_kind == ASSIGN_AUG_STORE) {
368 EMIT(rot_three);
369 EMIT(store_subscr);
370 } else {
371 compile_node(comp, pns1->nodes[0]);
372 if (assign_kind == ASSIGN_AUG_LOAD) {
373 EMIT(dup_top_two);
Damien George729f7b42014-04-17 22:10:53 +0100374 EMIT(load_subscr);
Damien429d7192013-10-04 19:53:11 +0100375 } else {
376 EMIT(store_subscr);
377 }
378 }
Damiend99b0522013-12-21 18:17:45 +0000379 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
380 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100381 if (assign_kind == ASSIGN_AUG_LOAD) {
382 EMIT(dup_top);
Damien Georgeb9791222014-01-23 00:34:21 +0000383 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100384 } else {
385 if (assign_kind == ASSIGN_AUG_STORE) {
386 EMIT(rot_two);
387 }
Damien Georgeb9791222014-01-23 00:34:21 +0000388 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100389 }
390 } else {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100391 goto cannot_assign;
Damien429d7192013-10-04 19:53:11 +0100392 }
393 } else {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100394 goto cannot_assign;
Damien429d7192013-10-04 19:53:11 +0100395 }
396
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100397 return;
398
399cannot_assign:
400 compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
Damien429d7192013-10-04 19:53:11 +0100401}
402
Damien George0288cf02014-04-11 11:53:00 +0000403// we need to allow for a caller passing in 1 initial node (node_head) followed by an array of nodes (nodes_tail)
Damien George6be0b0a2014-08-15 14:30:52 +0100404STATIC void c_assign_tuple(compiler_t *comp, mp_parse_node_t node_head, uint num_tail, mp_parse_node_t *nodes_tail) {
Damien George0288cf02014-04-11 11:53:00 +0000405 uint num_head = (node_head == MP_PARSE_NODE_NULL) ? 0 : 1;
406
407 // look for star expression
Damien George963a5a32015-01-16 17:47:07 +0000408 uint have_star_index = -1;
Damien George0288cf02014-04-11 11:53:00 +0000409 if (num_head != 0 && MP_PARSE_NODE_IS_STRUCT_KIND(node_head, PN_star_expr)) {
410 EMIT_ARG(unpack_ex, 0, num_tail);
411 have_star_index = 0;
412 }
Damien George963a5a32015-01-16 17:47:07 +0000413 for (uint i = 0; i < num_tail; i++) {
Damien George0288cf02014-04-11 11:53:00 +0000414 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {
Damien George963a5a32015-01-16 17:47:07 +0000415 if (have_star_index == (uint)-1) {
Damien George0288cf02014-04-11 11:53:00 +0000416 EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1);
417 have_star_index = num_head + i;
Damien429d7192013-10-04 19:53:11 +0100418 } else {
Damien George9d181f62014-04-27 16:55:27 +0100419 compile_syntax_error(comp, nodes_tail[i], "multiple *x in assignment");
Damien429d7192013-10-04 19:53:11 +0100420 return;
421 }
422 }
423 }
Damien George963a5a32015-01-16 17:47:07 +0000424 if (have_star_index == (uint)-1) {
Damien George0288cf02014-04-11 11:53:00 +0000425 EMIT_ARG(unpack_sequence, num_head + num_tail);
Damien429d7192013-10-04 19:53:11 +0100426 }
Damien George0288cf02014-04-11 11:53:00 +0000427 if (num_head != 0) {
428 if (0 == have_star_index) {
429 c_assign(comp, ((mp_parse_node_struct_t*)node_head)->nodes[0], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100430 } else {
Damien George0288cf02014-04-11 11:53:00 +0000431 c_assign(comp, node_head, ASSIGN_STORE);
432 }
433 }
Damien George963a5a32015-01-16 17:47:07 +0000434 for (uint i = 0; i < num_tail; i++) {
Damien George0288cf02014-04-11 11:53:00 +0000435 if (num_head + i == have_star_index) {
436 c_assign(comp, ((mp_parse_node_struct_t*)nodes_tail[i])->nodes[0], ASSIGN_STORE);
437 } else {
438 c_assign(comp, nodes_tail[i], ASSIGN_STORE);
Damien429d7192013-10-04 19:53:11 +0100439 }
440 }
441}
442
443// assigns top of stack to pn
Damien George6be0b0a2014-08-15 14:30:52 +0100444STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
Damien Georgeaedf5832015-03-25 22:06:47 +0000445 assert(!MP_PARSE_NODE_IS_NULL(pn));
446 if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damiend99b0522013-12-21 18:17:45 +0000447 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien George42f3de92014-10-03 17:44:14 +0000448 qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +0100449 switch (assign_kind) {
450 case ASSIGN_STORE:
451 case ASSIGN_AUG_STORE:
Damien George542bd6b2015-03-26 14:42:40 +0000452 compile_store_id(comp, arg);
Damien429d7192013-10-04 19:53:11 +0100453 break;
454 case ASSIGN_AUG_LOAD:
Damien Georged2d64f02015-01-14 21:32:42 +0000455 default:
Damien George542bd6b2015-03-26 14:42:40 +0000456 compile_load_id(comp, arg);
Damien429d7192013-10-04 19:53:11 +0100457 break;
458 }
459 } else {
Damien Georgef55a0592017-03-29 12:28:33 +1100460 goto cannot_assign;
Damien429d7192013-10-04 19:53:11 +0100461 }
462 } else {
Damien Georgeaedf5832015-03-25 22:06:47 +0000463 // pn must be a struct
Damiend99b0522013-12-21 18:17:45 +0000464 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
465 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
pohmelie81ebba72016-01-27 23:23:11 +0300466 case PN_atom_expr_normal:
Damien429d7192013-10-04 19:53:11 +0100467 // lhs is an index or attribute
pohmelie81ebba72016-01-27 23:23:11 +0300468 c_assign_atom_expr(comp, pns, assign_kind);
Damien429d7192013-10-04 19:53:11 +0100469 break;
470
471 case PN_testlist_star_expr:
472 case PN_exprlist:
473 // lhs is a tuple
474 if (assign_kind != ASSIGN_STORE) {
Damien Georgef55a0592017-03-29 12:28:33 +1100475 goto cannot_assign;
Damien429d7192013-10-04 19:53:11 +0100476 }
Damien George0288cf02014-04-11 11:53:00 +0000477 c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100478 break;
479
480 case PN_atom_paren:
481 // lhs is something in parenthesis
Damiend99b0522013-12-21 18:17:45 +0000482 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100483 // empty tuple
Damien George9d181f62014-04-27 16:55:27 +0100484 goto cannot_assign;
Damien George93b37262016-01-07 13:07:52 +0000485 } else {
486 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
Damien George44f65c02015-03-25 23:06:48 +0000487 if (assign_kind != ASSIGN_STORE) {
Damien Georgef55a0592017-03-29 12:28:33 +1100488 goto cannot_assign;
Damien George44f65c02015-03-25 23:06:48 +0000489 }
Damiend99b0522013-12-21 18:17:45 +0000490 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100491 goto testlist_comp;
Damien429d7192013-10-04 19:53:11 +0100492 }
493 break;
494
495 case PN_atom_bracket:
496 // lhs is something in brackets
497 if (assign_kind != ASSIGN_STORE) {
Damien Georgef55a0592017-03-29 12:28:33 +1100498 goto cannot_assign;
Damien429d7192013-10-04 19:53:11 +0100499 }
Damiend99b0522013-12-21 18:17:45 +0000500 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100501 // empty list, assignment allowed
Damien George0288cf02014-04-11 11:53:00 +0000502 c_assign_tuple(comp, MP_PARSE_NODE_NULL, 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000503 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
504 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +0100505 goto testlist_comp;
506 } else {
507 // brackets around 1 item
Damien George0288cf02014-04-11 11:53:00 +0000508 c_assign_tuple(comp, pns->nodes[0], 0, NULL);
Damien429d7192013-10-04 19:53:11 +0100509 }
510 break;
511
512 default:
Damien George9d181f62014-04-27 16:55:27 +0100513 goto cannot_assign;
Damien429d7192013-10-04 19:53:11 +0100514 }
515 return;
516
517 testlist_comp:
518 // lhs is a sequence
Damiend99b0522013-12-21 18:17:45 +0000519 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
520 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
521 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100522 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000523 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien George0288cf02014-04-11 11:53:00 +0000524 c_assign_tuple(comp, pns->nodes[0], 0, NULL);
Damiend99b0522013-12-21 18:17:45 +0000525 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100526 // sequence of many items
Damien George0288cf02014-04-11 11:53:00 +0000527 uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
528 c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes);
Damien George216a7112016-09-30 14:48:06 +1000529 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien George9d181f62014-04-27 16:55:27 +0100530 goto cannot_assign;
Damien429d7192013-10-04 19:53:11 +0100531 } else {
532 // sequence with 2 items
533 goto sequence_with_2_items;
534 }
535 } else {
536 // sequence with 2 items
537 sequence_with_2_items:
Damien George0288cf02014-04-11 11:53:00 +0000538 c_assign_tuple(comp, MP_PARSE_NODE_NULL, 2, pns->nodes);
Damien429d7192013-10-04 19:53:11 +0100539 }
540 return;
541 }
542 return;
543
Damien George9d181f62014-04-27 16:55:27 +0100544 cannot_assign:
545 compile_syntax_error(comp, pn, "can't assign to expression");
Damien429d7192013-10-04 19:53:11 +0100546}
547
Damien George65dc9602015-08-14 12:24:11 +0100548// stuff for lambda and comprehensions and generators:
Damien Georgee337f1e2014-03-31 15:18:37 +0100549// if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults
550// if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults
551// if both exist, the tuple is above the dictionary (ie the first pop gets the tuple)
Damien George6be0b0a2014-08-15 14:30:52 +0100552STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
Damien George30565092014-03-31 11:30:17 +0100553 assert(n_pos_defaults >= 0);
554 assert(n_kw_defaults >= 0);
555
Damien George3a3db4d2015-10-22 23:45:37 +0100556 // set flags
557 if (n_kw_defaults > 0) {
558 this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS;
559 }
560 this_scope->num_def_pos_args = n_pos_defaults;
561
Damien429d7192013-10-04 19:53:11 +0100562 // make closed over variables, if any
Damien318aec62013-12-10 18:28:17 +0000563 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
Damien429d7192013-10-04 19:53:11 +0100564 int nfree = 0;
565 if (comp->scope_cur->kind != SCOPE_MODULE) {
Damien318aec62013-12-10 18:28:17 +0000566 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
567 id_info_t *id = &comp->scope_cur->id_info[i];
568 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
569 for (int j = 0; j < this_scope->id_info_len; j++) {
570 id_info_t *id2 = &this_scope->id_info[j];
Damien George7ff996c2014-09-08 23:05:16 +0100571 if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
Alexander Steffen55f33242017-06-30 09:22:17 +0200572 // in MicroPython we load closures using LOAD_FAST
Damien George542bd6b2015-03-26 14:42:40 +0000573 EMIT_LOAD_FAST(id->qst, id->local_num);
Damien318aec62013-12-10 18:28:17 +0000574 nfree += 1;
575 }
576 }
Damien429d7192013-10-04 19:53:11 +0100577 }
578 }
579 }
Damien429d7192013-10-04 19:53:11 +0100580
581 // make the function/closure
582 if (nfree == 0) {
Damien George30565092014-03-31 11:30:17 +0100583 EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);
Damien429d7192013-10-04 19:53:11 +0100584 } else {
Damien George3558f622014-04-20 17:50:40 +0100585 EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);
Damien429d7192013-10-04 19:53:11 +0100586 }
587}
588
Damien George2c838942015-11-17 14:00:14 +0000589STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) {
Damien George40b40ff2017-04-22 14:23:47 +1000590 // For efficiency of the code below we extract the parse-node kind here
591 int pn_kind;
592 if (MP_PARSE_NODE_IS_ID(pn)) {
593 pn_kind = -1;
594 } else {
595 assert(MP_PARSE_NODE_IS_STRUCT(pn));
596 pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn);
597 }
598
599 if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) {
Damien George8b19db02014-04-11 23:25:34 +0100600 comp->have_star = true;
601 /* don't need to distinguish bare from named star
Damiend99b0522013-12-21 18:17:45 +0000602 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
603 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +0100604 // bare star
Damien George8b19db02014-04-11 23:25:34 +0100605 } else {
606 // named star
Damien429d7192013-10-04 19:53:11 +0100607 }
Damien George8b19db02014-04-11 23:25:34 +0100608 */
Damien Georgef41fdd02014-03-03 23:19:11 +0000609
Damien George40b40ff2017-04-22 14:23:47 +1000610 } else if (pn_kind == PN_typedargslist_dbl_star || pn_kind == PN_varargslist_dbl_star) {
Damien George8b19db02014-04-11 23:25:34 +0100611 // named double star
Damien Georgef41fdd02014-03-03 23:19:11 +0000612 // TODO do we need to do anything with this?
613
614 } else {
615 mp_parse_node_t pn_id;
Damien Georgef41fdd02014-03-03 23:19:11 +0000616 mp_parse_node_t pn_equal;
Damien George40b40ff2017-04-22 14:23:47 +1000617 if (pn_kind == -1) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000618 // this parameter is just an id
619
620 pn_id = pn;
Damien Georgef41fdd02014-03-03 23:19:11 +0000621 pn_equal = MP_PARSE_NODE_NULL;
622
Damien George40b40ff2017-04-22 14:23:47 +1000623 } else if (pn_kind == PN_typedargslist_name) {
Damien Georgef41fdd02014-03-03 23:19:11 +0000624 // this parameter has a colon and/or equal specifier
625
626 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
627 pn_id = pns->nodes[0];
Damien Georgead6aae12017-08-21 22:00:34 +1000628 //pn_colon = pns->nodes[1]; // unused
Damien Georgef41fdd02014-03-03 23:19:11 +0000629 pn_equal = pns->nodes[2];
Damien George2c838942015-11-17 14:00:14 +0000630
631 } else {
Damien George40b40ff2017-04-22 14:23:47 +1000632 assert(pn_kind == PN_varargslist_name); // should be
Damien George2c838942015-11-17 14:00:14 +0000633 // this parameter has an equal specifier
634
635 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
636 pn_id = pns->nodes[0];
637 pn_equal = pns->nodes[1];
Damien Georgef41fdd02014-03-03 23:19:11 +0000638 }
639
640 if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
641 // this parameter does not have a default value
642
643 // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
Damien George8b19db02014-04-11 23:25:34 +0100644 if (!comp->have_star && comp->num_default_params != 0) {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100645 compile_syntax_error(comp, pn, "non-default argument follows default argument");
Damien Georgef41fdd02014-03-03 23:19:11 +0000646 return;
647 }
648
649 } else {
650 // this parameter has a default value
651 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
652
Damien George8b19db02014-04-11 23:25:34 +0100653 if (comp->have_star) {
Damien George69b89d22014-04-11 13:38:30 +0000654 comp->num_dict_params += 1;
Alexander Steffen55f33242017-06-30 09:22:17 +0200655 // in MicroPython we put the default dict parameters into a dictionary using the bytecode
Damien George69b89d22014-04-11 13:38:30 +0000656 if (comp->num_dict_params == 1) {
Alexander Steffen55f33242017-06-30 09:22:17 +0200657 // in MicroPython we put the default positional parameters into a tuple using the bytecode
Damien George7b433012014-04-12 00:05:49 +0100658 // we need to do this here before we start building the map for the default keywords
659 if (comp->num_default_params > 0) {
660 EMIT_ARG(build_tuple, comp->num_default_params);
Damien George3558f622014-04-20 17:50:40 +0100661 } else {
662 EMIT(load_null); // sentinel indicating empty default positional args
Damien George7b433012014-04-12 00:05:49 +0100663 }
Damien George69b89d22014-04-11 13:38:30 +0000664 // first default dict param, so make the map
665 EMIT_ARG(build_map, 0);
Damien Georgef41fdd02014-03-03 23:19:11 +0000666 }
Damien Georgef0778a72014-06-07 22:01:00 +0100667
668 // compile value then key, then store it to the dict
Damien George69b89d22014-04-11 13:38:30 +0000669 compile_node(comp, pn_equal);
Damien George59fba2d2015-06-25 14:42:13 +0000670 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
Damien George69b89d22014-04-11 13:38:30 +0000671 EMIT(store_map);
Damien Georgef41fdd02014-03-03 23:19:11 +0000672 } else {
Damien George69b89d22014-04-11 13:38:30 +0000673 comp->num_default_params += 1;
674 compile_node(comp, pn_equal);
Damien Georgef41fdd02014-03-03 23:19:11 +0000675 }
676 }
Damien429d7192013-10-04 19:53:11 +0100677 }
678}
679
Damien George2c838942015-11-17 14:00:14 +0000680STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) {
Damien George29e9db02015-12-12 13:42:51 +0000681 // When we call compile_funcdef_lambdef_param below it can compile an arbitrary
682 // expression for default arguments, which may contain a lambda. The lambda will
683 // call here in a nested way, so we must save and restore the relevant state.
684 bool orig_have_star = comp->have_star;
685 uint16_t orig_num_dict_params = comp->num_dict_params;
686 uint16_t orig_num_default_params = comp->num_default_params;
687
Damien George2c838942015-11-17 14:00:14 +0000688 // compile default parameters
689 comp->have_star = false;
690 comp->num_dict_params = 0;
691 comp->num_default_params = 0;
692 apply_to_single_or_list(comp, pn_params, pn_list_kind, compile_funcdef_lambdef_param);
693
694 if (comp->compile_error != MP_OBJ_NULL) {
695 return;
696 }
697
Alexander Steffen55f33242017-06-30 09:22:17 +0200698 // in MicroPython we put the default positional parameters into a tuple using the bytecode
Damien George2c838942015-11-17 14:00:14 +0000699 // the default keywords args may have already made the tuple; if not, do it now
700 if (comp->num_default_params > 0 && comp->num_dict_params == 0) {
701 EMIT_ARG(build_tuple, comp->num_default_params);
702 EMIT(load_null); // sentinel indicating empty default keyword args
703 }
704
705 // make the function
706 close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);
Damien George29e9db02015-12-12 13:42:51 +0000707
708 // restore state
709 comp->have_star = orig_have_star;
710 comp->num_dict_params = orig_num_dict_params;
711 comp->num_default_params = orig_num_default_params;
Damien George2c838942015-11-17 14:00:14 +0000712}
713
Damien429d7192013-10-04 19:53:11 +0100714// leaves function object on stack
715// returns function name
Damien George969a6b32014-12-10 22:07:04 +0000716STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien George36db6bc2014-05-07 17:24:22 +0100717 if (comp->pass == MP_PASS_SCOPE) {
Damien429d7192013-10-04 19:53:11 +0100718 // create a new scope for this function
Damiend99b0522013-12-21 18:17:45 +0000719 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100720 // store the function scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000721 pns->nodes[4] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100722 }
723
Damien429d7192013-10-04 19:53:11 +0100724 // get the scope for this function
725 scope_t *fscope = (scope_t*)pns->nodes[4];
726
Damien George2c838942015-11-17 14:00:14 +0000727 // compile the function definition
728 compile_funcdef_lambdef(comp, fscope, pns->nodes[1], PN_typedargslist);
Damien429d7192013-10-04 19:53:11 +0100729
Damien429d7192013-10-04 19:53:11 +0100730 // return its name (the 'f' in "def f(...):")
731 return fscope->simple_name;
732}
733
734// leaves class object on stack
735// returns class name
Damien George969a6b32014-12-10 22:07:04 +0000736STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
Damien George36db6bc2014-05-07 17:24:22 +0100737 if (comp->pass == MP_PASS_SCOPE) {
Damien429d7192013-10-04 19:53:11 +0100738 // create a new scope for this class
Damiend99b0522013-12-21 18:17:45 +0000739 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
Damien429d7192013-10-04 19:53:11 +0100740 // store the class scope so the compiling function can use it at each pass
Damiend99b0522013-12-21 18:17:45 +0000741 pns->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +0100742 }
743
744 EMIT(load_build_class);
745
746 // scope for this class
747 scope_t *cscope = (scope_t*)pns->nodes[3];
748
749 // compile the class
750 close_over_variables_etc(comp, cscope, 0, 0);
751
752 // get its name
Damien George59fba2d2015-06-25 14:42:13 +0000753 EMIT_ARG(load_const_str, cscope->simple_name);
Damien429d7192013-10-04 19:53:11 +0100754
755 // nodes[1] has parent classes, if any
Damien George804760b2014-03-30 23:06:37 +0100756 // empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling
757 mp_parse_node_t parents = pns->nodes[1];
758 if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
759 parents = MP_PARSE_NODE_NULL;
760 }
Damien George804760b2014-03-30 23:06:37 +0100761 compile_trailer_paren_helper(comp, parents, false, 2);
Damien429d7192013-10-04 19:53:11 +0100762
763 // return its name (the 'C' in class C(...):")
764 return cscope->simple_name;
765}
766
Damien6cdd3af2013-10-05 18:08:26 +0100767// returns true if it was a built-in decorator (even if the built-in had an error)
Paul Sokolovsky520e2f52014-02-12 18:31:30 +0200768STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000769 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
Damien6cdd3af2013-10-05 18:08:26 +0100770 return false;
771 }
772
773 if (name_len != 2) {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100774 compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator");
Damien6cdd3af2013-10-05 18:08:26 +0100775 return true;
776 }
777
Damiend99b0522013-12-21 18:17:45 +0000778 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
Damien George3417bc22014-05-10 10:36:38 +0100779 if (attr == MP_QSTR_bytecode) {
Damien George96f137b2014-05-12 22:35:37 +0100780 *emit_options = MP_EMIT_OPT_BYTECODE;
Damience89a212013-10-15 22:25:17 +0100781#if MICROPY_EMIT_NATIVE
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000782 } else if (attr == MP_QSTR_native) {
Damien George65cad122014-04-06 11:48:15 +0100783 *emit_options = MP_EMIT_OPT_NATIVE_PYTHON;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000784 } else if (attr == MP_QSTR_viper) {
Damien George65cad122014-04-06 11:48:15 +0100785 *emit_options = MP_EMIT_OPT_VIPER;
Damience89a212013-10-15 22:25:17 +0100786#endif
Damien Georgead297a12016-12-09 13:17:49 +1100787 #if MICROPY_EMIT_INLINE_ASM
788 } else if (attr == ASM_DECORATOR_QSTR) {
789 *emit_options = MP_EMIT_OPT_ASM;
790 #endif
Damien6cdd3af2013-10-05 18:08:26 +0100791 } else {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100792 compile_syntax_error(comp, name_nodes[1], "invalid micropython decorator");
Damien6cdd3af2013-10-05 18:08:26 +0100793 }
794
795 return true;
796}
797
Damien George969a6b32014-12-10 22:07:04 +0000798STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100799 // get the list of decorators
Damiend99b0522013-12-21 18:17:45 +0000800 mp_parse_node_t *nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +0000801 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_decorators, &nodes);
Damien429d7192013-10-04 19:53:11 +0100802
Damien6cdd3af2013-10-05 18:08:26 +0100803 // inherit emit options for this function/class definition
804 uint emit_options = comp->scope_cur->emit_options;
805
806 // compile each decorator
807 int num_built_in_decorators = 0;
Damien429d7192013-10-04 19:53:11 +0100808 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +0000809 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
810 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
Damien6cdd3af2013-10-05 18:08:26 +0100811
812 // nodes[0] contains the decorator function, which is a dotted name
Damiend99b0522013-12-21 18:17:45 +0000813 mp_parse_node_t *name_nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +0000814 int name_len = mp_parse_node_extract_list(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
Damien6cdd3af2013-10-05 18:08:26 +0100815
816 // check for built-in decorators
817 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
818 // this was a built-in
819 num_built_in_decorators += 1;
820
821 } else {
822 // not a built-in, compile normally
823
824 // compile the decorator function
825 compile_node(comp, name_nodes[0]);
Damien George50912e72015-01-20 11:55:10 +0000826 for (int j = 1; j < name_len; j++) {
827 assert(MP_PARSE_NODE_IS_ID(name_nodes[j])); // should be
828 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[j]));
Damien6cdd3af2013-10-05 18:08:26 +0100829 }
830
831 // nodes[1] contains arguments to the decorator function, if any
Damiend99b0522013-12-21 18:17:45 +0000832 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
Damien6cdd3af2013-10-05 18:08:26 +0100833 // call the decorator function with the arguments in nodes[1]
834 compile_node(comp, pns_decorator->nodes[1]);
835 }
Damien429d7192013-10-04 19:53:11 +0100836 }
837 }
838
pohmelie81ebba72016-01-27 23:23:11 +0300839 // compile the body (funcdef, async funcdef or classdef) and get its name
Damiend99b0522013-12-21 18:17:45 +0000840 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +0100841 qstr body_name = 0;
Damiend99b0522013-12-21 18:17:45 +0000842 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
Damien6cdd3af2013-10-05 18:08:26 +0100843 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
pohmelie81ebba72016-01-27 23:23:11 +0300844 #if MICROPY_PY_ASYNC_AWAIT
845 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_async_funcdef) {
846 assert(MP_PARSE_NODE_IS_STRUCT(pns_body->nodes[0]));
847 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns_body->nodes[0];
848 body_name = compile_funcdef_helper(comp, pns0, emit_options);
849 scope_t *fscope = (scope_t*)pns0->nodes[4];
850 fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
851 #endif
Damien429d7192013-10-04 19:53:11 +0100852 } else {
Damien George0bb97132015-02-27 14:25:47 +0000853 assert(MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef); // should be
854 body_name = compile_classdef_helper(comp, pns_body, emit_options);
Damien429d7192013-10-04 19:53:11 +0100855 }
856
857 // call each decorator
Damien6cdd3af2013-10-05 18:08:26 +0100858 for (int i = 0; i < n - num_built_in_decorators; i++) {
Damien George922ddd62014-04-09 12:43:17 +0100859 EMIT_ARG(call_function, 1, 0, 0);
Damien429d7192013-10-04 19:53:11 +0100860 }
861
862 // store func/class object into name
Damien George542bd6b2015-03-26 14:42:40 +0000863 compile_store_id(comp, body_name);
Damien429d7192013-10-04 19:53:11 +0100864}
865
Damien George969a6b32014-12-10 22:07:04 +0000866STATIC void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +0100867 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +0100868 // store function object into function name
Damien George542bd6b2015-03-26 14:42:40 +0000869 compile_store_id(comp, fname);
Damien429d7192013-10-04 19:53:11 +0100870}
871
Damien George6be0b0a2014-08-15 14:30:52 +0100872STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +0000873 if (MP_PARSE_NODE_IS_ID(pn)) {
Damien George542bd6b2015-03-26 14:42:40 +0000874 compile_delete_id(comp, MP_PARSE_NODE_LEAF_ARG(pn));
pohmelie81ebba72016-01-27 23:23:11 +0300875 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_expr_normal)) {
Damiend99b0522013-12-21 18:17:45 +0000876 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +0100877
pohmelie81ebba72016-01-27 23:23:11 +0300878 compile_node(comp, pns->nodes[0]); // base of the atom_expr_normal node
Damien429d7192013-10-04 19:53:11 +0100879
Damiend99b0522013-12-21 18:17:45 +0000880 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
881 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pohmelie81ebba72016-01-27 23:23:11 +0300882 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) {
Damiend99b0522013-12-21 18:17:45 +0000883 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100884 for (int i = 0; i < n - 1; i++) {
885 compile_node(comp, pns1->nodes[i]);
886 }
Damiend99b0522013-12-21 18:17:45 +0000887 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
888 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
Damien429d7192013-10-04 19:53:11 +0100889 }
Damien Georgeaedf5832015-03-25 22:06:47 +0000890 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
Damien429d7192013-10-04 19:53:11 +0100891 compile_node(comp, pns1->nodes[0]);
892 EMIT(delete_subscr);
Damiend99b0522013-12-21 18:17:45 +0000893 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
894 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
Damien Georgeb9791222014-01-23 00:34:21 +0000895 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100896 } else {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100897 goto cannot_delete;
Damien429d7192013-10-04 19:53:11 +0100898 }
899 } else {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100900 goto cannot_delete;
Damien429d7192013-10-04 19:53:11 +0100901 }
902
Damiend99b0522013-12-21 18:17:45 +0000903 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
904 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien George93b37262016-01-07 13:07:52 +0000905 if (MP_PARSE_NODE_IS_NULL(pn)) {
906 goto cannot_delete;
907 } else {
908 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp));
Damiend99b0522013-12-21 18:17:45 +0000909 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +0100910 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
911
Damiend99b0522013-12-21 18:17:45 +0000912 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
913 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
914 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +0100915 // sequence of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +0000916 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
Damien429d7192013-10-04 19:53:11 +0100917 c_del_stmt(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +0000918 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +0100919 // sequence of many items
Damiend99b0522013-12-21 18:17:45 +0000920 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
Damien429d7192013-10-04 19:53:11 +0100921 c_del_stmt(comp, pns->nodes[0]);
922 for (int i = 0; i < n; i++) {
923 c_del_stmt(comp, pns1->nodes[i]);
924 }
Damien George216a7112016-09-30 14:48:06 +1000925 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for) {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100926 goto cannot_delete;
Damien429d7192013-10-04 19:53:11 +0100927 } else {
928 // sequence with 2 items
929 goto sequence_with_2_items;
930 }
931 } else {
932 // sequence with 2 items
933 sequence_with_2_items:
934 c_del_stmt(comp, pns->nodes[0]);
935 c_del_stmt(comp, pns->nodes[1]);
936 }
Damien429d7192013-10-04 19:53:11 +0100937 }
938 } else {
Ville Skyttäca16c382017-05-29 10:08:14 +0300939 // some arbitrary statement that we can't delete (eg del 1)
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100940 goto cannot_delete;
Damien429d7192013-10-04 19:53:11 +0100941 }
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100942
943 return;
944
945cannot_delete:
946 compile_syntax_error(comp, (mp_parse_node_t)pn, "can't delete expression");
Damien429d7192013-10-04 19:53:11 +0100947}
948
Damien George969a6b32014-12-10 22:07:04 +0000949STATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100950 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
951}
952
Damien George969a6b32014-12-10 22:07:04 +0000953STATIC void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georged94bc672017-06-22 15:05:58 +1000954 if (comp->break_label == INVALID_LABEL) {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100955 compile_syntax_error(comp, (mp_parse_node_t)pns, "'break' outside loop");
Damien429d7192013-10-04 19:53:11 +0100956 }
Damien George090c9232014-10-17 14:08:49 +0000957 assert(comp->cur_except_level >= comp->break_continue_except_level);
Damien Georgecbddb272014-02-01 20:08:18 +0000958 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +0100959}
960
Damien George969a6b32014-12-10 22:07:04 +0000961STATIC void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georged94bc672017-06-22 15:05:58 +1000962 if (comp->continue_label == INVALID_LABEL) {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100963 compile_syntax_error(comp, (mp_parse_node_t)pns, "'continue' outside loop");
Damien429d7192013-10-04 19:53:11 +0100964 }
Damien George090c9232014-10-17 14:08:49 +0000965 assert(comp->cur_except_level >= comp->break_continue_except_level);
Damien Georgecbddb272014-02-01 20:08:18 +0000966 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
Damien429d7192013-10-04 19:53:11 +0100967}
968
Damien George969a6b32014-12-10 22:07:04 +0000969STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien5ac1b2e2013-10-18 19:58:12 +0100970 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +0100971 compile_syntax_error(comp, (mp_parse_node_t)pns, "'return' outside function");
Damien5ac1b2e2013-10-18 19:58:12 +0100972 return;
973 }
Damiend99b0522013-12-21 18:17:45 +0000974 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien5ac1b2e2013-10-18 19:58:12 +0100975 // no argument to 'return', so return None
Damien Georgeb9791222014-01-23 00:34:21 +0000976 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien Georgeae54fbf2017-04-22 14:58:01 +1000977 } else if (MICROPY_COMP_RETURN_IF_EXPR
978 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
Damien429d7192013-10-04 19:53:11 +0100979 // special case when returning an if-expression; to match CPython optimisation
Damiend99b0522013-12-21 18:17:45 +0000980 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
981 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];
Damien429d7192013-10-04 19:53:11 +0100982
Damien George6f355fd2014-04-10 14:11:31 +0100983 uint l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +0100984 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
985 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
986 EMIT(return_value);
Damien Georgeb9791222014-01-23 00:34:21 +0000987 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +0100988 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
989 } else {
990 compile_node(comp, pns->nodes[0]);
991 }
992 EMIT(return_value);
993}
994
Damien George969a6b32014-12-10 22:07:04 +0000995STATIC void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +0100996 compile_node(comp, pns->nodes[0]);
997 EMIT(pop_top);
998}
999
Damien George969a6b32014-12-10 22:07:04 +00001000STATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00001001 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001002 // raise
Damien Georgeb9791222014-01-23 00:34:21 +00001003 EMIT_ARG(raise_varargs, 0);
Damiend99b0522013-12-21 18:17:45 +00001004 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
Damien429d7192013-10-04 19:53:11 +01001005 // raise x from y
Damiend99b0522013-12-21 18:17:45 +00001006 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01001007 compile_node(comp, pns->nodes[0]);
1008 compile_node(comp, pns->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00001009 EMIT_ARG(raise_varargs, 2);
Damien429d7192013-10-04 19:53:11 +01001010 } else {
1011 // raise x
1012 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001013 EMIT_ARG(raise_varargs, 1);
Damien429d7192013-10-04 19:53:11 +01001014 }
1015}
1016
Damien George635543c2014-04-10 12:56:52 +01001017// q_base holds the base of the name
1018// eg a -> q_base=a
1019// a.b.c -> q_base=a
Damien George6be0b0a2014-08-15 14:30:52 +01001020STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
Damien429d7192013-10-04 19:53:11 +01001021 bool is_as = false;
Damiend99b0522013-12-21 18:17:45 +00001022 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
1023 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien429d7192013-10-04 19:53:11 +01001024 // a name of the form x as y; unwrap it
Damien George635543c2014-04-10 12:56:52 +01001025 *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001026 pn = pns->nodes[0];
1027 is_as = true;
1028 }
Damien George635543c2014-04-10 12:56:52 +01001029 if (MP_PARSE_NODE_IS_NULL(pn)) {
1030 // empty name (eg, from . import x)
1031 *q_base = MP_QSTR_;
1032 EMIT_ARG(import_name, MP_QSTR_); // import the empty string
1033 } else if (MP_PARSE_NODE_IS_ID(pn)) {
Damien429d7192013-10-04 19:53:11 +01001034 // just a simple name
Damien George635543c2014-04-10 12:56:52 +01001035 qstr q_full = MP_PARSE_NODE_LEAF_ARG(pn);
Damien429d7192013-10-04 19:53:11 +01001036 if (!is_as) {
Damien George635543c2014-04-10 12:56:52 +01001037 *q_base = q_full;
Damien429d7192013-10-04 19:53:11 +01001038 }
Damien George635543c2014-04-10 12:56:52 +01001039 EMIT_ARG(import_name, q_full);
Damien George0bb97132015-02-27 14:25:47 +00001040 } else {
1041 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_name)); // should be
Damiend99b0522013-12-21 18:17:45 +00001042 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien George0bb97132015-02-27 14:25:47 +00001043 {
Damien429d7192013-10-04 19:53:11 +01001044 // a name of the form a.b.c
1045 if (!is_as) {
Damien George635543c2014-04-10 12:56:52 +01001046 *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001047 }
Damiend99b0522013-12-21 18:17:45 +00001048 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001049 int len = n - 1;
1050 for (int i = 0; i < n; i++) {
Damien George55baff42014-01-21 21:40:13 +00001051 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001052 }
Damien George55baff42014-01-21 21:40:13 +00001053 byte *q_ptr;
1054 byte *str_dest = qstr_build_start(len, &q_ptr);
Damien429d7192013-10-04 19:53:11 +01001055 for (int i = 0; i < n; i++) {
1056 if (i > 0) {
Damien Georgefe8fb912014-01-02 16:36:09 +00001057 *str_dest++ = '.';
Damien429d7192013-10-04 19:53:11 +01001058 }
Damien Georgec3f64d92015-11-27 12:23:18 +00001059 size_t str_src_len;
Damien George55baff42014-01-21 21:40:13 +00001060 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
Damien Georgefe8fb912014-01-02 16:36:09 +00001061 memcpy(str_dest, str_src, str_src_len);
1062 str_dest += str_src_len;
Damien429d7192013-10-04 19:53:11 +01001063 }
Damien George635543c2014-04-10 12:56:52 +01001064 qstr q_full = qstr_build_end(q_ptr);
1065 EMIT_ARG(import_name, q_full);
Damien429d7192013-10-04 19:53:11 +01001066 if (is_as) {
1067 for (int i = 1; i < n; i++) {
Damien Georgeb9791222014-01-23 00:34:21 +00001068 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001069 }
1070 }
Damien429d7192013-10-04 19:53:11 +01001071 }
Damien429d7192013-10-04 19:53:11 +01001072 }
1073}
1074
Damien George6be0b0a2014-08-15 14:30:52 +01001075STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
Damien George635543c2014-04-10 12:56:52 +01001076 EMIT_ARG(load_const_small_int, 0); // level 0 import
1077 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything
1078 qstr q_base;
1079 do_import_name(comp, pn, &q_base);
Damien George542bd6b2015-03-26 14:42:40 +00001080 compile_store_id(comp, q_base);
Damien429d7192013-10-04 19:53:11 +01001081}
1082
Damien George969a6b32014-12-10 22:07:04 +00001083STATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001084 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
1085}
1086
Damien George969a6b32014-12-10 22:07:04 +00001087STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George635543c2014-04-10 12:56:52 +01001088 mp_parse_node_t pn_import_source = pns->nodes[0];
1089
Ville Skyttäca16c382017-05-29 10:08:14 +03001090 // extract the preceding .'s (if any) for a relative import, to compute the import level
Damien George635543c2014-04-10 12:56:52 +01001091 uint import_level = 0;
1092 do {
1093 mp_parse_node_t pn_rel;
1094 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)) {
1095 // This covers relative imports with dots only like "from .. import"
1096 pn_rel = pn_import_source;
1097 pn_import_source = MP_PARSE_NODE_NULL;
1098 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_import_from_2b)) {
1099 // This covers relative imports starting with dot(s) like "from .foo import"
1100 mp_parse_node_struct_t *pns_2b = (mp_parse_node_struct_t*)pn_import_source;
1101 pn_rel = pns_2b->nodes[0];
1102 pn_import_source = pns_2b->nodes[1];
1103 assert(!MP_PARSE_NODE_IS_NULL(pn_import_source)); // should not be
1104 } else {
1105 // Not a relative import
1106 break;
1107 }
1108
1109 // get the list of . and/or ...'s
1110 mp_parse_node_t *nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +00001111 int n = mp_parse_node_extract_list(&pn_rel, PN_one_or_more_period_or_ellipsis, &nodes);
Damien George635543c2014-04-10 12:56:52 +01001112
1113 // count the total number of .'s
1114 for (int i = 0; i < n; i++) {
1115 if (MP_PARSE_NODE_IS_TOKEN_KIND(nodes[i], MP_TOKEN_DEL_PERIOD)) {
1116 import_level++;
1117 } else {
1118 // should be an MP_TOKEN_ELLIPSIS
1119 import_level += 3;
1120 }
1121 }
1122 } while (0);
1123
Damiend99b0522013-12-21 18:17:45 +00001124 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
Damien George635543c2014-04-10 12:56:52 +01001125 EMIT_ARG(load_const_small_int, import_level);
Damiendb4c3612013-12-10 17:27:24 +00001126
1127 // build the "fromlist" tuple
Damien George59fba2d2015-06-25 14:42:13 +00001128 EMIT_ARG(load_const_str, MP_QSTR__star_);
Damien Georgeb9791222014-01-23 00:34:21 +00001129 EMIT_ARG(build_tuple, 1);
Damiendb4c3612013-12-10 17:27:24 +00001130
1131 // do the import
Damien George635543c2014-04-10 12:56:52 +01001132 qstr dummy_q;
1133 do_import_name(comp, pn_import_source, &dummy_q);
Damien429d7192013-10-04 19:53:11 +01001134 EMIT(import_star);
Damiendb4c3612013-12-10 17:27:24 +00001135
Damien429d7192013-10-04 19:53:11 +01001136 } else {
Damien George635543c2014-04-10 12:56:52 +01001137 EMIT_ARG(load_const_small_int, import_level);
Damiendb4c3612013-12-10 17:27:24 +00001138
1139 // build the "fromlist" tuple
Damiend99b0522013-12-21 18:17:45 +00001140 mp_parse_node_t *pn_nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +00001141 int n = mp_parse_node_extract_list(&pns->nodes[1], PN_import_as_names, &pn_nodes);
Damiendb4c3612013-12-10 17:27:24 +00001142 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001143 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1144 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1145 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien George59fba2d2015-06-25 14:42:13 +00001146 EMIT_ARG(load_const_str, id2);
Damiendb4c3612013-12-10 17:27:24 +00001147 }
Damien Georgeb9791222014-01-23 00:34:21 +00001148 EMIT_ARG(build_tuple, n);
Damiendb4c3612013-12-10 17:27:24 +00001149
1150 // do the import
Damien George635543c2014-04-10 12:56:52 +01001151 qstr dummy_q;
1152 do_import_name(comp, pn_import_source, &dummy_q);
Damien429d7192013-10-04 19:53:11 +01001153 for (int i = 0; i < n; i++) {
Damiend99b0522013-12-21 18:17:45 +00001154 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
1155 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
1156 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
Damien Georgeb9791222014-01-23 00:34:21 +00001157 EMIT_ARG(import_from, id2);
Damiend99b0522013-12-21 18:17:45 +00001158 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
Damien George542bd6b2015-03-26 14:42:40 +00001159 compile_store_id(comp, id2);
Damien429d7192013-10-04 19:53:11 +01001160 } else {
Damien George542bd6b2015-03-26 14:42:40 +00001161 compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
Damien429d7192013-10-04 19:53:11 +01001162 }
1163 }
1164 EMIT(pop_top);
1165 }
1166}
1167
Damien George584ba672014-12-21 17:26:45 +00001168STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
1169 bool added;
1170 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
Damien George558a0162015-09-07 16:55:02 +01001171 if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
1172 compile_syntax_error(comp, pn, "identifier redefined as global");
Damien George584ba672014-12-21 17:26:45 +00001173 return;
1174 }
1175 id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
1176
1177 // if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL
1178 id_info = scope_find_global(comp->scope_cur, qst);
1179 if (id_info != NULL) {
1180 id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
1181 }
1182}
1183
Damien George969a6b32014-12-10 22:07:04 +00001184STATIC void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George36db6bc2014-05-07 17:24:22 +01001185 if (comp->pass == MP_PASS_SCOPE) {
Damien George584ba672014-12-21 17:26:45 +00001186 mp_parse_node_t *nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +00001187 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
Damien George584ba672014-12-21 17:26:45 +00001188 for (int i = 0; i < n; i++) {
1189 compile_declare_global(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001190 }
1191 }
1192}
1193
Damien George584ba672014-12-21 17:26:45 +00001194STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
1195 bool added;
1196 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
Damien George0d105172016-09-30 13:53:00 +10001197 if (added) {
1198 scope_find_local_and_close_over(comp->scope_cur, id_info, qst);
1199 if (id_info->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
1200 compile_syntax_error(comp, pn, "no binding for nonlocal found");
1201 }
1202 } else if (id_info->kind != ID_INFO_KIND_FREE) {
Damien George558a0162015-09-07 16:55:02 +01001203 compile_syntax_error(comp, pn, "identifier redefined as nonlocal");
Damien George584ba672014-12-21 17:26:45 +00001204 }
Damien George584ba672014-12-21 17:26:45 +00001205}
1206
Damien George969a6b32014-12-10 22:07:04 +00001207STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George36db6bc2014-05-07 17:24:22 +01001208 if (comp->pass == MP_PASS_SCOPE) {
Damien George584ba672014-12-21 17:26:45 +00001209 if (comp->scope_cur->kind == SCOPE_MODULE) {
1210 compile_syntax_error(comp, (mp_parse_node_t)pns, "can't declare nonlocal in outer code");
1211 return;
1212 }
1213 mp_parse_node_t *nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +00001214 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
Damien George584ba672014-12-21 17:26:45 +00001215 for (int i = 0; i < n; i++) {
1216 compile_declare_nonlocal(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));
Damien429d7192013-10-04 19:53:11 +01001217 }
1218 }
1219}
1220
Damien George969a6b32014-12-10 22:07:04 +00001221STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George24df30c2016-08-26 22:28:22 +10001222 // with optimisations enabled we don't compile assertions
1223 if (MP_STATE_VM(mp_optimise_value) != 0) {
1224 return;
1225 }
1226
Damien George6f355fd2014-04-10 14:11:31 +01001227 uint l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001228 c_if_cond(comp, pns->nodes[0], true, l_end);
Damien George542bd6b2015-03-26 14:42:40 +00001229 EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
Damiend99b0522013-12-21 18:17:45 +00001230 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien429d7192013-10-04 19:53:11 +01001231 // assertion message
1232 compile_node(comp, pns->nodes[1]);
Damien George922ddd62014-04-09 12:43:17 +01001233 EMIT_ARG(call_function, 1, 0, 0);
Damien429d7192013-10-04 19:53:11 +01001234 }
Damien Georgeb9791222014-01-23 00:34:21 +00001235 EMIT_ARG(raise_varargs, 1);
1236 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001237}
1238
Damien George969a6b32014-12-10 22:07:04 +00001239STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George6f355fd2014-04-10 14:11:31 +01001240 uint l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001241
Damien George65dc9602015-08-14 12:24:11 +01001242 // optimisation: don't emit anything when "if False"
Damien Georgeb0cbfb02016-11-13 15:32:05 +11001243 if (!mp_parse_node_is_const_false(pns->nodes[0])) {
Damien George391db862014-10-17 17:57:33 +00001244 uint l_fail = comp_next_label(comp);
1245 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
Damien429d7192013-10-04 19:53:11 +01001246
Damien George391db862014-10-17 17:57:33 +00001247 compile_node(comp, pns->nodes[1]); // if block
Damien Georgeaf6edc62014-04-02 16:12:28 +01001248
Damien George65dc9602015-08-14 12:24:11 +01001249 // optimisation: skip everything else when "if True"
Damien Georgeb0cbfb02016-11-13 15:32:05 +11001250 if (mp_parse_node_is_const_true(pns->nodes[0])) {
Damien George391db862014-10-17 17:57:33 +00001251 goto done;
1252 }
1253
1254 if (
Damien George65dc9602015-08-14 12:24:11 +01001255 // optimisation: don't jump over non-existent elif/else blocks
1256 !(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))
Damien George391db862014-10-17 17:57:33 +00001257 // optimisation: don't jump if last instruction was return
1258 && !EMIT(last_emit_was_return_value)
1259 ) {
1260 // jump over elif/else blocks
1261 EMIT_ARG(jump, l_end);
1262 }
1263
1264 EMIT_ARG(label_assign, l_fail);
Damien Georgeaf6edc62014-04-02 16:12:28 +01001265 }
1266
Damien George235f9b32014-10-17 17:30:16 +00001267 // compile elif blocks (if any)
1268 mp_parse_node_t *pn_elif;
Damien Georgedfe944c2015-02-13 02:29:46 +00001269 int n_elif = mp_parse_node_extract_list(&pns->nodes[2], PN_if_stmt_elif_list, &pn_elif);
Damien George235f9b32014-10-17 17:30:16 +00001270 for (int i = 0; i < n_elif; i++) {
1271 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_elif[i], PN_if_stmt_elif)); // should be
1272 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pn_elif[i];
Damien429d7192013-10-04 19:53:11 +01001273
Damien George65dc9602015-08-14 12:24:11 +01001274 // optimisation: don't emit anything when "if False"
Damien Georgeb0cbfb02016-11-13 15:32:05 +11001275 if (!mp_parse_node_is_const_false(pns_elif->nodes[0])) {
Damien George391db862014-10-17 17:57:33 +00001276 uint l_fail = comp_next_label(comp);
1277 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
Damien429d7192013-10-04 19:53:11 +01001278
Damien George391db862014-10-17 17:57:33 +00001279 compile_node(comp, pns_elif->nodes[1]); // elif block
1280
Damien George65dc9602015-08-14 12:24:11 +01001281 // optimisation: skip everything else when "elif True"
Damien Georgeb0cbfb02016-11-13 15:32:05 +11001282 if (mp_parse_node_is_const_true(pns_elif->nodes[0])) {
Damien George391db862014-10-17 17:57:33 +00001283 goto done;
1284 }
1285
1286 // optimisation: don't jump if last instruction was return
1287 if (!EMIT(last_emit_was_return_value)) {
1288 EMIT_ARG(jump, l_end);
1289 }
1290 EMIT_ARG(label_assign, l_fail);
Damien429d7192013-10-04 19:53:11 +01001291 }
1292 }
1293
1294 // compile else block
1295 compile_node(comp, pns->nodes[3]); // can be null
1296
Damien George391db862014-10-17 17:57:33 +00001297done:
Damien Georgeb9791222014-01-23 00:34:21 +00001298 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01001299}
1300
Damien Georgecbddb272014-02-01 20:08:18 +00001301#define START_BREAK_CONTINUE_BLOCK \
Damien George090c9232014-10-17 14:08:49 +00001302 uint16_t old_break_label = comp->break_label; \
1303 uint16_t old_continue_label = comp->continue_label; \
1304 uint16_t old_break_continue_except_level = comp->break_continue_except_level; \
Damien George6f355fd2014-04-10 14:11:31 +01001305 uint break_label = comp_next_label(comp); \
1306 uint continue_label = comp_next_label(comp); \
Damien Georgecbddb272014-02-01 20:08:18 +00001307 comp->break_label = break_label; \
1308 comp->continue_label = continue_label; \
1309 comp->break_continue_except_level = comp->cur_except_level;
1310
1311#define END_BREAK_CONTINUE_BLOCK \
1312 comp->break_label = old_break_label; \
1313 comp->continue_label = old_continue_label; \
Damien George090c9232014-10-17 14:08:49 +00001314 comp->break_continue_except_level = old_break_continue_except_level;
Damien Georgecbddb272014-02-01 20:08:18 +00001315
Damien George969a6b32014-12-10 22:07:04 +00001316STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgecbddb272014-02-01 20:08:18 +00001317 START_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001318
Damien Georgeb0cbfb02016-11-13 15:32:05 +11001319 if (!mp_parse_node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False"
Damien George391db862014-10-17 17:57:33 +00001320 uint top_label = comp_next_label(comp);
Damien Georgeb0cbfb02016-11-13 15:32:05 +11001321 if (!mp_parse_node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for "while True"
Damien George391db862014-10-17 17:57:33 +00001322 EMIT_ARG(jump, continue_label);
1323 }
1324 EMIT_ARG(label_assign, top_label);
1325 compile_node(comp, pns->nodes[1]); // body
1326 EMIT_ARG(label_assign, continue_label);
1327 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
1328 }
Damience89a212013-10-15 22:25:17 +01001329
1330 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001331 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001332
1333 compile_node(comp, pns->nodes[2]); // else
1334
Damien Georgeb9791222014-01-23 00:34:21 +00001335 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001336}
1337
Damien Georgee181c0d2014-12-12 17:19:56 +00001338// This function compiles an optimised for-loop of the form:
1339// for <var> in range(<start>, <end>, <step>):
1340// <body>
1341// else:
1342// <else>
1343// <var> must be an identifier and <step> must be a small-int.
1344//
1345// Semantics of for-loop require:
1346// - final failing value should not be stored in the loop variable
1347// - if the loop never runs, the loop variable should never be assigned
1348// - assignments to <var>, <end> or <step> in the body do not alter the loop
1349// (<step> is a constant for us, so no need to worry about it changing)
1350//
1351// If <end> is a small-int, then the stack during the for-loop contains just
1352// the current value of <var>. Otherwise, the stack contains <end> then the
1353// current value of <var>.
Damien George6be0b0a2014-08-15 14:30:52 +01001354STATIC 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) {
Damien Georgecbddb272014-02-01 20:08:18 +00001355 START_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001356
Damien George6f355fd2014-04-10 14:11:31 +01001357 uint top_label = comp_next_label(comp);
1358 uint entry_label = comp_next_label(comp);
Damienf72fd0e2013-11-06 20:20:49 +00001359
Damien Georgee181c0d2014-12-12 17:19:56 +00001360 // put the end value on the stack if it's not a small-int constant
1361 bool end_on_stack = !MP_PARSE_NODE_IS_SMALL_INT(pn_end);
1362 if (end_on_stack) {
1363 compile_node(comp, pn_end);
1364 }
1365
1366 // compile: start
Damienf72fd0e2013-11-06 20:20:49 +00001367 compile_node(comp, pn_start);
Damienf72fd0e2013-11-06 20:20:49 +00001368
Damien Georgeb9791222014-01-23 00:34:21 +00001369 EMIT_ARG(jump, entry_label);
1370 EMIT_ARG(label_assign, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001371
Damien Georgec33ce602014-12-11 17:35:23 +00001372 // duplicate next value and store it to var
1373 EMIT(dup_top);
Damien George3ff2d032014-03-31 18:02:22 +01001374 c_assign(comp, pn_var, ASSIGN_STORE);
1375
Damienf3822fc2013-11-09 20:12:03 +00001376 // compile body
1377 compile_node(comp, pn_body);
1378
Damien Georgeb9791222014-01-23 00:34:21 +00001379 EMIT_ARG(label_assign, continue_label);
Damien George600ae732014-01-21 23:48:04 +00001380
Damien Georgee181c0d2014-12-12 17:19:56 +00001381 // compile: var + step
Damienf72fd0e2013-11-06 20:20:49 +00001382 compile_node(comp, pn_step);
Damien Georged17926d2014-03-30 13:35:08 +01001383 EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);
Damienf72fd0e2013-11-06 20:20:49 +00001384
Damien Georgeb9791222014-01-23 00:34:21 +00001385 EMIT_ARG(label_assign, entry_label);
Damienf72fd0e2013-11-06 20:20:49 +00001386
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001387 // compile: if var <cond> end: goto top
Damien Georgee181c0d2014-12-12 17:19:56 +00001388 if (end_on_stack) {
1389 EMIT(dup_top_two);
1390 EMIT(rot_two);
1391 } else {
1392 EMIT(dup_top);
1393 compile_node(comp, pn_end);
1394 }
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02001395 assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
1396 if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
Damien Georged17926d2014-03-30 13:35:08 +01001397 EMIT_ARG(binary_op, MP_BINARY_OP_LESS);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001398 } else {
Damien Georged17926d2014-03-30 13:35:08 +01001399 EMIT_ARG(binary_op, MP_BINARY_OP_MORE);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001400 }
Damien George63f38322015-02-28 15:04:06 +00001401 EMIT_ARG(pop_jump_if, true, top_label);
Damienf72fd0e2013-11-06 20:20:49 +00001402
1403 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001404 END_BREAK_CONTINUE_BLOCK
Damienf72fd0e2013-11-06 20:20:49 +00001405
Damien George4c5f1082017-06-22 13:50:33 +10001406 // Compile the else block. We must pop the iterator variables before
1407 // executing the else code because it may contain break/continue statements.
1408 uint end_label = 0;
1409 if (!MP_PARSE_NODE_IS_NULL(pn_else)) {
1410 // discard final value of "var", and possible "end" value
1411 EMIT(pop_top);
1412 if (end_on_stack) {
1413 EMIT(pop_top);
1414 }
1415 compile_node(comp, pn_else);
1416 end_label = comp_next_label(comp);
1417 EMIT_ARG(jump, end_label);
1418 EMIT_ARG(adjust_stack_size, 1 + end_on_stack);
1419 }
Damienf72fd0e2013-11-06 20:20:49 +00001420
Damien Georgeb9791222014-01-23 00:34:21 +00001421 EMIT_ARG(label_assign, break_label);
Damien Georgee181c0d2014-12-12 17:19:56 +00001422
1423 // discard final value of var that failed the loop condition
1424 EMIT(pop_top);
1425
1426 // discard <end> value if it's on the stack
1427 if (end_on_stack) {
1428 EMIT(pop_top);
1429 }
Damien George4c5f1082017-06-22 13:50:33 +10001430
1431 if (!MP_PARSE_NODE_IS_NULL(pn_else)) {
1432 EMIT_ARG(label_assign, end_label);
1433 }
Damienf72fd0e2013-11-06 20:20:49 +00001434}
1435
Damien George969a6b32014-12-10 22:07:04 +00001436STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damienf72fd0e2013-11-06 20:20:49 +00001437 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
1438 // this is actually slower, but uses no heap memory
1439 // for viper it will be much, much faster
pohmelie81ebba72016-01-27 23:23:11 +03001440 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)) {
Damiend99b0522013-12-21 18:17:45 +00001441 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
pohmelie81ebba72016-01-27 23:23:11 +03001442 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001443 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
Damien Georgefa03bbf2017-04-22 14:13:37 +10001444 && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pns_it->nodes[1]) == PN_trailer_paren) {
Damiend99b0522013-12-21 18:17:45 +00001445 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
1446 mp_parse_node_t *args;
Damien Georgedfe944c2015-02-13 02:29:46 +00001447 int n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args);
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001448 mp_parse_node_t pn_range_start;
1449 mp_parse_node_t pn_range_end;
1450 mp_parse_node_t pn_range_step;
1451 bool optimize = false;
Damienf72fd0e2013-11-06 20:20:49 +00001452 if (1 <= n_args && n_args <= 3) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001453 optimize = true;
Damienf72fd0e2013-11-06 20:20:49 +00001454 if (n_args == 1) {
Damien Georgeed9c93f2016-11-13 15:35:11 +11001455 pn_range_start = mp_parse_node_new_small_int(0);
Damienf72fd0e2013-11-06 20:20:49 +00001456 pn_range_end = args[0];
Damien Georgeed9c93f2016-11-13 15:35:11 +11001457 pn_range_step = mp_parse_node_new_small_int(1);
Damienf72fd0e2013-11-06 20:20:49 +00001458 } else if (n_args == 2) {
1459 pn_range_start = args[0];
1460 pn_range_end = args[1];
Damien Georgeed9c93f2016-11-13 15:35:11 +11001461 pn_range_step = mp_parse_node_new_small_int(1);
Damienf72fd0e2013-11-06 20:20:49 +00001462 } else {
1463 pn_range_start = args[0];
1464 pn_range_end = args[1];
1465 pn_range_step = args[2];
Damien Georgede9b5362017-04-05 10:50:26 +10001466 // the step must be a non-zero constant integer to do the optimisation
1467 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)
1468 || MP_PARSE_NODE_LEAF_SMALL_INT(pn_range_step) == 0) {
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001469 optimize = false;
1470 }
Damienf72fd0e2013-11-06 20:20:49 +00001471 }
Damien George33ac0fd2015-12-08 21:05:14 +00001472 // arguments must be able to be compiled as standard expressions
1473 if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_start)) {
1474 int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_range_start);
1475 if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {
1476 optimize = false;
1477 }
1478 }
1479 if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_end)) {
1480 int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_range_end);
1481 if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {
1482 optimize = false;
1483 }
1484 }
Paul Sokolovsky899c69f2014-01-10 20:38:57 +02001485 }
1486 if (optimize) {
Damienf72fd0e2013-11-06 20:20:49 +00001487 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
1488 return;
1489 }
1490 }
1491 }
Damienf72fd0e2013-11-06 20:20:49 +00001492
Damien Georgecbddb272014-02-01 20:08:18 +00001493 START_BREAK_CONTINUE_BLOCK
Damien George25c84642014-05-30 15:20:41 +01001494 comp->break_label |= MP_EMIT_BREAK_FROM_FOR;
Damien429d7192013-10-04 19:53:11 +01001495
Damien George6f355fd2014-04-10 14:11:31 +01001496 uint pop_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001497
Damien429d7192013-10-04 19:53:11 +01001498 compile_node(comp, pns->nodes[1]); // iterator
Damien Georgef4df3aa2016-01-09 23:59:52 +00001499 EMIT_ARG(get_iter, true);
Damien Georgecbddb272014-02-01 20:08:18 +00001500 EMIT_ARG(label_assign, continue_label);
Damien Georgeb9791222014-01-23 00:34:21 +00001501 EMIT_ARG(for_iter, pop_label);
Damien429d7192013-10-04 19:53:11 +01001502 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1503 compile_node(comp, pns->nodes[2]); // body
Damien415eb6f2013-10-05 12:19:06 +01001504 if (!EMIT(last_emit_was_return_value)) {
Damien Georgecbddb272014-02-01 20:08:18 +00001505 EMIT_ARG(jump, continue_label);
Damien429d7192013-10-04 19:53:11 +01001506 }
Damien Georgeb9791222014-01-23 00:34:21 +00001507 EMIT_ARG(label_assign, pop_label);
Damien George30b42dd2017-01-17 15:30:18 +11001508 EMIT(for_iter_end);
Damien429d7192013-10-04 19:53:11 +01001509
1510 // break/continue apply to outer loop (if any) in the else block
Damien Georgecbddb272014-02-01 20:08:18 +00001511 END_BREAK_CONTINUE_BLOCK
Damien429d7192013-10-04 19:53:11 +01001512
Damien George4c5f1082017-06-22 13:50:33 +10001513 compile_node(comp, pns->nodes[3]); // else (may be empty)
Damien429d7192013-10-04 19:53:11 +01001514
Damien Georgeb9791222014-01-23 00:34:21 +00001515 EMIT_ARG(label_assign, break_label);
Damien429d7192013-10-04 19:53:11 +01001516}
1517
Damien George6be0b0a2014-08-15 14:30:52 +01001518STATIC 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) {
Damien429d7192013-10-04 19:53:11 +01001519 // setup code
Damien George6f355fd2014-04-10 14:11:31 +01001520 uint l1 = comp_next_label(comp);
1521 uint success_label = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001522
Damien Georgeb9791222014-01-23 00:34:21 +00001523 EMIT_ARG(setup_except, l1);
Damien George8dcc0c72014-03-27 10:55:21 +00001524 compile_increase_except_level(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001525
Damien429d7192013-10-04 19:53:11 +01001526 compile_node(comp, pn_body); // body
1527 EMIT(pop_block);
Damien George069a35e2014-04-10 17:22:19 +00001528 EMIT_ARG(jump, success_label); // jump over exception handler
1529
1530 EMIT_ARG(label_assign, l1); // start of exception handler
Damien Georgeb601d952014-06-30 05:17:25 +01001531 EMIT(start_except_handler);
Damien George069a35e2014-04-10 17:22:19 +00001532
Damien Georgef0406852016-09-27 12:37:21 +10001533 // at this point the top of the stack contains the exception instance that was raised
1534
Damien George6f355fd2014-04-10 14:11:31 +01001535 uint l2 = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001536
1537 for (int i = 0; i < n_except; i++) {
Damiend99b0522013-12-21 18:17:45 +00001538 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
1539 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
Damien429d7192013-10-04 19:53:11 +01001540
1541 qstr qstr_exception_local = 0;
Damien George6f355fd2014-04-10 14:11:31 +01001542 uint end_finally_label = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01001543
Damiend99b0522013-12-21 18:17:45 +00001544 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01001545 // this is a catch all exception handler
1546 if (i + 1 != n_except) {
Damien George18c059f2017-03-29 12:36:46 +11001547 compile_syntax_error(comp, pn_excepts[i], "default 'except' must be last");
Damien Georgec935d692015-01-13 23:33:16 +00001548 compile_decrease_except_level(comp);
Damien429d7192013-10-04 19:53:11 +01001549 return;
1550 }
1551 } else {
1552 // this exception handler requires a match to a certain type of exception
Damiend99b0522013-12-21 18:17:45 +00001553 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
1554 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
1555 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
1556 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
Damien429d7192013-10-04 19:53:11 +01001557 // handler binds the exception to a local
1558 pns_exception_expr = pns3->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00001559 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01001560 }
1561 }
1562 EMIT(dup_top);
1563 compile_node(comp, pns_exception_expr);
Damien Georged17926d2014-03-30 13:35:08 +01001564 EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
Damien George63f38322015-02-28 15:04:06 +00001565 EMIT_ARG(pop_jump_if, false, end_finally_label);
Damien429d7192013-10-04 19:53:11 +01001566 }
1567
Damien Georgef0406852016-09-27 12:37:21 +10001568 // either discard or store the exception instance
Damien429d7192013-10-04 19:53:11 +01001569 if (qstr_exception_local == 0) {
1570 EMIT(pop_top);
1571 } else {
Damien George542bd6b2015-03-26 14:42:40 +00001572 compile_store_id(comp, qstr_exception_local);
Damien429d7192013-10-04 19:53:11 +01001573 }
1574
Damien George6f355fd2014-04-10 14:11:31 +01001575 uint l3 = 0;
Damien429d7192013-10-04 19:53:11 +01001576 if (qstr_exception_local != 0) {
Damienb05d7072013-10-05 13:37:10 +01001577 l3 = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00001578 EMIT_ARG(setup_finally, l3);
Damien George8dcc0c72014-03-27 10:55:21 +00001579 compile_increase_except_level(comp);
Damien429d7192013-10-04 19:53:11 +01001580 }
1581 compile_node(comp, pns_except->nodes[1]);
1582 if (qstr_exception_local != 0) {
1583 EMIT(pop_block);
1584 }
1585 EMIT(pop_except);
1586 if (qstr_exception_local != 0) {
Damien Georgeb9791222014-01-23 00:34:21 +00001587 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1588 EMIT_ARG(label_assign, l3);
1589 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien George542bd6b2015-03-26 14:42:40 +00001590 compile_store_id(comp, qstr_exception_local);
1591 compile_delete_id(comp, qstr_exception_local);
Damien Georgecbddb272014-02-01 20:08:18 +00001592
Damien George8dcc0c72014-03-27 10:55:21 +00001593 compile_decrease_except_level(comp);
Damien429d7192013-10-04 19:53:11 +01001594 EMIT(end_finally);
1595 }
Damien Georgeb9791222014-01-23 00:34:21 +00001596 EMIT_ARG(jump, l2);
1597 EMIT_ARG(label_assign, end_finally_label);
Damien Georgef0406852016-09-27 12:37:21 +10001598 EMIT_ARG(adjust_stack_size, 1); // stack adjust for the exception instance
Damien429d7192013-10-04 19:53:11 +01001599 }
1600
Damien George8dcc0c72014-03-27 10:55:21 +00001601 compile_decrease_except_level(comp);
Damien429d7192013-10-04 19:53:11 +01001602 EMIT(end_finally);
Damien Georgeb601d952014-06-30 05:17:25 +01001603 EMIT(end_except_handler);
Damien Georgecbddb272014-02-01 20:08:18 +00001604
Damien Georgeb9791222014-01-23 00:34:21 +00001605 EMIT_ARG(label_assign, success_label);
Damien429d7192013-10-04 19:53:11 +01001606 compile_node(comp, pn_else); // else block, can be null
Damien Georgeb9791222014-01-23 00:34:21 +00001607 EMIT_ARG(label_assign, l2);
Damien429d7192013-10-04 19:53:11 +01001608}
1609
Damien George6be0b0a2014-08-15 14:30:52 +01001610STATIC 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) {
Damien George6f355fd2014-04-10 14:11:31 +01001611 uint l_finally_block = comp_next_label(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001612
Damien Georgeb9791222014-01-23 00:34:21 +00001613 EMIT_ARG(setup_finally, l_finally_block);
Damien George8dcc0c72014-03-27 10:55:21 +00001614 compile_increase_except_level(comp);
Damien Georgecbddb272014-02-01 20:08:18 +00001615
Damien429d7192013-10-04 19:53:11 +01001616 if (n_except == 0) {
Damiend99b0522013-12-21 18:17:45 +00001617 assert(MP_PARSE_NODE_IS_NULL(pn_else));
Damien Georged66ae182014-04-10 17:28:54 +00001618 EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state
Damien429d7192013-10-04 19:53:11 +01001619 compile_node(comp, pn_body);
Damien Georged66ae182014-04-10 17:28:54 +00001620 EMIT_ARG(adjust_stack_size, -3);
Damien429d7192013-10-04 19:53:11 +01001621 } else {
1622 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
1623 }
1624 EMIT(pop_block);
Damien Georgeb9791222014-01-23 00:34:21 +00001625 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1626 EMIT_ARG(label_assign, l_finally_block);
Damien429d7192013-10-04 19:53:11 +01001627 compile_node(comp, pn_finally);
Damien Georgecbddb272014-02-01 20:08:18 +00001628
Damien George8dcc0c72014-03-27 10:55:21 +00001629 compile_decrease_except_level(comp);
Damien429d7192013-10-04 19:53:11 +01001630 EMIT(end_finally);
Damien429d7192013-10-04 19:53:11 +01001631}
1632
Damien George969a6b32014-12-10 22:07:04 +00001633STATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George0bb97132015-02-27 14:25:47 +00001634 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should be
1635 {
Damiend99b0522013-12-21 18:17:45 +00001636 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
1637 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
Damien429d7192013-10-04 19:53:11 +01001638 // just try-finally
Damiend99b0522013-12-21 18:17:45 +00001639 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
1640 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
Damien429d7192013-10-04 19:53:11 +01001641 // try-except and possibly else and/or finally
Damiend99b0522013-12-21 18:17:45 +00001642 mp_parse_node_t *pn_excepts;
Damien Georgedfe944c2015-02-13 02:29:46 +00001643 int n_except = mp_parse_node_extract_list(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001644 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
Damien429d7192013-10-04 19:53:11 +01001645 // no finally
1646 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
1647 } else {
1648 // have finally
Damiend99b0522013-12-21 18:17:45 +00001649 compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((mp_parse_node_struct_t*)pns2->nodes[2])->nodes[0]);
Damien429d7192013-10-04 19:53:11 +01001650 }
1651 } else {
1652 // just try-except
Damiend99b0522013-12-21 18:17:45 +00001653 mp_parse_node_t *pn_excepts;
Damien Georgedfe944c2015-02-13 02:29:46 +00001654 int n_except = mp_parse_node_extract_list(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
Damiend99b0522013-12-21 18:17:45 +00001655 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
Damien429d7192013-10-04 19:53:11 +01001656 }
Damien429d7192013-10-04 19:53:11 +01001657 }
1658}
1659
Damien George6be0b0a2014-08-15 14:30:52 +01001660STATIC void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) {
Damien429d7192013-10-04 19:53:11 +01001661 if (n == 0) {
1662 // no more pre-bits, compile the body of the with
1663 compile_node(comp, body);
1664 } else {
Damien George6f355fd2014-04-10 14:11:31 +01001665 uint l_end = comp_next_label(comp);
Damien George2c915e12016-04-07 08:53:24 +01001666 if (MICROPY_EMIT_NATIVE && comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {
1667 // we need to allocate an extra label for the native emitter
1668 // it will use l_end+1 as an auxiliary label
1669 comp_next_label(comp);
1670 }
Damiend99b0522013-12-21 18:17:45 +00001671 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Damien429d7192013-10-04 19:53:11 +01001672 // this pre-bit is of the form "a as b"
Damiend99b0522013-12-21 18:17:45 +00001673 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Damien429d7192013-10-04 19:53:11 +01001674 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001675 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001676 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1677 } else {
1678 // this pre-bit is just an expression
1679 compile_node(comp, nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00001680 EMIT_ARG(setup_with, l_end);
Damien429d7192013-10-04 19:53:11 +01001681 EMIT(pop_top);
1682 }
Paul Sokolovsky44307d52014-03-29 04:10:11 +02001683 compile_increase_except_level(comp);
Damien429d7192013-10-04 19:53:11 +01001684 // compile additional pre-bits and the body
1685 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
1686 // finish this with block
Damien Georgece8b4e82016-04-07 08:50:38 +01001687 EMIT_ARG(with_cleanup, l_end);
Paul Sokolovsky44307d52014-03-29 04:10:11 +02001688 compile_decrease_except_level(comp);
Damien429d7192013-10-04 19:53:11 +01001689 EMIT(end_finally);
1690 }
1691}
1692
Damien George969a6b32014-12-10 22:07:04 +00001693STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01001694 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Damiend99b0522013-12-21 18:17:45 +00001695 mp_parse_node_t *nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +00001696 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);
Damien429d7192013-10-04 19:53:11 +01001697 assert(n > 0);
1698
1699 // compile in a nested fashion
1700 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1701}
1702
pohmelie81ebba72016-01-27 23:23:11 +03001703STATIC void compile_yield_from(compiler_t *comp) {
Damien Georgef4df3aa2016-01-09 23:59:52 +00001704 EMIT_ARG(get_iter, false);
pohmelie81ebba72016-01-27 23:23:11 +03001705 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1706 EMIT(yield_from);
1707}
1708
1709#if MICROPY_PY_ASYNC_AWAIT
1710STATIC void compile_await_object_method(compiler_t *comp, qstr method) {
Damien Georgedd11af22017-04-19 09:45:59 +10001711 EMIT_ARG(load_method, method, false);
pohmelie81ebba72016-01-27 23:23:11 +03001712 EMIT_ARG(call_method, 0, 0, 0);
1713 compile_yield_from(comp);
1714}
1715
1716STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1717 // comp->break_label |= MP_EMIT_BREAK_FROM_FOR;
1718
1719 qstr context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
1720 uint while_else_label = comp_next_label(comp);
1721 uint try_exception_label = comp_next_label(comp);
1722 uint try_else_label = comp_next_label(comp);
1723 uint try_finally_label = comp_next_label(comp);
1724
1725 compile_node(comp, pns->nodes[1]); // iterator
1726 compile_await_object_method(comp, MP_QSTR___aiter__);
1727 compile_store_id(comp, context);
1728
1729 START_BREAK_CONTINUE_BLOCK
1730
1731 EMIT_ARG(label_assign, continue_label);
1732
1733 EMIT_ARG(setup_except, try_exception_label);
1734 compile_increase_except_level(comp);
1735
1736 compile_load_id(comp, context);
1737 compile_await_object_method(comp, MP_QSTR___anext__);
1738 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
1739 EMIT(pop_block);
1740 EMIT_ARG(jump, try_else_label);
1741
1742 EMIT_ARG(label_assign, try_exception_label);
1743 EMIT(start_except_handler);
1744 EMIT(dup_top);
1745 EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration);
1746 EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
1747 EMIT_ARG(pop_jump_if, false, try_finally_label);
Damien Georgeb32c01b2016-09-28 11:52:13 +10001748 EMIT(pop_top); // pop exception instance
pohmelie81ebba72016-01-27 23:23:11 +03001749 EMIT(pop_except);
1750 EMIT_ARG(jump, while_else_label);
1751
1752 EMIT_ARG(label_assign, try_finally_label);
Damien Georgeb32c01b2016-09-28 11:52:13 +10001753 EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack
pohmelie81ebba72016-01-27 23:23:11 +03001754 compile_decrease_except_level(comp);
1755 EMIT(end_finally);
1756 EMIT(end_except_handler);
1757
1758 EMIT_ARG(label_assign, try_else_label);
1759 compile_node(comp, pns->nodes[2]); // body
1760
1761 EMIT_ARG(jump, continue_label);
1762 // break/continue apply to outer loop (if any) in the else block
1763 END_BREAK_CONTINUE_BLOCK
1764
1765 EMIT_ARG(label_assign, while_else_label);
1766 compile_node(comp, pns->nodes[3]); // else
1767
1768 EMIT_ARG(label_assign, break_label);
1769}
1770
1771STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) {
1772 if (n == 0) {
1773 // no more pre-bits, compile the body of the with
1774 compile_node(comp, body);
1775 } else {
1776 uint try_exception_label = comp_next_label(comp);
1777 uint no_reraise_label = comp_next_label(comp);
1778 uint try_else_label = comp_next_label(comp);
1779 uint end_label = comp_next_label(comp);
1780 qstr context;
1781
1782 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
1783 // this pre-bit is of the form "a as b"
1784 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
1785 compile_node(comp, pns->nodes[0]);
1786 context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
1787 compile_store_id(comp, context);
1788 compile_load_id(comp, context);
1789 compile_await_object_method(comp, MP_QSTR___aenter__);
1790 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
1791 } else {
1792 // this pre-bit is just an expression
1793 compile_node(comp, nodes[0]);
1794 context = MP_PARSE_NODE_LEAF_ARG(nodes[0]);
1795 compile_store_id(comp, context);
1796 compile_load_id(comp, context);
1797 compile_await_object_method(comp, MP_QSTR___aenter__);
1798 EMIT(pop_top);
1799 }
1800
1801 compile_load_id(comp, context);
Damien Georgedd11af22017-04-19 09:45:59 +10001802 EMIT_ARG(load_method, MP_QSTR___aexit__, false);
pohmelie81ebba72016-01-27 23:23:11 +03001803
1804 EMIT_ARG(setup_except, try_exception_label);
1805 compile_increase_except_level(comp);
1806 // compile additional pre-bits and the body
1807 compile_async_with_stmt_helper(comp, n - 1, nodes + 1, body);
1808 // finish this with block
1809 EMIT(pop_block);
1810 EMIT_ARG(jump, try_else_label); // jump over exception handler
1811
1812 EMIT_ARG(label_assign, try_exception_label); // start of exception handler
1813 EMIT(start_except_handler);
Damien Georgeb32c01b2016-09-28 11:52:13 +10001814
1815 // at this point the stack contains: ..., __aexit__, self, exc
1816 EMIT(dup_top);
1817 #if MICROPY_CPYTHON_COMPAT
1818 EMIT_ARG(load_attr, MP_QSTR___class__); // get type(exc)
1819 #else
1820 compile_load_id(comp, MP_QSTR_type);
pohmelie81ebba72016-01-27 23:23:11 +03001821 EMIT(rot_two);
Damien Georgeb32c01b2016-09-28 11:52:13 +10001822 EMIT_ARG(call_function, 1, 0, 0); // get type(exc)
1823 #endif
1824 EMIT(rot_two);
1825 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // dummy traceback value
1826 // at this point the stack contains: ..., __aexit__, self, type(exc), exc, None
pohmelie81ebba72016-01-27 23:23:11 +03001827 EMIT_ARG(call_method, 3, 0, 0);
Damien Georgeb32c01b2016-09-28 11:52:13 +10001828
pohmelie81ebba72016-01-27 23:23:11 +03001829 compile_yield_from(comp);
1830 EMIT_ARG(pop_jump_if, true, no_reraise_label);
1831 EMIT_ARG(raise_varargs, 0);
1832
1833 EMIT_ARG(label_assign, no_reraise_label);
1834 EMIT(pop_except);
1835 EMIT_ARG(jump, end_label);
1836
Damien Georgeb32c01b2016-09-28 11:52:13 +10001837 EMIT_ARG(adjust_stack_size, 3); // adjust for __aexit__, self, exc
pohmelie81ebba72016-01-27 23:23:11 +03001838 compile_decrease_except_level(comp);
1839 EMIT(end_finally);
1840 EMIT(end_except_handler);
1841
1842 EMIT_ARG(label_assign, try_else_label); // start of try-else handler
1843 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
1844 EMIT(dup_top);
1845 EMIT(dup_top);
1846 EMIT_ARG(call_method, 3, 0, 0);
1847 compile_yield_from(comp);
1848 EMIT(pop_top);
1849
1850 EMIT_ARG(label_assign, end_label);
1851
1852 }
1853}
1854
1855STATIC void compile_async_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1856 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
1857 mp_parse_node_t *nodes;
1858 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);
1859 assert(n > 0);
1860
1861 // compile in a nested fashion
1862 compile_async_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
1863}
1864
1865STATIC void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
1866 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[0]));
1867 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
1868 if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_funcdef) {
1869 // async def
1870 compile_funcdef(comp, pns0);
1871 scope_t *fscope = (scope_t*)pns0->nodes[4];
1872 fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
1873 } else if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_for_stmt) {
1874 // async for
1875 compile_async_for_stmt(comp, pns0);
1876 } else {
1877 // async with
1878 assert(MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_with_stmt);
1879 compile_async_with_stmt(comp, pns0);
1880 }
1881}
1882#endif
1883
Damien George969a6b32014-12-10 22:07:04 +00001884STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00001885 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
Damien5ac1b2e2013-10-18 19:58:12 +01001886 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
1887 // for REPL, evaluate then print the expression
Damien George542bd6b2015-03-26 14:42:40 +00001888 compile_load_id(comp, MP_QSTR___repl_print__);
Damien5ac1b2e2013-10-18 19:58:12 +01001889 compile_node(comp, pns->nodes[0]);
Damien George922ddd62014-04-09 12:43:17 +01001890 EMIT_ARG(call_function, 1, 0, 0);
Damien5ac1b2e2013-10-18 19:58:12 +01001891 EMIT(pop_top);
1892
Damien429d7192013-10-04 19:53:11 +01001893 } else {
Damien5ac1b2e2013-10-18 19:58:12 +01001894 // for non-REPL, evaluate then discard the expression
Damien George5042bce2014-05-25 22:06:06 +01001895 if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
Damien George7d414a12015-02-08 01:57:40 +00001896 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
Damien5ac1b2e2013-10-18 19:58:12 +01001897 // do nothing with a lonely constant
1898 } else {
1899 compile_node(comp, pns->nodes[0]); // just an expression
1900 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
1901 }
Damien429d7192013-10-04 19:53:11 +01001902 }
Damien Georgeb948de32015-10-08 14:26:01 +01001903 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
Damiend99b0522013-12-21 18:17:45 +00001904 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
1905 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
Damien429d7192013-10-04 19:53:11 +01001906 if (kind == PN_expr_stmt_augassign) {
1907 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
1908 compile_node(comp, pns1->nodes[1]); // rhs
Damiend99b0522013-12-21 18:17:45 +00001909 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
Damien Georged17926d2014-03-30 13:35:08 +01001910 mp_binary_op_t op;
Damiend99b0522013-12-21 18:17:45 +00001911 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
Damien Georged17926d2014-03-30 13:35:08 +01001912 case MP_TOKEN_DEL_PIPE_EQUAL: op = MP_BINARY_OP_INPLACE_OR; break;
1913 case MP_TOKEN_DEL_CARET_EQUAL: op = MP_BINARY_OP_INPLACE_XOR; break;
1914 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = MP_BINARY_OP_INPLACE_AND; break;
1915 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = MP_BINARY_OP_INPLACE_LSHIFT; break;
1916 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = MP_BINARY_OP_INPLACE_RSHIFT; break;
1917 case MP_TOKEN_DEL_PLUS_EQUAL: op = MP_BINARY_OP_INPLACE_ADD; break;
1918 case MP_TOKEN_DEL_MINUS_EQUAL: op = MP_BINARY_OP_INPLACE_SUBTRACT; break;
1919 case MP_TOKEN_DEL_STAR_EQUAL: op = MP_BINARY_OP_INPLACE_MULTIPLY; break;
1920 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
1921 case MP_TOKEN_DEL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
1922 case MP_TOKEN_DEL_PERCENT_EQUAL: op = MP_BINARY_OP_INPLACE_MODULO; break;
Damien Georged2d64f02015-01-14 21:32:42 +00001923 case MP_TOKEN_DEL_DBL_STAR_EQUAL: default: op = MP_BINARY_OP_INPLACE_POWER; break;
Damien429d7192013-10-04 19:53:11 +01001924 }
Damien George7e5fb242014-02-01 22:18:47 +00001925 EMIT_ARG(binary_op, op);
Damien429d7192013-10-04 19:53:11 +01001926 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
1927 } else if (kind == PN_expr_stmt_assign_list) {
Damiend99b0522013-12-21 18:17:45 +00001928 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
Damien Georgeb948de32015-10-08 14:26:01 +01001929 compile_node(comp, pns1->nodes[rhs]); // rhs
Damien429d7192013-10-04 19:53:11 +01001930 // following CPython, we store left-most first
1931 if (rhs > 0) {
1932 EMIT(dup_top);
1933 }
1934 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1935 for (int i = 0; i < rhs; i++) {
1936 if (i + 1 < rhs) {
1937 EMIT(dup_top);
1938 }
Damien Georgeb948de32015-10-08 14:26:01 +01001939 c_assign(comp, pns1->nodes[i], ASSIGN_STORE); // middle store
Damien429d7192013-10-04 19:53:11 +01001940 }
Damien George0bb97132015-02-27 14:25:47 +00001941 } else {
Damien Georgeb948de32015-10-08 14:26:01 +01001942 plain_assign:
Damien George42e0c592015-03-14 13:11:35 +00001943 if (MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
Damien Georgeb948de32015-10-08 14:26:01 +01001944 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
Damiend99b0522013-12-21 18:17:45 +00001945 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
Damien Georgeb948de32015-10-08 14:26:01 +01001946 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 2
Damiend99b0522013-12-21 18:17:45 +00001947 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
Damien George65dc9602015-08-14 12:24:11 +01001948 // optimisation for a, b = c, d
Damien Georgeb948de32015-10-08 14:26:01 +01001949 mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];
Damien George4dea9222015-04-09 15:29:54 +00001950 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien George495d7812014-04-08 17:51:47 +01001951 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
1952 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) {
1953 // can't optimise when it's a star expression on the lhs
1954 goto no_optimisation;
1955 }
Damien429d7192013-10-04 19:53:11 +01001956 compile_node(comp, pns10->nodes[0]); // rhs
1957 compile_node(comp, pns10->nodes[1]); // rhs
1958 EMIT(rot_two);
1959 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1960 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
Damien George42e0c592015-03-14 13:11:35 +00001961 } else if (MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
Damien Georgeb948de32015-10-08 14:26:01 +01001962 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
Damiend99b0522013-12-21 18:17:45 +00001963 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
Damien Georgeb948de32015-10-08 14:26:01 +01001964 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 3
Damiend99b0522013-12-21 18:17:45 +00001965 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
Damien George65dc9602015-08-14 12:24:11 +01001966 // optimisation for a, b, c = d, e, f
Damien Georgeb948de32015-10-08 14:26:01 +01001967 mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];
Damien George4dea9222015-04-09 15:29:54 +00001968 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Damien George495d7812014-04-08 17:51:47 +01001969 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
1970 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)
1971 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) {
1972 // can't optimise when it's a star expression on the lhs
1973 goto no_optimisation;
1974 }
Damien429d7192013-10-04 19:53:11 +01001975 compile_node(comp, pns10->nodes[0]); // rhs
1976 compile_node(comp, pns10->nodes[1]); // rhs
1977 compile_node(comp, pns10->nodes[2]); // rhs
1978 EMIT(rot_three);
1979 EMIT(rot_two);
1980 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
1981 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
1982 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
1983 } else {
Damien George495d7812014-04-08 17:51:47 +01001984 no_optimisation:
Damien Georgeb948de32015-10-08 14:26:01 +01001985 compile_node(comp, pns->nodes[1]); // rhs
Damien429d7192013-10-04 19:53:11 +01001986 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
1987 }
Damien429d7192013-10-04 19:53:11 +01001988 }
Damien Georgeb948de32015-10-08 14:26:01 +01001989 } else {
1990 goto plain_assign;
Damien429d7192013-10-04 19:53:11 +01001991 }
1992}
1993
Damien George6be0b0a2014-08-15 14:30:52 +01001994STATIC void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, mp_binary_op_t binary_op) {
Damiend99b0522013-12-21 18:17:45 +00001995 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01001996 compile_node(comp, pns->nodes[0]);
1997 for (int i = 1; i < num_nodes; i += 1) {
1998 compile_node(comp, pns->nodes[i]);
Damien Georgeb9791222014-01-23 00:34:21 +00001999 EMIT_ARG(binary_op, binary_op);
Damien429d7192013-10-04 19:53:11 +01002000 }
2001}
2002
Damien George969a6b32014-12-10 22:07:04 +00002003STATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00002004 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
2005 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002006
Damien George6f355fd2014-04-10 14:11:31 +01002007 uint l_fail = comp_next_label(comp);
2008 uint l_end = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002009 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
2010 compile_node(comp, pns->nodes[0]); // success value
Damien Georgeb9791222014-01-23 00:34:21 +00002011 EMIT_ARG(jump, l_end);
2012 EMIT_ARG(label_assign, l_fail);
Damien Georged66ae182014-04-10 17:28:54 +00002013 EMIT_ARG(adjust_stack_size, -1); // adjust stack size
Damien429d7192013-10-04 19:53:11 +01002014 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
Damien Georgeb9791222014-01-23 00:34:21 +00002015 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002016}
2017
Damien George969a6b32014-12-10 22:07:04 +00002018STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George36db6bc2014-05-07 17:24:22 +01002019 if (comp->pass == MP_PASS_SCOPE) {
Damien429d7192013-10-04 19:53:11 +01002020 // create a new scope for this lambda
Damiend99b0522013-12-21 18:17:45 +00002021 scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002022 // store the lambda scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002023 pns->nodes[2] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002024 }
2025
2026 // get the scope for this lambda
2027 scope_t *this_scope = (scope_t*)pns->nodes[2];
2028
Damien George2c838942015-11-17 14:00:14 +00002029 // compile the lambda definition
2030 compile_funcdef_lambdef(comp, this_scope, pns->nodes[0], PN_varargslist);
Damien429d7192013-10-04 19:53:11 +01002031}
2032
Damien George7711afb2015-02-28 15:10:18 +00002033STATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns, bool cond) {
Damien George6f355fd2014-04-10 14:11:31 +01002034 uint l_end = comp_next_label(comp);
Damiend99b0522013-12-21 18:17:45 +00002035 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002036 for (int i = 0; i < n; i += 1) {
2037 compile_node(comp, pns->nodes[i]);
2038 if (i + 1 < n) {
Damien George7711afb2015-02-28 15:10:18 +00002039 EMIT_ARG(jump_if_or_pop, cond, l_end);
Damien429d7192013-10-04 19:53:11 +01002040 }
2041 }
Damien Georgeb9791222014-01-23 00:34:21 +00002042 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002043}
2044
Damien George7711afb2015-02-28 15:10:18 +00002045STATIC void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
2046 compile_or_and_test(comp, pns, true);
2047}
2048
Damien George969a6b32014-12-10 22:07:04 +00002049STATIC void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George7711afb2015-02-28 15:10:18 +00002050 compile_or_and_test(comp, pns, false);
Damien429d7192013-10-04 19:53:11 +01002051}
2052
Damien George969a6b32014-12-10 22:07:04 +00002053STATIC void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002054 compile_node(comp, pns->nodes[0]);
Damien Georged17926d2014-03-30 13:35:08 +01002055 EMIT_ARG(unary_op, MP_UNARY_OP_NOT);
Damien429d7192013-10-04 19:53:11 +01002056}
2057
Damien George969a6b32014-12-10 22:07:04 +00002058STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00002059 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002060 compile_node(comp, pns->nodes[0]);
2061 bool multi = (num_nodes > 3);
Damien George6f355fd2014-04-10 14:11:31 +01002062 uint l_fail = 0;
Damien429d7192013-10-04 19:53:11 +01002063 if (multi) {
Damienb05d7072013-10-05 13:37:10 +01002064 l_fail = comp_next_label(comp);
Damien429d7192013-10-04 19:53:11 +01002065 }
2066 for (int i = 1; i + 1 < num_nodes; i += 2) {
2067 compile_node(comp, pns->nodes[i + 1]);
2068 if (i + 2 < num_nodes) {
2069 EMIT(dup_top);
2070 EMIT(rot_three);
2071 }
Damien George7e5fb242014-02-01 22:18:47 +00002072 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
Damien Georged17926d2014-03-30 13:35:08 +01002073 mp_binary_op_t op;
Damien George7e5fb242014-02-01 22:18:47 +00002074 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
Damien Georged17926d2014-03-30 13:35:08 +01002075 case MP_TOKEN_OP_LESS: op = MP_BINARY_OP_LESS; break;
2076 case MP_TOKEN_OP_MORE: op = MP_BINARY_OP_MORE; break;
2077 case MP_TOKEN_OP_DBL_EQUAL: op = MP_BINARY_OP_EQUAL; break;
2078 case MP_TOKEN_OP_LESS_EQUAL: op = MP_BINARY_OP_LESS_EQUAL; break;
2079 case MP_TOKEN_OP_MORE_EQUAL: op = MP_BINARY_OP_MORE_EQUAL; break;
2080 case MP_TOKEN_OP_NOT_EQUAL: op = MP_BINARY_OP_NOT_EQUAL; break;
Damien Georged2d64f02015-01-14 21:32:42 +00002081 case MP_TOKEN_KW_IN: default: op = MP_BINARY_OP_IN; break;
Damien George7e5fb242014-02-01 22:18:47 +00002082 }
2083 EMIT_ARG(binary_op, op);
Damien George0bb97132015-02-27 14:25:47 +00002084 } else {
2085 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])); // should be
Damiend99b0522013-12-21 18:17:45 +00002086 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
2087 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
Damien429d7192013-10-04 19:53:11 +01002088 if (kind == PN_comp_op_not_in) {
Damien Georged17926d2014-03-30 13:35:08 +01002089 EMIT_ARG(binary_op, MP_BINARY_OP_NOT_IN);
Damien George0bb97132015-02-27 14:25:47 +00002090 } else {
2091 assert(kind == PN_comp_op_is); // should be
Damiend99b0522013-12-21 18:17:45 +00002092 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
Damien Georged17926d2014-03-30 13:35:08 +01002093 EMIT_ARG(binary_op, MP_BINARY_OP_IS);
Damien429d7192013-10-04 19:53:11 +01002094 } else {
Damien Georged17926d2014-03-30 13:35:08 +01002095 EMIT_ARG(binary_op, MP_BINARY_OP_IS_NOT);
Damien429d7192013-10-04 19:53:11 +01002096 }
Damien429d7192013-10-04 19:53:11 +01002097 }
Damien429d7192013-10-04 19:53:11 +01002098 }
2099 if (i + 2 < num_nodes) {
Damien George63f38322015-02-28 15:04:06 +00002100 EMIT_ARG(jump_if_or_pop, false, l_fail);
Damien429d7192013-10-04 19:53:11 +01002101 }
2102 }
2103 if (multi) {
Damien George6f355fd2014-04-10 14:11:31 +01002104 uint l_end = comp_next_label(comp);
Damien Georgeb9791222014-01-23 00:34:21 +00002105 EMIT_ARG(jump, l_end);
2106 EMIT_ARG(label_assign, l_fail);
Damien Georged66ae182014-04-10 17:28:54 +00002107 EMIT_ARG(adjust_stack_size, 1);
Damien429d7192013-10-04 19:53:11 +01002108 EMIT(rot_two);
2109 EMIT(pop_top);
Damien Georgeb9791222014-01-23 00:34:21 +00002110 EMIT_ARG(label_assign, l_end);
Damien429d7192013-10-04 19:53:11 +01002111 }
2112}
2113
Damien George969a6b32014-12-10 22:07:04 +00002114STATIC void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George9d181f62014-04-27 16:55:27 +01002115 compile_syntax_error(comp, (mp_parse_node_t)pns, "*x must be assignment target");
Damien429d7192013-10-04 19:53:11 +01002116}
2117
Damien George969a6b32014-12-10 22:07:04 +00002118STATIC void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georged17926d2014-03-30 13:35:08 +01002119 c_binary_op(comp, pns, MP_BINARY_OP_OR);
Damien429d7192013-10-04 19:53:11 +01002120}
2121
Damien George969a6b32014-12-10 22:07:04 +00002122STATIC void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georged17926d2014-03-30 13:35:08 +01002123 c_binary_op(comp, pns, MP_BINARY_OP_XOR);
Damien429d7192013-10-04 19:53:11 +01002124}
2125
Damien George969a6b32014-12-10 22:07:04 +00002126STATIC void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georged17926d2014-03-30 13:35:08 +01002127 c_binary_op(comp, pns, MP_BINARY_OP_AND);
Damien429d7192013-10-04 19:53:11 +01002128}
2129
Krzysztof Blazewicza040fb82017-04-27 21:32:50 +02002130STATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00002131 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damien429d7192013-10-04 19:53:11 +01002132 compile_node(comp, pns->nodes[0]);
2133 for (int i = 1; i + 1 < num_nodes; i += 2) {
2134 compile_node(comp, pns->nodes[i + 1]);
Krzysztof Blazewicz91a385d2017-04-27 21:33:11 +02002135 mp_binary_op_t op;
2136 mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]);
2137 switch (tok) {
2138 case MP_TOKEN_OP_PLUS: op = MP_BINARY_OP_ADD; break;
2139 case MP_TOKEN_OP_MINUS: op = MP_BINARY_OP_SUBTRACT; break;
2140 case MP_TOKEN_OP_STAR: op = MP_BINARY_OP_MULTIPLY; break;
2141 case MP_TOKEN_OP_DBL_SLASH: op = MP_BINARY_OP_FLOOR_DIVIDE; break;
2142 case MP_TOKEN_OP_SLASH: op = MP_BINARY_OP_TRUE_DIVIDE; break;
2143 case MP_TOKEN_OP_PERCENT: op = MP_BINARY_OP_MODULO; break;
2144 case MP_TOKEN_OP_DBL_LESS: op = MP_BINARY_OP_LSHIFT; break;
2145 default:
2146 assert(tok == MP_TOKEN_OP_DBL_MORE);
2147 op = MP_BINARY_OP_RSHIFT;
2148 break;
Damien429d7192013-10-04 19:53:11 +01002149 }
Krzysztof Blazewicz91a385d2017-04-27 21:33:11 +02002150 EMIT_ARG(binary_op, op);
Damien429d7192013-10-04 19:53:11 +01002151 }
2152}
2153
Damien George969a6b32014-12-10 22:07:04 +00002154STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002155 compile_node(comp, pns->nodes[1]);
Damien George0291a622017-07-09 13:18:14 +10002156 mp_unary_op_t op;
Krzysztof Blazewicz91a385d2017-04-27 21:33:11 +02002157 mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2158 switch (tok) {
2159 case MP_TOKEN_OP_PLUS: op = MP_UNARY_OP_POSITIVE; break;
2160 case MP_TOKEN_OP_MINUS: op = MP_UNARY_OP_NEGATIVE; break;
2161 default:
2162 assert(tok == MP_TOKEN_OP_TILDE);
2163 op = MP_UNARY_OP_INVERT;
2164 break;
Damien429d7192013-10-04 19:53:11 +01002165 }
Krzysztof Blazewicz91a385d2017-04-27 21:33:11 +02002166 EMIT_ARG(unary_op, op);
Damien429d7192013-10-04 19:53:11 +01002167}
2168
pohmelie81ebba72016-01-27 23:23:11 +03002169STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George53359422017-04-18 22:52:18 +10002170 // compile the subject of the expression
2171 compile_node(comp, pns->nodes[0]);
Damien George35e2a4e2014-02-05 00:51:47 +00002172
Damien George53359422017-04-18 22:52:18 +10002173 // compile_atom_expr_await may call us with a NULL node
2174 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
2175 return;
2176 }
2177
2178 // get the array of trailers (known to be an array of PARSE_NODE_STRUCT)
2179 size_t num_trail = 1;
2180 mp_parse_node_struct_t **pns_trail = (mp_parse_node_struct_t**)&pns->nodes[1];
2181 if (MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_atom_expr_trailers) {
2182 num_trail = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_trail[0]);
2183 pns_trail = (mp_parse_node_struct_t**)&pns_trail[0]->nodes[0];
2184 }
2185
2186 // the current index into the array of trailers
2187 size_t i = 0;
2188
2189 // handle special super() call
2190 if (comp->scope_cur->kind == SCOPE_FUNCTION
2191 && MP_PARSE_NODE_IS_ID(pns->nodes[0])
2192 && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super
2193 && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren
2194 && MP_PARSE_NODE_IS_NULL(pns_trail[0]->nodes[0])) {
2195 // at this point we have matched "super()" within a function
2196
2197 // load the class for super to search for a parent
2198 compile_load_id(comp, MP_QSTR___class__);
2199
2200 // look for first argument to function (assumes it's "self")
2201 bool found = false;
2202 id_info_t *id = &comp->scope_cur->id_info[0];
2203 for (size_t n = comp->scope_cur->id_info_len; n > 0; --n, ++id) {
2204 if (id->flags & ID_FLAG_IS_PARAM) {
2205 // first argument found; load it
2206 compile_load_id(comp, id->qst);
2207 found = true;
2208 break;
2209 }
2210 }
2211 if (!found) {
2212 compile_syntax_error(comp, (mp_parse_node_t)pns_trail[0],
2213 "super() can't find self"); // really a TypeError
2214 return;
2215 }
2216
Damien Georgedd11af22017-04-19 09:45:59 +10002217 if (num_trail >= 3
2218 && MP_PARSE_NODE_STRUCT_KIND(pns_trail[1]) == PN_trailer_period
2219 && MP_PARSE_NODE_STRUCT_KIND(pns_trail[2]) == PN_trailer_paren) {
2220 // optimisation for method calls super().f(...), to eliminate heap allocation
2221 mp_parse_node_struct_t *pns_period = pns_trail[1];
2222 mp_parse_node_struct_t *pns_paren = pns_trail[2];
2223 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), true);
2224 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
2225 i = 3;
2226 } else {
2227 // a super() call
2228 EMIT_ARG(call_function, 2, 0, 0);
2229 i = 1;
2230 }
Damien George53359422017-04-18 22:52:18 +10002231 }
2232
2233 // compile the remaining trailers
2234 for (; i < num_trail; i++) {
2235 if (i + 1 < num_trail
2236 && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i]) == PN_trailer_period
2237 && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i + 1]) == PN_trailer_paren) {
2238 // optimisation for method calls a.f(...), following PyPy
2239 mp_parse_node_struct_t *pns_period = pns_trail[i];
2240 mp_parse_node_struct_t *pns_paren = pns_trail[i + 1];
Damien Georgedd11af22017-04-19 09:45:59 +10002241 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false);
Damien George53359422017-04-18 22:52:18 +10002242 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
2243 i += 1;
2244 } else {
2245 // node is one of: trailer_paren, trailer_bracket, trailer_period
2246 compile_node(comp, (mp_parse_node_t)pns_trail[i]);
2247 }
2248 }
pohmelie81ebba72016-01-27 23:23:11 +03002249}
Damien George3acaa282016-03-16 13:04:51 +00002250
pohmelie81ebba72016-01-27 23:23:11 +03002251STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
2252 compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power
2253 EMIT_ARG(binary_op, MP_BINARY_OP_POWER);
Damien George35e2a4e2014-02-05 00:51:47 +00002254}
2255
Paul Sokolovsky520e2f52014-02-12 18:31:30 +02002256STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) {
Damien429d7192013-10-04 19:53:11 +01002257 // function to call is on top of stack
2258
Damien George2c0842b2014-04-27 16:46:51 +01002259 // get the list of arguments
2260 mp_parse_node_t *args;
Damien Georgedfe944c2015-02-13 02:29:46 +00002261 int n_args = mp_parse_node_extract_list(&pn_arglist, PN_arglist, &args);
Damien429d7192013-10-04 19:53:11 +01002262
Damien George2c0842b2014-04-27 16:46:51 +01002263 // compile the arguments
2264 // Rather than calling compile_node on the list, we go through the list of args
2265 // explicitly here so that we can count the number of arguments and give sensible
2266 // error messages.
2267 int n_positional = n_positional_extra;
2268 uint n_keyword = 0;
2269 uint star_flags = 0;
Delio Brignolie6978a42015-09-17 12:07:06 +02002270 mp_parse_node_struct_t *star_args_node = NULL, *dblstar_args_node = NULL;
Damien George2c0842b2014-04-27 16:46:51 +01002271 for (int i = 0; i < n_args; i++) {
2272 if (MP_PARSE_NODE_IS_STRUCT(args[i])) {
2273 mp_parse_node_struct_t *pns_arg = (mp_parse_node_struct_t*)args[i];
2274 if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_star) {
2275 if (star_flags & MP_EMIT_STAR_FLAG_SINGLE) {
2276 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple *x");
2277 return;
2278 }
2279 star_flags |= MP_EMIT_STAR_FLAG_SINGLE;
Delio Brignolie6978a42015-09-17 12:07:06 +02002280 star_args_node = pns_arg;
Damien George2c0842b2014-04-27 16:46:51 +01002281 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_dbl_star) {
2282 if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) {
2283 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple **x");
2284 return;
2285 }
2286 star_flags |= MP_EMIT_STAR_FLAG_DOUBLE;
Delio Brignolie6978a42015-09-17 12:07:06 +02002287 dblstar_args_node = pns_arg;
Damien George2c0842b2014-04-27 16:46:51 +01002288 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) {
Damien Georgeb948de32015-10-08 14:26:01 +01002289 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_comp_for)) {
Damien George2c0842b2014-04-27 16:46:51 +01002290 if (!MP_PARSE_NODE_IS_ID(pns_arg->nodes[0])) {
2291 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "LHS of keyword arg must be an id");
2292 return;
2293 }
Damien George59fba2d2015-06-25 14:42:13 +00002294 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]));
Damien Georgeb948de32015-10-08 14:26:01 +01002295 compile_node(comp, pns_arg->nodes[1]);
Damien George2c0842b2014-04-27 16:46:51 +01002296 n_keyword += 1;
2297 } else {
Damien George2c0842b2014-04-27 16:46:51 +01002298 compile_comprehension(comp, pns_arg, SCOPE_GEN_EXPR);
2299 n_positional++;
2300 }
2301 } else {
2302 goto normal_argument;
2303 }
2304 } else {
2305 normal_argument:
Damien George1e70fda2017-06-14 18:18:01 +10002306 if (star_flags) {
2307 compile_syntax_error(comp, args[i], "non-keyword arg after */**");
2308 return;
2309 }
Damien George2c0842b2014-04-27 16:46:51 +01002310 if (n_keyword > 0) {
2311 compile_syntax_error(comp, args[i], "non-keyword arg after keyword arg");
2312 return;
2313 }
2314 compile_node(comp, args[i]);
2315 n_positional++;
2316 }
Damien429d7192013-10-04 19:53:11 +01002317 }
2318
Delio Brignolie6978a42015-09-17 12:07:06 +02002319 // compile the star/double-star arguments if we had them
Damien Georgefbcaf0e2015-09-23 11:47:01 +01002320 // if we had one but not the other then we load "null" as a place holder
2321 if (star_flags != 0) {
2322 if (star_args_node == NULL) {
2323 EMIT(load_null);
2324 } else {
2325 compile_node(comp, star_args_node->nodes[0]);
2326 }
2327 if (dblstar_args_node == NULL) {
2328 EMIT(load_null);
2329 } else {
2330 compile_node(comp, dblstar_args_node->nodes[0]);
2331 }
Delio Brignolie6978a42015-09-17 12:07:06 +02002332 }
2333
Damien George2c0842b2014-04-27 16:46:51 +01002334 // emit the function/method call
Damien429d7192013-10-04 19:53:11 +01002335 if (is_method_call) {
Damien George2c0842b2014-04-27 16:46:51 +01002336 EMIT_ARG(call_method, n_positional, n_keyword, star_flags);
Damien429d7192013-10-04 19:53:11 +01002337 } else {
Damien George2c0842b2014-04-27 16:46:51 +01002338 EMIT_ARG(call_function, n_positional, n_keyword, star_flags);
Damien429d7192013-10-04 19:53:11 +01002339 }
Damien429d7192013-10-04 19:53:11 +01002340}
2341
Damien429d7192013-10-04 19:53:11 +01002342// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
Damien George6be0b0a2014-08-15 14:30:52 +01002343STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
Damiend99b0522013-12-21 18:17:45 +00002344 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
2345 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
2346 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01002347
Damien George36db6bc2014-05-07 17:24:22 +01002348 if (comp->pass == MP_PASS_SCOPE) {
Damien429d7192013-10-04 19:53:11 +01002349 // create a new scope for this comprehension
Damiend99b0522013-12-21 18:17:45 +00002350 scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002351 // store the comprehension scope so the compiling function (this one) can use it at each pass
Damiend99b0522013-12-21 18:17:45 +00002352 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
Damien429d7192013-10-04 19:53:11 +01002353 }
2354
2355 // get the scope for this comprehension
2356 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
2357
2358 // compile the comprehension
2359 close_over_variables_etc(comp, this_scope, 0, 0);
2360
2361 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
Damien George4d2bab12017-02-10 15:39:33 +11002362 if (kind == SCOPE_GEN_EXPR) {
2363 EMIT_ARG(get_iter, false);
2364 }
Damien George922ddd62014-04-09 12:43:17 +01002365 EMIT_ARG(call_function, 1, 0, 0);
Damien429d7192013-10-04 19:53:11 +01002366}
2367
Damien George969a6b32014-12-10 22:07:04 +00002368STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00002369 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002370 // an empty tuple
Damiend99b0522013-12-21 18:17:45 +00002371 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
Damien George93b37262016-01-07 13:07:52 +00002372 } else {
2373 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
Damiend99b0522013-12-21 18:17:45 +00002374 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2375 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
2376 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
2377 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
2378 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002379 // tuple of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002380 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002381 c_tuple(comp, pns->nodes[0], NULL);
Damiend99b0522013-12-21 18:17:45 +00002382 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002383 // tuple of many items
Damien429d7192013-10-04 19:53:11 +01002384 c_tuple(comp, pns->nodes[0], pns2);
Damiend99b0522013-12-21 18:17:45 +00002385 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002386 // generator expression
2387 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
2388 } else {
2389 // tuple with 2 items
2390 goto tuple_with_2_items;
2391 }
2392 } else {
2393 // tuple with 2 items
2394 tuple_with_2_items:
Damiend99b0522013-12-21 18:17:45 +00002395 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
Damien429d7192013-10-04 19:53:11 +01002396 }
Damien429d7192013-10-04 19:53:11 +01002397 }
2398}
2399
Damien George969a6b32014-12-10 22:07:04 +00002400STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00002401 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002402 // empty list
Damien Georgeb9791222014-01-23 00:34:21 +00002403 EMIT_ARG(build_list, 0);
Damiend99b0522013-12-21 18:17:45 +00002404 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
2405 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
2406 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
2407 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
2408 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
Damien429d7192013-10-04 19:53:11 +01002409 // list of one item, with trailing comma
Damiend99b0522013-12-21 18:17:45 +00002410 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
Damien429d7192013-10-04 19:53:11 +01002411 compile_node(comp, pns2->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002412 EMIT_ARG(build_list, 1);
Damiend99b0522013-12-21 18:17:45 +00002413 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
Damien429d7192013-10-04 19:53:11 +01002414 // list of many items
2415 compile_node(comp, pns2->nodes[0]);
2416 compile_generic_all_nodes(comp, pns3);
Damien Georgeb9791222014-01-23 00:34:21 +00002417 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
Damiend99b0522013-12-21 18:17:45 +00002418 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
Damien429d7192013-10-04 19:53:11 +01002419 // list comprehension
2420 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
2421 } else {
2422 // list with 2 items
2423 goto list_with_2_items;
2424 }
2425 } else {
2426 // list with 2 items
2427 list_with_2_items:
2428 compile_node(comp, pns2->nodes[0]);
2429 compile_node(comp, pns2->nodes[1]);
Damien Georgeb9791222014-01-23 00:34:21 +00002430 EMIT_ARG(build_list, 2);
Damien429d7192013-10-04 19:53:11 +01002431 }
2432 } else {
2433 // list with 1 item
2434 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002435 EMIT_ARG(build_list, 1);
Damien429d7192013-10-04 19:53:11 +01002436 }
2437}
2438
Damien George969a6b32014-12-10 22:07:04 +00002439STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00002440 mp_parse_node_t pn = pns->nodes[0];
2441 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002442 // empty dict
Damien Georgeb9791222014-01-23 00:34:21 +00002443 EMIT_ARG(build_map, 0);
Damiend99b0522013-12-21 18:17:45 +00002444 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2445 pns = (mp_parse_node_struct_t*)pn;
2446 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
Damien429d7192013-10-04 19:53:11 +01002447 // dict with one element
Damien Georgeb9791222014-01-23 00:34:21 +00002448 EMIT_ARG(build_map, 1);
Damien429d7192013-10-04 19:53:11 +01002449 compile_node(comp, pn);
2450 EMIT(store_map);
Damiend99b0522013-12-21 18:17:45 +00002451 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
2452 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
2453 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
2454 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
Damien429d7192013-10-04 19:53:11 +01002455 // dict/set with multiple elements
2456
2457 // get tail elements (2nd, 3rd, ...)
Damiend99b0522013-12-21 18:17:45 +00002458 mp_parse_node_t *nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +00002459 int n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
Damien429d7192013-10-04 19:53:11 +01002460
2461 // first element sets whether it's a dict or set
2462 bool is_dict;
Damien Georgee37dcaa2014-12-27 17:07:16 +00002463 if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002464 // a dictionary
Damien Georgeb9791222014-01-23 00:34:21 +00002465 EMIT_ARG(build_map, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002466 compile_node(comp, pns->nodes[0]);
2467 EMIT(store_map);
2468 is_dict = true;
2469 } else {
2470 // a set
2471 compile_node(comp, pns->nodes[0]); // 1st value of set
2472 is_dict = false;
2473 }
2474
2475 // process rest of elements
2476 for (int i = 0; i < n; i++) {
Damien George50912e72015-01-20 11:55:10 +00002477 mp_parse_node_t pn_i = nodes[i];
2478 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn_i, PN_dictorsetmaker_item);
2479 compile_node(comp, pn_i);
Damien429d7192013-10-04 19:53:11 +01002480 if (is_dict) {
2481 if (!is_key_value) {
Damien Georgef9b0e642017-03-29 12:44:27 +11002482 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
2483 compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax");
2484 } else {
2485 compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dict");
2486 }
Damien429d7192013-10-04 19:53:11 +01002487 return;
2488 }
2489 EMIT(store_map);
2490 } else {
2491 if (is_key_value) {
Damien Georgef9b0e642017-03-29 12:44:27 +11002492 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
2493 compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax");
2494 } else {
2495 compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
2496 }
Damien429d7192013-10-04 19:53:11 +01002497 return;
2498 }
2499 }
2500 }
2501
Damien Georgee37dcaa2014-12-27 17:07:16 +00002502 #if MICROPY_PY_BUILTINS_SET
Damien429d7192013-10-04 19:53:11 +01002503 // if it's a set, build it
2504 if (!is_dict) {
Damien Georgeb9791222014-01-23 00:34:21 +00002505 EMIT_ARG(build_set, 1 + n);
Damien429d7192013-10-04 19:53:11 +01002506 }
Damien Georgee37dcaa2014-12-27 17:07:16 +00002507 #endif
Damien George0bb97132015-02-27 14:25:47 +00002508 } else {
2509 assert(MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for); // should be
Damien429d7192013-10-04 19:53:11 +01002510 // dict/set comprehension
Damien Georgee37dcaa2014-12-27 17:07:16 +00002511 if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
Damien429d7192013-10-04 19:53:11 +01002512 // a dictionary comprehension
2513 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
2514 } else {
2515 // a set comprehension
2516 compile_comprehension(comp, pns, SCOPE_SET_COMP);
2517 }
Damien429d7192013-10-04 19:53:11 +01002518 }
2519 } else {
2520 // set with one element
2521 goto set_with_one_element;
2522 }
2523 } else {
2524 // set with one element
2525 set_with_one_element:
Damien Georgee37dcaa2014-12-27 17:07:16 +00002526 #if MICROPY_PY_BUILTINS_SET
Damien429d7192013-10-04 19:53:11 +01002527 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002528 EMIT_ARG(build_set, 1);
Damien Georgee37dcaa2014-12-27 17:07:16 +00002529 #else
2530 assert(0);
2531 #endif
Damien429d7192013-10-04 19:53:11 +01002532 }
2533}
2534
Damien George969a6b32014-12-10 22:07:04 +00002535STATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgebbcd49a2014-02-06 20:30:16 +00002536 compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
Damien429d7192013-10-04 19:53:11 +01002537}
2538
Damien George969a6b32014-12-10 22:07:04 +00002539STATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002540 // object who's index we want is on top of stack
2541 compile_node(comp, pns->nodes[0]); // the index
Damien George729f7b42014-04-17 22:10:53 +01002542 EMIT(load_subscr);
Damien429d7192013-10-04 19:53:11 +01002543}
2544
Damien George969a6b32014-12-10 22:07:04 +00002545STATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002546 // object who's attribute we want is on top of stack
Damien Georgeb9791222014-01-23 00:34:21 +00002547 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
Damien429d7192013-10-04 19:53:11 +01002548}
2549
Damien George83204f32014-12-27 17:20:41 +00002550#if MICROPY_PY_BUILTINS_SLICE
Damien George969a6b32014-12-10 22:07:04 +00002551STATIC void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damiend99b0522013-12-21 18:17:45 +00002552 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
2553 mp_parse_node_t pn = pns->nodes[0];
2554 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002555 // [?:]
Damien Georgeb9791222014-01-23 00:34:21 +00002556 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
2557 EMIT_ARG(build_slice, 2);
Damiend99b0522013-12-21 18:17:45 +00002558 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
2559 pns = (mp_parse_node_struct_t*)pn;
2560 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
Damien Georgeb9791222014-01-23 00:34:21 +00002561 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002562 pn = pns->nodes[0];
Damiend99b0522013-12-21 18:17:45 +00002563 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002564 // [?::]
Damien Georgeb9791222014-01-23 00:34:21 +00002565 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002566 } else {
2567 // [?::x]
2568 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002569 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002570 }
Damiend99b0522013-12-21 18:17:45 +00002571 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
Damien429d7192013-10-04 19:53:11 +01002572 compile_node(comp, pns->nodes[0]);
Damiend99b0522013-12-21 18:17:45 +00002573 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2574 pns = (mp_parse_node_struct_t*)pns->nodes[1];
2575 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
2576 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien429d7192013-10-04 19:53:11 +01002577 // [?:x:]
Damien Georgeb9791222014-01-23 00:34:21 +00002578 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002579 } else {
2580 // [?:x:x]
2581 compile_node(comp, pns->nodes[0]);
Damien Georgeb9791222014-01-23 00:34:21 +00002582 EMIT_ARG(build_slice, 3);
Damien429d7192013-10-04 19:53:11 +01002583 }
2584 } else {
2585 // [?:x]
2586 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002587 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002588 }
2589 } else {
2590 // [?:x]
2591 compile_node(comp, pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002592 EMIT_ARG(build_slice, 2);
Damien429d7192013-10-04 19:53:11 +01002593 }
2594}
2595
Damien George969a6b32014-12-10 22:07:04 +00002596STATIC void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002597 compile_node(comp, pns->nodes[0]); // start of slice
Damiend99b0522013-12-21 18:17:45 +00002598 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
2599 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
Damien429d7192013-10-04 19:53:11 +01002600}
2601
Damien George969a6b32014-12-10 22:07:04 +00002602STATIC void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien Georgeb9791222014-01-23 00:34:21 +00002603 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002604 compile_subscript_3_helper(comp, pns);
2605}
Damien George83204f32014-12-27 17:20:41 +00002606#endif // MICROPY_PY_BUILTINS_SLICE
Damien429d7192013-10-04 19:53:11 +01002607
Damien George969a6b32014-12-10 22:07:04 +00002608STATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien429d7192013-10-04 19:53:11 +01002609 // if this is called then we are compiling a dict key:value pair
2610 compile_node(comp, pns->nodes[1]); // value
2611 compile_node(comp, pns->nodes[0]); // key
2612}
2613
Damien George969a6b32014-12-10 22:07:04 +00002614STATIC void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien6cdd3af2013-10-05 18:08:26 +01002615 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
Damien429d7192013-10-04 19:53:11 +01002616 // store class object into class name
Damien George542bd6b2015-03-26 14:42:40 +00002617 compile_store_id(comp, cname);
Damien429d7192013-10-04 19:53:11 +01002618}
2619
Damien George969a6b32014-12-10 22:07:04 +00002620STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George0e3329a2014-04-11 13:10:21 +00002621 if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {
Damien Georgeb7ffdcc2014-04-08 16:41:02 +01002622 compile_syntax_error(comp, (mp_parse_node_t)pns, "'yield' outside function");
Damien429d7192013-10-04 19:53:11 +01002623 return;
2624 }
Damiend99b0522013-12-21 18:17:45 +00002625 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damien Georgeb9791222014-01-23 00:34:21 +00002626 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002627 EMIT(yield_value);
Damiend99b0522013-12-21 18:17:45 +00002628 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
2629 pns = (mp_parse_node_struct_t*)pns->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002630 compile_node(comp, pns->nodes[0]);
pohmelie81ebba72016-01-27 23:23:11 +03002631 compile_yield_from(comp);
Damien429d7192013-10-04 19:53:11 +01002632 } else {
2633 compile_node(comp, pns->nodes[0]);
2634 EMIT(yield_value);
2635 }
2636}
2637
pohmelie81ebba72016-01-27 23:23:11 +03002638#if MICROPY_PY_ASYNC_AWAIT
2639STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pns) {
2640 if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {
2641 compile_syntax_error(comp, (mp_parse_node_t)pns, "'await' outside function");
2642 return;
2643 }
2644 compile_atom_expr_normal(comp, pns);
2645 compile_yield_from(comp);
2646}
2647#endif
2648
Damien George52552552017-02-24 13:43:43 +11002649STATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) {
2650 #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
2651 // nodes are 32-bit pointers, but need to extract 64-bit object
2652 return (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32);
2653 #else
2654 return (mp_obj_t)pns->nodes[0];
2655 #endif
Damien George65ef6b72015-01-14 21:17:27 +00002656}
2657
Damien George7d414a12015-02-08 01:57:40 +00002658STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
Damien George52552552017-02-24 13:43:43 +11002659 EMIT_ARG(load_const_obj, get_const_object(pns));
Damien George7d414a12015-02-08 01:57:40 +00002660}
2661
Damiend99b0522013-12-21 18:17:45 +00002662typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
Damien George3ff16ff2016-05-20 12:38:15 +01002663STATIC const compile_function_t compile_function[] = {
Damien George71019ae2017-02-15 10:58:05 +11002664// only define rules with a compile function
Damien429d7192013-10-04 19:53:11 +01002665#define c(f) compile_##f
Damien George1dc76af2014-02-26 16:57:08 +00002666#define DEF_RULE(rule, comp, kind, ...) comp,
Damien George71019ae2017-02-15 10:58:05 +11002667#define DEF_RULE_NC(rule, kind, ...)
Damien George51dfcb42015-01-01 20:27:54 +00002668#include "py/grammar.h"
Damien429d7192013-10-04 19:53:11 +01002669#undef c
2670#undef DEF_RULE
Damien George71019ae2017-02-15 10:58:05 +11002671#undef DEF_RULE_NC
Damien George7d414a12015-02-08 01:57:40 +00002672 compile_const_object,
Damien429d7192013-10-04 19:53:11 +01002673};
2674
Damien George6be0b0a2014-08-15 14:30:52 +01002675STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
Damiend99b0522013-12-21 18:17:45 +00002676 if (MP_PARSE_NODE_IS_NULL(pn)) {
Damien429d7192013-10-04 19:53:11 +01002677 // pass
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02002678 } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
Damien George40f3c022014-07-03 13:25:24 +01002679 mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
Damien Georgeea235202016-02-11 22:30:53 +00002680 #if MICROPY_DYNAMIC_COMPILER
2681 mp_uint_t sign_mask = -(1 << (mp_dynamic_compiler.small_int_bits - 1));
2682 if ((arg & sign_mask) == 0 || (arg & sign_mask) == sign_mask) {
2683 // integer fits in target runtime's small-int
2684 EMIT_ARG(load_const_small_int, arg);
2685 } else {
2686 // integer doesn't fit, so create a multi-precision int object
2687 // (but only create the actual object on the last pass)
2688 if (comp->pass != MP_PASS_EMIT) {
2689 EMIT_ARG(load_const_obj, mp_const_none);
2690 } else {
2691 EMIT_ARG(load_const_obj, mp_obj_new_int_from_ll(arg));
2692 }
2693 }
2694 #else
Paul Sokolovsky56e5ef22014-02-22 16:39:45 +02002695 EMIT_ARG(load_const_small_int, arg);
Damien Georgeea235202016-02-11 22:30:53 +00002696 #endif
Damiend99b0522013-12-21 18:17:45 +00002697 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
Damien George831137b2015-12-17 13:13:18 +00002698 uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
Damiend99b0522013-12-21 18:17:45 +00002699 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
Damien George542bd6b2015-03-26 14:42:40 +00002700 case MP_PARSE_NODE_ID: compile_load_id(comp, arg); break;
Damien George59fba2d2015-06-25 14:42:13 +00002701 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg); break;
2702 case MP_PARSE_NODE_BYTES:
2703 // only create and load the actual bytes object on the last pass
2704 if (comp->pass != MP_PASS_EMIT) {
2705 EMIT_ARG(load_const_obj, mp_const_none);
2706 } else {
Damien Georgec3f64d92015-11-27 12:23:18 +00002707 size_t len;
Damien George59fba2d2015-06-25 14:42:13 +00002708 const byte *data = qstr_data(arg, &len);
2709 EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len));
2710 }
2711 break;
Damien Georged2d64f02015-01-14 21:32:42 +00002712 case MP_PARSE_NODE_TOKEN: default:
Damiend99b0522013-12-21 18:17:45 +00002713 if (arg == MP_TOKEN_NEWLINE) {
Damien91d387d2013-10-09 15:09:52 +01002714 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
Damien5ac1b2e2013-10-18 19:58:12 +01002715 // or when single_input lets through a NEWLINE (user enters a blank line)
Damien91d387d2013-10-09 15:09:52 +01002716 // do nothing
2717 } else {
Damien Georgeb9791222014-01-23 00:34:21 +00002718 EMIT_ARG(load_const_tok, arg);
Damien91d387d2013-10-09 15:09:52 +01002719 }
2720 break;
Damien429d7192013-10-04 19:53:11 +01002721 }
2722 } else {
Damiend99b0522013-12-21 18:17:45 +00002723 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien George41125902015-03-26 16:44:14 +00002724 EMIT_ARG(set_source_line, pns->source_line);
Damien George71019ae2017-02-15 10:58:05 +11002725 assert(MP_PARSE_NODE_STRUCT_KIND(pns) <= PN_const_object);
Damien George65ef6b72015-01-14 21:17:27 +00002726 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
Damien Georgedeaa57a2016-10-12 10:20:48 +11002727 f(comp, pns);
Damien429d7192013-10-04 19:53:11 +01002728 }
2729}
2730
Damien George2ac4af62014-08-15 16:45:41 +01002731STATIC 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) {
Damien George9a569122015-11-23 16:50:42 +00002732 // check that **kw is last
2733 if ((comp->scope_cur->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
2734 compile_syntax_error(comp, pn, "invalid syntax");
2735 return;
2736 }
2737
Damien George2827d622014-04-27 15:50:52 +01002738 qstr param_name = MP_QSTR_NULL;
2739 uint param_flag = ID_FLAG_IS_PARAM;
Damiend99b0522013-12-21 18:17:45 +00002740 if (MP_PARSE_NODE_IS_ID(pn)) {
2741 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
Damien George8b19db02014-04-11 23:25:34 +01002742 if (comp->have_star) {
Damien George2827d622014-04-27 15:50:52 +01002743 // comes after a star, so counts as a keyword-only parameter
2744 comp->scope_cur->num_kwonly_args += 1;
Damien429d7192013-10-04 19:53:11 +01002745 } else {
Damien George2827d622014-04-27 15:50:52 +01002746 // comes before a star, so counts as a positional parameter
2747 comp->scope_cur->num_pos_args += 1;
Damien429d7192013-10-04 19:53:11 +01002748 }
Damienb14de212013-10-06 00:28:28 +01002749 } else {
Damiend99b0522013-12-21 18:17:45 +00002750 assert(MP_PARSE_NODE_IS_STRUCT(pn));
2751 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2752 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
2753 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien George8b19db02014-04-11 23:25:34 +01002754 if (comp->have_star) {
Damien George2827d622014-04-27 15:50:52 +01002755 // comes after a star, so counts as a keyword-only parameter
2756 comp->scope_cur->num_kwonly_args += 1;
Damienb14de212013-10-06 00:28:28 +01002757 } else {
Damien George2827d622014-04-27 15:50:52 +01002758 // comes before a star, so counts as a positional parameter
2759 comp->scope_cur->num_pos_args += 1;
Damienb14de212013-10-06 00:28:28 +01002760 }
Damiend99b0522013-12-21 18:17:45 +00002761 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
Damien George9a569122015-11-23 16:50:42 +00002762 if (comp->have_star) {
2763 // more than one star
2764 compile_syntax_error(comp, pn, "invalid syntax");
2765 return;
2766 }
Damien George8b19db02014-04-11 23:25:34 +01002767 comp->have_star = true;
Damien George2827d622014-04-27 15:50:52 +01002768 param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM;
Damiend99b0522013-12-21 18:17:45 +00002769 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002770 // bare star
2771 // TODO see http://www.python.org/dev/peps/pep-3102/
Damienb14de212013-10-06 00:28:28 +01002772 //assert(comp->scope_cur->num_dict_params == 0);
Damiend99b0522013-12-21 18:17:45 +00002773 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
Damienb14de212013-10-06 00:28:28 +01002774 // named star
Damien George8725f8f2014-02-15 19:33:11 +00002775 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002776 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien George0bb97132015-02-27 14:25:47 +00002777 } else {
2778 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)); // should be
Damien George8b19db02014-04-11 23:25:34 +01002779 // named star with possible annotation
Damien George8725f8f2014-02-15 19:33:11 +00002780 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
Damiend99b0522013-12-21 18:17:45 +00002781 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2782 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damienb14de212013-10-06 00:28:28 +01002783 }
Damien George0bb97132015-02-27 14:25:47 +00002784 } else {
2785 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star); // should be
Damiend99b0522013-12-21 18:17:45 +00002786 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Damien George2827d622014-04-27 15:50:52 +01002787 param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM;
Damien George8725f8f2014-02-15 19:33:11 +00002788 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
Damien429d7192013-10-04 19:53:11 +01002789 }
Damien429d7192013-10-04 19:53:11 +01002790 }
2791
Damien George2827d622014-04-27 15:50:52 +01002792 if (param_name != MP_QSTR_NULL) {
Damien429d7192013-10-04 19:53:11 +01002793 bool added;
2794 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
2795 if (!added) {
Damien George9d181f62014-04-27 16:55:27 +01002796 compile_syntax_error(comp, pn, "name reused for argument");
Damien429d7192013-10-04 19:53:11 +01002797 return;
2798 }
Damien429d7192013-10-04 19:53:11 +01002799 id_info->kind = ID_INFO_KIND_LOCAL;
Damien George2827d622014-04-27 15:50:52 +01002800 id_info->flags = param_flag;
Damien429d7192013-10-04 19:53:11 +01002801 }
2802}
2803
Damien George2827d622014-04-27 15:50:52 +01002804STATIC void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
Damien George2ac4af62014-08-15 16:45:41 +01002805 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star);
Damien429d7192013-10-04 19:53:11 +01002806}
2807
Damien George2827d622014-04-27 15:50:52 +01002808STATIC void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
Damien George2ac4af62014-08-15 16:45:41 +01002809 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star);
2810}
2811
Damien Georgeea5b59b2015-09-04 16:44:14 +01002812#if MICROPY_EMIT_NATIVE
Damien George2ac4af62014-08-15 16:45:41 +01002813STATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn) {
2814 if (!MP_PARSE_NODE_IS_STRUCT(pn)) {
2815 // no annotation
2816 return;
2817 }
2818
2819 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2820 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_name) {
2821 // named parameter with possible annotation
2822 // fallthrough
2823 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_star) {
2824 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
2825 // named star with possible annotation
2826 pns = (mp_parse_node_struct_t*)pns->nodes[0];
2827 // fallthrough
2828 } else {
2829 // no annotation
2830 return;
2831 }
Damien Georgee49153f2016-10-11 12:29:54 +11002832 } else {
2833 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star);
Damien George2ac4af62014-08-15 16:45:41 +01002834 // double star with possible annotation
2835 // fallthrough
Damien George2ac4af62014-08-15 16:45:41 +01002836 }
2837
2838 mp_parse_node_t pn_annotation = pns->nodes[1];
2839
2840 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien George2ac4af62014-08-15 16:45:41 +01002841 qstr param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
2842 id_info_t *id_info = scope_find(comp->scope_cur, param_name);
2843 assert(id_info != NULL);
2844
Damien Georgeea5b59b2015-09-04 16:44:14 +01002845 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
2846 qstr arg_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
2847 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ARG, id_info->local_num, arg_type);
2848 } else {
2849 compile_syntax_error(comp, pn_annotation, "parameter annotation must be an identifier");
Damien George2ac4af62014-08-15 16:45:41 +01002850 }
Damien George2ac4af62014-08-15 16:45:41 +01002851 }
Damien429d7192013-10-04 19:53:11 +01002852}
Damien Georgeea5b59b2015-09-04 16:44:14 +01002853#endif // MICROPY_EMIT_NATIVE
Damien429d7192013-10-04 19:53:11 +01002854
Damien Georgea8312432015-12-18 01:37:55 +00002855STATIC 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) {
2856 uint l_top = comp_next_label(comp);
2857 uint l_end = comp_next_label(comp);
2858 EMIT_ARG(label_assign, l_top);
2859 EMIT_ARG(for_iter, l_end);
2860 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
2861 mp_parse_node_t pn_iter = pns_comp_for->nodes[2];
2862
Damien429d7192013-10-04 19:53:11 +01002863 tail_recursion:
Damiend99b0522013-12-21 18:17:45 +00002864 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
Damien429d7192013-10-04 19:53:11 +01002865 // no more nested if/for; compile inner expression
2866 compile_node(comp, pn_inner_expr);
Damien Georgea5624bf2016-09-18 23:59:47 +10002867 if (comp->scope_cur->kind == SCOPE_GEN_EXPR) {
Damien429d7192013-10-04 19:53:11 +01002868 EMIT(yield_value);
2869 EMIT(pop_top);
Damien Georgea5624bf2016-09-18 23:59:47 +10002870 } else {
Damien George088740e2017-01-17 15:27:37 +11002871 EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5);
Damien429d7192013-10-04 19:53:11 +01002872 }
Damien George0dd6a592017-04-22 21:43:42 +10002873 } else if (MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_if) {
Damien429d7192013-10-04 19:53:11 +01002874 // if condition
Damiend99b0522013-12-21 18:17:45 +00002875 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002876 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
2877 pn_iter = pns_comp_if->nodes[1];
2878 goto tail_recursion;
Damien George0bb97132015-02-27 14:25:47 +00002879 } else {
Damien George0dd6a592017-04-22 21:43:42 +10002880 assert(MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_for); // should be
Damien429d7192013-10-04 19:53:11 +01002881 // for loop
Damiend99b0522013-12-21 18:17:45 +00002882 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
Damien429d7192013-10-04 19:53:11 +01002883 compile_node(comp, pns_comp_for2->nodes[1]);
Damien George6e769da2017-01-17 14:32:50 +11002884 EMIT_ARG(get_iter, true);
Damien Georgea8312432015-12-18 01:37:55 +00002885 compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1);
Damien429d7192013-10-04 19:53:11 +01002886 }
Damien Georgea8312432015-12-18 01:37:55 +00002887
2888 EMIT_ARG(jump, l_top);
2889 EMIT_ARG(label_assign, l_end);
Damien George30b42dd2017-01-17 15:30:18 +11002890 EMIT(for_iter_end);
Damien429d7192013-10-04 19:53:11 +01002891}
2892
Damien George1463c1f2014-04-25 23:52:57 +01002893STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
Damien George65dc9602015-08-14 12:24:11 +01002894#if MICROPY_ENABLE_DOC_STRING
Damien429d7192013-10-04 19:53:11 +01002895 // see http://www.python.org/dev/peps/pep-0257/
2896
2897 // look for the first statement
Damiend99b0522013-12-21 18:17:45 +00002898 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damiene388f102013-12-12 15:24:38 +00002899 // a statement; fall through
Damiend99b0522013-12-21 18:17:45 +00002900 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
Damiene388f102013-12-12 15:24:38 +00002901 // file input; find the first non-newline node
Damiend99b0522013-12-21 18:17:45 +00002902 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
2903 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
Damiene388f102013-12-12 15:24:38 +00002904 for (int i = 0; i < num_nodes; i++) {
2905 pn = pns->nodes[i];
Damiend99b0522013-12-21 18:17:45 +00002906 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)) {
Damiene388f102013-12-12 15:24:38 +00002907 // not a newline, so this is the first statement; finish search
2908 break;
2909 }
2910 }
2911 // 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
Damiend99b0522013-12-21 18:17:45 +00002912 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
Damiene388f102013-12-12 15:24:38 +00002913 // a list of statements; get the first one
Damiend99b0522013-12-21 18:17:45 +00002914 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
Damien429d7192013-10-04 19:53:11 +01002915 } else {
2916 return;
2917 }
2918
2919 // check the first statement for a doc string
Damiend99b0522013-12-21 18:17:45 +00002920 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
Damien George4dea9222015-04-09 15:29:54 +00002921 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
Damien George5042bce2014-05-25 22:06:06 +01002922 if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])
2923 && MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)
Damien George52552552017-02-24 13:43:43 +11002924 || (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)
2925 && MP_OBJ_IS_STR(get_const_object((mp_parse_node_struct_t*)pns->nodes[0])))) {
Damien George5042bce2014-05-25 22:06:06 +01002926 // compile the doc string
2927 compile_node(comp, pns->nodes[0]);
2928 // store the doc string
Damien George542bd6b2015-03-26 14:42:40 +00002929 compile_store_id(comp, MP_QSTR___doc__);
Damien429d7192013-10-04 19:53:11 +01002930 }
2931 }
Damien Georgeff8dd3f2015-01-20 12:47:20 +00002932#else
2933 (void)comp;
2934 (void)pn;
Damien George1463c1f2014-04-25 23:52:57 +01002935#endif
Damien429d7192013-10-04 19:53:11 +01002936}
2937
Damien George1463c1f2014-04-25 23:52:57 +01002938STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
Damien429d7192013-10-04 19:53:11 +01002939 comp->pass = pass;
2940 comp->scope_cur = scope;
Damien Georged94bc672017-06-22 15:05:58 +10002941 comp->next_label = 0;
Damien Georgeb9791222014-01-23 00:34:21 +00002942 EMIT_ARG(start_pass, pass, scope);
Damien429d7192013-10-04 19:53:11 +01002943
Damien George36db6bc2014-05-07 17:24:22 +01002944 if (comp->pass == MP_PASS_SCOPE) {
Damien George8dcc0c72014-03-27 10:55:21 +00002945 // reset maximum stack sizes in scope
2946 // they will be computed in this first pass
Damien429d7192013-10-04 19:53:11 +01002947 scope->stack_size = 0;
Damien George8dcc0c72014-03-27 10:55:21 +00002948 scope->exc_stack_size = 0;
Damien429d7192013-10-04 19:53:11 +01002949 }
2950
Damien429d7192013-10-04 19:53:11 +01002951 // compile
Damien Georged02c6d82014-01-15 22:14:03 +00002952 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
2953 assert(scope->kind == SCOPE_MODULE);
2954 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2955 compile_node(comp, pns->nodes[0]); // compile the expression
2956 EMIT(return_value);
2957 } else if (scope->kind == SCOPE_MODULE) {
Damien5ac1b2e2013-10-18 19:58:12 +01002958 if (!comp->is_repl) {
2959 check_for_doc_string(comp, scope->pn);
2960 }
Damien429d7192013-10-04 19:53:11 +01002961 compile_node(comp, scope->pn);
Damien Georgeb9791222014-01-23 00:34:21 +00002962 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01002963 EMIT(return_value);
2964 } else if (scope->kind == SCOPE_FUNCTION) {
Damiend99b0522013-12-21 18:17:45 +00002965 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
2966 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
2967 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien429d7192013-10-04 19:53:11 +01002968
2969 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01002970 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien George36db6bc2014-05-07 17:24:22 +01002971 if (comp->pass == MP_PASS_SCOPE) {
Damien George8b19db02014-04-11 23:25:34 +01002972 comp->have_star = false;
Damien429d7192013-10-04 19:53:11 +01002973 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
Damien Georgeea5b59b2015-09-04 16:44:14 +01002974 }
2975 #if MICROPY_EMIT_NATIVE
2976 else if (scope->emit_options == MP_EMIT_OPT_VIPER) {
Damien George2ac4af62014-08-15 16:45:41 +01002977 // compile annotations; only needed on latter compiler passes
Damien Georgeea5b59b2015-09-04 16:44:14 +01002978 // only needed for viper emitter
Damien429d7192013-10-04 19:53:11 +01002979
Damien George2ac4af62014-08-15 16:45:41 +01002980 // argument annotations
2981 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_annotations);
2982
2983 // pns->nodes[2] is return/whole function annotation
Damien Georgea5190a72014-08-15 22:39:08 +01002984 mp_parse_node_t pn_annotation = pns->nodes[2];
2985 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
Damien Georgeea5b59b2015-09-04 16:44:14 +01002986 // nodes[2] can be null or a test-expr
2987 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
2988 qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
2989 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_RETURN, 0, ret_type);
2990 } else {
2991 compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier");
Damien George2ac4af62014-08-15 16:45:41 +01002992 }
2993 }
Damien George2ac4af62014-08-15 16:45:41 +01002994 }
Damien Georgeea5b59b2015-09-04 16:44:14 +01002995 #endif // MICROPY_EMIT_NATIVE
Damien429d7192013-10-04 19:53:11 +01002996
2997 compile_node(comp, pns->nodes[3]); // 3 is function body
2998 // emit return if it wasn't the last opcode
Damien415eb6f2013-10-05 12:19:06 +01002999 if (!EMIT(last_emit_was_return_value)) {
Damien Georgeb9791222014-01-23 00:34:21 +00003000 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01003001 EMIT(return_value);
3002 }
3003 } else if (scope->kind == SCOPE_LAMBDA) {
Damiend99b0522013-12-21 18:17:45 +00003004 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
3005 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
3006 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
Damien429d7192013-10-04 19:53:11 +01003007
3008 // work out number of parameters, keywords and default parameters, and add them to the id_info array
Damien6cdd3af2013-10-05 18:08:26 +01003009 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
Damien George36db6bc2014-05-07 17:24:22 +01003010 if (comp->pass == MP_PASS_SCOPE) {
Damien George8b19db02014-04-11 23:25:34 +01003011 comp->have_star = false;
Damien429d7192013-10-04 19:53:11 +01003012 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
3013 }
3014
3015 compile_node(comp, pns->nodes[1]); // 1 is lambda body
Damien George0e3329a2014-04-11 13:10:21 +00003016
3017 // if the lambda is a generator, then we return None, not the result of the expression of the lambda
3018 if (scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
3019 EMIT(pop_top);
3020 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
3021 }
Damien429d7192013-10-04 19:53:11 +01003022 EMIT(return_value);
3023 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
3024 // a bit of a hack at the moment
3025
Damiend99b0522013-12-21 18:17:45 +00003026 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
3027 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
3028 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
3029 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
3030 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
Damien429d7192013-10-04 19:53:11 +01003031
Damien George708c0732014-04-27 19:23:46 +01003032 // We need a unique name for the comprehension argument (the iterator).
3033 // CPython uses .0, but we should be able to use anything that won't
3034 // clash with a user defined variable. Best to use an existing qstr,
3035 // so we use the blank qstr.
Damien George708c0732014-04-27 19:23:46 +01003036 qstr qstr_arg = MP_QSTR_;
Damien George36db6bc2014-05-07 17:24:22 +01003037 if (comp->pass == MP_PASS_SCOPE) {
Damien429d7192013-10-04 19:53:11 +01003038 bool added;
3039 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
3040 assert(added);
3041 id_info->kind = ID_INFO_KIND_LOCAL;
Damien George2827d622014-04-27 15:50:52 +01003042 scope->num_pos_args = 1;
Damien429d7192013-10-04 19:53:11 +01003043 }
3044
3045 if (scope->kind == SCOPE_LIST_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00003046 EMIT_ARG(build_list, 0);
Damien429d7192013-10-04 19:53:11 +01003047 } else if (scope->kind == SCOPE_DICT_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00003048 EMIT_ARG(build_map, 0);
Damien Georgee37dcaa2014-12-27 17:07:16 +00003049 #if MICROPY_PY_BUILTINS_SET
Damien429d7192013-10-04 19:53:11 +01003050 } else if (scope->kind == SCOPE_SET_COMP) {
Damien Georgeb9791222014-01-23 00:34:21 +00003051 EMIT_ARG(build_set, 0);
Damien Georgee37dcaa2014-12-27 17:07:16 +00003052 #endif
Damien429d7192013-10-04 19:53:11 +01003053 }
3054
Damien George088740e2017-01-17 15:27:37 +11003055 // There are 4 slots on the stack for the iterator, and the first one is
3056 // NULL to indicate that the second one points to the iterator object.
Damien George4d2bab12017-02-10 15:39:33 +11003057 if (scope->kind == SCOPE_GEN_EXPR) {
Damien George60656ea2017-03-23 16:36:08 +11003058 // TODO static assert that MP_OBJ_ITER_BUF_NSLOTS == 4
Damien George4d2bab12017-02-10 15:39:33 +11003059 EMIT(load_null);
3060 compile_load_id(comp, qstr_arg);
3061 EMIT(load_null);
3062 EMIT(load_null);
3063 } else {
3064 compile_load_id(comp, qstr_arg);
3065 EMIT_ARG(get_iter, true);
3066 }
Damien George6e769da2017-01-17 14:32:50 +11003067
Damien Georgea8312432015-12-18 01:37:55 +00003068 compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0);
Damien429d7192013-10-04 19:53:11 +01003069
3070 if (scope->kind == SCOPE_GEN_EXPR) {
Damien Georgeb9791222014-01-23 00:34:21 +00003071 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01003072 }
3073 EMIT(return_value);
3074 } else {
3075 assert(scope->kind == SCOPE_CLASS);
Damiend99b0522013-12-21 18:17:45 +00003076 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
3077 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
3078 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
Damien429d7192013-10-04 19:53:11 +01003079
Damien George36db6bc2014-05-07 17:24:22 +01003080 if (comp->pass == MP_PASS_SCOPE) {
Damien429d7192013-10-04 19:53:11 +01003081 bool added;
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003082 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
Damien429d7192013-10-04 19:53:11 +01003083 assert(added);
3084 id_info->kind = ID_INFO_KIND_LOCAL;
Damien429d7192013-10-04 19:53:11 +01003085 }
3086
Damien George542bd6b2015-03-26 14:42:40 +00003087 compile_load_id(comp, MP_QSTR___name__);
3088 compile_store_id(comp, MP_QSTR___module__);
Damien George59fba2d2015-06-25 14:42:13 +00003089 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
Damien George542bd6b2015-03-26 14:42:40 +00003090 compile_store_id(comp, MP_QSTR___qualname__);
Damien429d7192013-10-04 19:53:11 +01003091
3092 check_for_doc_string(comp, pns->nodes[2]);
3093 compile_node(comp, pns->nodes[2]); // 2 is class body
3094
Damien Georgeeb7bfcb2014-01-04 15:57:35 +00003095 id_info_t *id = scope_find(scope, MP_QSTR___class__);
Damien429d7192013-10-04 19:53:11 +01003096 assert(id != NULL);
3097 if (id->kind == ID_INFO_KIND_LOCAL) {
Damien Georgeb9791222014-01-23 00:34:21 +00003098 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Damien429d7192013-10-04 19:53:11 +01003099 } else {
Damien George542bd6b2015-03-26 14:42:40 +00003100 EMIT_LOAD_FAST(MP_QSTR___class__, id->local_num);
Damien429d7192013-10-04 19:53:11 +01003101 }
3102 EMIT(return_value);
3103 }
3104
Damien415eb6f2013-10-05 12:19:06 +01003105 EMIT(end_pass);
Damien George8dcc0c72014-03-27 10:55:21 +00003106
3107 // make sure we match all the exception levels
3108 assert(comp->cur_except_level == 0);
Damien826005c2013-10-05 23:17:28 +01003109}
3110
Damien Georgead297a12016-12-09 13:17:49 +11003111#if MICROPY_EMIT_INLINE_ASM
Damien George36db6bc2014-05-07 17:24:22 +01003112// requires 3 passes: SCOPE, CODE_SIZE, EMIT
Damien George1463c1f2014-04-25 23:52:57 +01003113STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
Damien826005c2013-10-05 23:17:28 +01003114 comp->pass = pass;
3115 comp->scope_cur = scope;
Damien Georged94bc672017-06-22 15:05:58 +10003116 comp->next_label = 0;
Damien826005c2013-10-05 23:17:28 +01003117
3118 if (scope->kind != SCOPE_FUNCTION) {
Damien George01039b52014-12-21 17:44:27 +00003119 compile_syntax_error(comp, MP_PARSE_NODE_NULL, "inline assembler must be a function");
Damien826005c2013-10-05 23:17:28 +01003120 return;
3121 }
3122
Damien George36db6bc2014-05-07 17:24:22 +01003123 if (comp->pass > MP_PASS_SCOPE) {
Damien Georgee920bab2016-12-09 21:23:17 +11003124 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, &comp->compile_error);
Damiena2f2f7d2013-10-06 00:14:13 +01003125 }
3126
Damien826005c2013-10-05 23:17:28 +01003127 // get the function definition parse node
Damiend99b0522013-12-21 18:17:45 +00003128 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
3129 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
3130 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
Damien826005c2013-10-05 23:17:28 +01003131
Damiend99b0522013-12-21 18:17:45 +00003132 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
Damien826005c2013-10-05 23:17:28 +01003133
Damiena2f2f7d2013-10-06 00:14:13 +01003134 // parameters are in pns->nodes[1]
Damien George36db6bc2014-05-07 17:24:22 +01003135 if (comp->pass == MP_PASS_CODE_SIZE) {
Damiend99b0522013-12-21 18:17:45 +00003136 mp_parse_node_t *pn_params;
Damien Georgedfe944c2015-02-13 02:29:46 +00003137 int n_params = mp_parse_node_extract_list(&pns->nodes[1], PN_typedargslist, &pn_params);
Damien George2827d622014-04-27 15:50:52 +01003138 scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
Damien George8dfbd2d2015-02-13 01:00:51 +00003139 if (comp->compile_error != MP_OBJ_NULL) {
3140 goto inline_asm_error;
3141 }
Damiena2f2f7d2013-10-06 00:14:13 +01003142 }
3143
Damien George8f54c082016-01-15 15:20:43 +00003144 // pns->nodes[2] is function return annotation
3145 mp_uint_t type_sig = MP_NATIVE_TYPE_INT;
3146 mp_parse_node_t pn_annotation = pns->nodes[2];
3147 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
3148 // nodes[2] can be null or a test-expr
3149 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
3150 qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
3151 switch (ret_type) {
3152 case MP_QSTR_object: type_sig = MP_NATIVE_TYPE_OBJ; break;
3153 case MP_QSTR_bool: type_sig = MP_NATIVE_TYPE_BOOL; break;
3154 case MP_QSTR_int: type_sig = MP_NATIVE_TYPE_INT; break;
3155 case MP_QSTR_uint: type_sig = MP_NATIVE_TYPE_UINT; break;
3156 default: compile_syntax_error(comp, pn_annotation, "unknown type"); return;
3157 }
3158 } else {
3159 compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier");
3160 }
3161 }
Damien826005c2013-10-05 23:17:28 +01003162
Damiend99b0522013-12-21 18:17:45 +00003163 mp_parse_node_t pn_body = pns->nodes[3]; // body
3164 mp_parse_node_t *nodes;
Damien Georgedfe944c2015-02-13 02:29:46 +00003165 int num = mp_parse_node_extract_list(&pn_body, PN_suite_block_stmts, &nodes);
Damien826005c2013-10-05 23:17:28 +01003166
Damien826005c2013-10-05 23:17:28 +01003167 for (int i = 0; i < num; i++) {
Damiend99b0522013-12-21 18:17:45 +00003168 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
3169 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
Damien Georgea26dc502014-04-12 17:54:52 +01003170 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_pass_stmt) {
3171 // no instructions
3172 continue;
Damien George3d7bf5d2015-02-16 17:46:28 +00003173 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_expr_stmt) {
Damien Georgea26dc502014-04-12 17:54:52 +01003174 // not an instruction; error
Damien George3d7bf5d2015-02-16 17:46:28 +00003175 not_an_instruction:
Damien George3665d0b2015-03-03 17:11:18 +00003176 compile_syntax_error(comp, nodes[i], "expecting an assembler instruction");
Damien Georgea26dc502014-04-12 17:54:52 +01003177 return;
3178 }
Damien George3d7bf5d2015-02-16 17:46:28 +00003179
3180 // check structure of parse node
Damiend99b0522013-12-21 18:17:45 +00003181 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
Damien George3d7bf5d2015-02-16 17:46:28 +00003182 if (!MP_PARSE_NODE_IS_NULL(pns2->nodes[1])) {
3183 goto not_an_instruction;
3184 }
Damiend99b0522013-12-21 18:17:45 +00003185 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
pohmelie81ebba72016-01-27 23:23:11 +03003186 if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_atom_expr_normal) {
Damien George3d7bf5d2015-02-16 17:46:28 +00003187 goto not_an_instruction;
3188 }
3189 if (!MP_PARSE_NODE_IS_ID(pns2->nodes[0])) {
3190 goto not_an_instruction;
3191 }
3192 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren)) {
3193 goto not_an_instruction;
3194 }
Damien George3d7bf5d2015-02-16 17:46:28 +00003195
3196 // parse node looks like an instruction
3197 // get instruction name and args
Damiend99b0522013-12-21 18:17:45 +00003198 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
3199 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
3200 mp_parse_node_t *pn_arg;
Damien Georgedfe944c2015-02-13 02:29:46 +00003201 int n_args = mp_parse_node_extract_list(&pns2->nodes[0], PN_arglist, &pn_arg);
Damien826005c2013-10-05 23:17:28 +01003202
3203 // emit instructions
Damien Georgee5f8a772014-04-21 13:33:15 +01003204 if (op == MP_QSTR_label) {
Damiend99b0522013-12-21 18:17:45 +00003205 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
Damien George3665d0b2015-03-03 17:11:18 +00003206 compile_syntax_error(comp, nodes[i], "'label' requires 1 argument");
Damien826005c2013-10-05 23:17:28 +01003207 return;
3208 }
Damien George6f355fd2014-04-10 14:11:31 +01003209 uint lab = comp_next_label(comp);
Damien George36db6bc2014-05-07 17:24:22 +01003210 if (pass > MP_PASS_SCOPE) {
Damien George9c5cabb2015-03-03 17:08:02 +00003211 if (!EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]))) {
3212 compile_syntax_error(comp, nodes[i], "label redefined");
3213 return;
3214 }
Damien826005c2013-10-05 23:17:28 +01003215 }
Damien Georgee5f8a772014-04-21 13:33:15 +01003216 } else if (op == MP_QSTR_align) {
3217 if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
Damien George3665d0b2015-03-03 17:11:18 +00003218 compile_syntax_error(comp, nodes[i], "'align' requires 1 argument");
Damien Georgee5f8a772014-04-21 13:33:15 +01003219 return;
3220 }
Damien George36db6bc2014-05-07 17:24:22 +01003221 if (pass > MP_PASS_SCOPE) {
Damien Georgedd53b122016-12-09 20:54:54 +11003222 mp_asm_base_align((mp_asm_base_t*)comp->emit_inline_asm,
3223 MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));
Damien Georgee5f8a772014-04-21 13:33:15 +01003224 }
3225 } else if (op == MP_QSTR_data) {
3226 if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
Damien George3665d0b2015-03-03 17:11:18 +00003227 compile_syntax_error(comp, nodes[i], "'data' requires at least 2 arguments");
Damien Georgee5f8a772014-04-21 13:33:15 +01003228 return;
3229 }
Damien George36db6bc2014-05-07 17:24:22 +01003230 if (pass > MP_PASS_SCOPE) {
Damien George40f3c022014-07-03 13:25:24 +01003231 mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
Damien George50912e72015-01-20 11:55:10 +00003232 for (uint j = 1; j < n_args; j++) {
3233 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[j])) {
Damien George3665d0b2015-03-03 17:11:18 +00003234 compile_syntax_error(comp, nodes[i], "'data' requires integer arguments");
Damien Georgee5f8a772014-04-21 13:33:15 +01003235 return;
3236 }
Damien Georgedd53b122016-12-09 20:54:54 +11003237 mp_asm_base_data((mp_asm_base_t*)comp->emit_inline_asm,
3238 bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j]));
Damien Georgee5f8a772014-04-21 13:33:15 +01003239 }
3240 }
Damien826005c2013-10-05 23:17:28 +01003241 } else {
Damien George36db6bc2014-05-07 17:24:22 +01003242 if (pass > MP_PASS_SCOPE) {
Damien Georgeb9791222014-01-23 00:34:21 +00003243 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
Damien826005c2013-10-05 23:17:28 +01003244 }
3245 }
Damien George8dfbd2d2015-02-13 01:00:51 +00003246
3247 if (comp->compile_error != MP_OBJ_NULL) {
3248 pns = pns2; // this is the parse node that had the error
3249 goto inline_asm_error;
3250 }
Damien826005c2013-10-05 23:17:28 +01003251 }
3252
Damien George36db6bc2014-05-07 17:24:22 +01003253 if (comp->pass > MP_PASS_SCOPE) {
Damien George8f54c082016-01-15 15:20:43 +00003254 EMIT_INLINE_ASM_ARG(end_pass, type_sig);
Damien Georgee920bab2016-12-09 21:23:17 +11003255
3256 if (comp->pass == MP_PASS_EMIT) {
3257 void *f = mp_asm_base_get_code((mp_asm_base_t*)comp->emit_inline_asm);
3258 mp_emit_glue_assign_native(comp->scope_cur->raw_code, MP_CODE_NATIVE_ASM,
3259 f, mp_asm_base_get_code_size((mp_asm_base_t*)comp->emit_inline_asm),
3260 NULL, comp->scope_cur->num_pos_args, 0, type_sig);
3261 }
Damien George8dfbd2d2015-02-13 01:00:51 +00003262 }
3263
3264 if (comp->compile_error != MP_OBJ_NULL) {
Damien Georgecfc4c332015-07-29 22:16:01 +00003265 // inline assembler had an error; set line for its exception
Damien George8dfbd2d2015-02-13 01:00:51 +00003266 inline_asm_error:
Damien Georgecfc4c332015-07-29 22:16:01 +00003267 comp->compile_error_line = pns->source_line;
Damienb05d7072013-10-05 13:37:10 +01003268 }
Damien429d7192013-10-04 19:53:11 +01003269}
Damien George094d4502014-04-02 17:31:27 +01003270#endif
Damien429d7192013-10-04 19:53:11 +01003271
Damien Georgeff8dd3f2015-01-20 12:47:20 +00003272STATIC void scope_compute_things(scope_t *scope) {
Alexander Steffen55f33242017-06-30 09:22:17 +02003273 // in MicroPython we put the *x parameter after all other parameters (except **y)
Damien George2827d622014-04-27 15:50:52 +01003274 if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {
3275 id_info_t *id_param = NULL;
3276 for (int i = scope->id_info_len - 1; i >= 0; i--) {
3277 id_info_t *id = &scope->id_info[i];
3278 if (id->flags & ID_FLAG_IS_STAR_PARAM) {
3279 if (id_param != NULL) {
3280 // swap star param with last param
3281 id_info_t temp = *id_param; *id_param = *id; *id = temp;
3282 }
3283 break;
3284 } else if (id_param == NULL && id->flags == ID_FLAG_IS_PARAM) {
3285 id_param = id;
3286 }
3287 }
3288 }
Damien George2827d622014-04-27 15:50:52 +01003289
Damien429d7192013-10-04 19:53:11 +01003290 // in functions, turn implicit globals into explicit globals
Damien George6baf76e2013-12-30 22:32:17 +00003291 // compute the index of each local
Damien429d7192013-10-04 19:53:11 +01003292 scope->num_locals = 0;
3293 for (int i = 0; i < scope->id_info_len; i++) {
3294 id_info_t *id = &scope->id_info[i];
Damien George7ff996c2014-09-08 23:05:16 +01003295 if (scope->kind == SCOPE_CLASS && id->qst == MP_QSTR___class__) {
Damien429d7192013-10-04 19:53:11 +01003296 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
3297 continue;
3298 }
Damien George3dea8c92016-09-30 12:34:05 +10003299 if (SCOPE_IS_FUNC_LIKE(scope->kind) && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
Damien429d7192013-10-04 19:53:11 +01003300 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
3301 }
Damien George2827d622014-04-27 15:50:52 +01003302 // params always count for 1 local, even if they are a cell
Damien George11d8cd52014-04-09 14:42:51 +01003303 if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) {
Damien George2827d622014-04-27 15:50:52 +01003304 id->local_num = scope->num_locals++;
Damien9ecbcff2013-12-11 00:41:43 +00003305 }
3306 }
3307
Damien George65dc9602015-08-14 12:24:11 +01003308 // compute the index of cell vars
Damien9ecbcff2013-12-11 00:41:43 +00003309 for (int i = 0; i < scope->id_info_len; i++) {
3310 id_info_t *id = &scope->id_info[i];
Alexander Steffen55f33242017-06-30 09:22:17 +02003311 // in MicroPython the cells come right after the fast locals
Damien George6baf76e2013-12-30 22:32:17 +00003312 // parameters are not counted here, since they remain at the start
3313 // of the locals, even if they are cell vars
Damien George11d8cd52014-04-09 14:42:51 +01003314 if (id->kind == ID_INFO_KIND_CELL && !(id->flags & ID_FLAG_IS_PARAM)) {
Damien George6baf76e2013-12-30 22:32:17 +00003315 id->local_num = scope->num_locals;
3316 scope->num_locals += 1;
3317 }
Damien9ecbcff2013-12-11 00:41:43 +00003318 }
Damien9ecbcff2013-12-11 00:41:43 +00003319
Damien George65dc9602015-08-14 12:24:11 +01003320 // compute the index of free vars
Damien9ecbcff2013-12-11 00:41:43 +00003321 // make sure they are in the order of the parent scope
3322 if (scope->parent != NULL) {
3323 int num_free = 0;
3324 for (int i = 0; i < scope->parent->id_info_len; i++) {
3325 id_info_t *id = &scope->parent->id_info[i];
3326 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
3327 for (int j = 0; j < scope->id_info_len; j++) {
3328 id_info_t *id2 = &scope->id_info[j];
Damien George7ff996c2014-09-08 23:05:16 +01003329 if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
Damien George11d8cd52014-04-09 14:42:51 +01003330 assert(!(id2->flags & ID_FLAG_IS_PARAM)); // free vars should not be params
Alexander Steffen55f33242017-06-30 09:22:17 +02003331 // in MicroPython the frees come first, before the params
Damien George6baf76e2013-12-30 22:32:17 +00003332 id2->local_num = num_free;
Damien9ecbcff2013-12-11 00:41:43 +00003333 num_free += 1;
3334 }
3335 }
3336 }
Damien429d7192013-10-04 19:53:11 +01003337 }
Alexander Steffen55f33242017-06-30 09:22:17 +02003338 // in MicroPython shift all other locals after the free locals
Damien George6baf76e2013-12-30 22:32:17 +00003339 if (num_free > 0) {
3340 for (int i = 0; i < scope->id_info_len; i++) {
3341 id_info_t *id = &scope->id_info[i];
Damien George2bf7c092014-04-09 15:26:46 +01003342 if (id->kind != ID_INFO_KIND_FREE || (id->flags & ID_FLAG_IS_PARAM)) {
Damien George6baf76e2013-12-30 22:32:17 +00003343 id->local_num += num_free;
3344 }
3345 }
Damien George2827d622014-04-27 15:50:52 +01003346 scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function
Damien George6baf76e2013-12-30 22:32:17 +00003347 scope->num_locals += num_free;
3348 }
Damien429d7192013-10-04 19:53:11 +01003349 }
Damien429d7192013-10-04 19:53:11 +01003350}
3351
Damien Georged4dba882015-11-13 13:38:28 +00003352#if !MICROPY_PERSISTENT_CODE_SAVE
3353STATIC
3354#endif
3355mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {
Damien George9d5e5c02015-09-24 13:15:57 +01003356 // put compiler state on the stack, it's relatively small
3357 compiler_t comp_state = {0};
3358 compiler_t *comp = &comp_state;
3359
Damien Georgecbd2f742014-01-19 11:48:48 +00003360 comp->source_file = source_file;
Damien5ac1b2e2013-10-18 19:58:12 +01003361 comp->is_repl = is_repl;
Damien Georged94bc672017-06-22 15:05:58 +10003362 comp->break_label = INVALID_LABEL;
3363 comp->continue_label = INVALID_LABEL;
Damien429d7192013-10-04 19:53:11 +01003364
Damien George62a3a282015-03-01 12:04:05 +00003365 // create the module scope
Damien George58e0f4a2015-09-23 10:50:43 +01003366 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, parse_tree->root, emit_opt);
Damien George62a3a282015-03-01 12:04:05 +00003367
Damien Georgea210c772015-03-26 15:49:53 +00003368 // create standard emitter; it's used at least for MP_PASS_SCOPE
Damien Georgea210c772015-03-26 15:49:53 +00003369 emit_t *emit_bc = emit_bc_new();
Damien Georgea210c772015-03-26 15:49:53 +00003370
Damien826005c2013-10-05 23:17:28 +01003371 // compile pass 1
Damien Georgea210c772015-03-26 15:49:53 +00003372 comp->emit = emit_bc;
Damien George41125902015-03-26 16:44:14 +00003373 #if MICROPY_EMIT_NATIVE
Damien Georgea210c772015-03-26 15:49:53 +00003374 comp->emit_method_table = &emit_bc_method_table;
3375 #endif
Damien826005c2013-10-05 23:17:28 +01003376 uint max_num_labels = 0;
Damien Georgea91ac202014-10-05 19:01:34 +01003377 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003378 if (false) {
Damien Georgead297a12016-12-09 13:17:49 +11003379 #if MICROPY_EMIT_INLINE_ASM
3380 } else if (s->emit_options == MP_EMIT_OPT_ASM) {
Damien George36db6bc2014-05-07 17:24:22 +01003381 compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);
Damien Georgead297a12016-12-09 13:17:49 +11003382 #endif
Damien826005c2013-10-05 23:17:28 +01003383 } else {
Damien George36db6bc2014-05-07 17:24:22 +01003384 compile_scope(comp, s, MP_PASS_SCOPE);
Damien826005c2013-10-05 23:17:28 +01003385 }
3386
3387 // update maximim number of labels needed
3388 if (comp->next_label > max_num_labels) {
3389 max_num_labels = comp->next_label;
3390 }
Damien429d7192013-10-04 19:53:11 +01003391 }
3392
Damien826005c2013-10-05 23:17:28 +01003393 // compute some things related to scope and identifiers
Damien Georgea91ac202014-10-05 19:01:34 +01003394 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
Damien Georgeff8dd3f2015-01-20 12:47:20 +00003395 scope_compute_things(s);
Damien429d7192013-10-04 19:53:11 +01003396 }
3397
Damien Georgea210c772015-03-26 15:49:53 +00003398 // set max number of labels now that it's calculated
Damien Georgea210c772015-03-26 15:49:53 +00003399 emit_bc_set_max_num_labels(emit_bc, max_num_labels);
Damien Georgea210c772015-03-26 15:49:53 +00003400
Damien826005c2013-10-05 23:17:28 +01003401 // compile pass 2 and 3
Damien Georgee67ed5d2014-01-04 13:55:24 +00003402#if MICROPY_EMIT_NATIVE
Damiendc833822013-10-06 01:01:01 +01003403 emit_t *emit_native = NULL;
Damienc025ebb2013-10-12 14:30:21 +01003404#endif
Damien Georgea91ac202014-10-05 19:01:34 +01003405 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
Damienc025ebb2013-10-12 14:30:21 +01003406 if (false) {
3407 // dummy
3408
Damien Georgead297a12016-12-09 13:17:49 +11003409 #if MICROPY_EMIT_INLINE_ASM
3410 } else if (s->emit_options == MP_EMIT_OPT_ASM) {
3411 // inline assembly
3412 if (comp->emit_inline_asm == NULL) {
3413 comp->emit_inline_asm = ASM_EMITTER(new)(max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003414 }
3415 comp->emit = NULL;
Damien Georgead297a12016-12-09 13:17:49 +11003416 comp->emit_inline_asm_method_table = &ASM_EMITTER(method_table);
Damien George36db6bc2014-05-07 17:24:22 +01003417 compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
Damien Georgede9cd002016-12-19 17:42:25 +11003418 #if MICROPY_EMIT_INLINE_XTENSA
3419 // Xtensa requires an extra pass to compute size of l32r const table
3420 // TODO this can be improved by calculating it during SCOPE pass
3421 // but that requires some other structural changes to the asm emitters
3422 compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
3423 #endif
Damien Georgea91ac202014-10-05 19:01:34 +01003424 if (comp->compile_error == MP_OBJ_NULL) {
Damien George36db6bc2014-05-07 17:24:22 +01003425 compile_scope_inline_asm(comp, s, MP_PASS_EMIT);
Damien Georgea26dc502014-04-12 17:54:52 +01003426 }
Damien Georgead297a12016-12-09 13:17:49 +11003427 #endif
Damienc025ebb2013-10-12 14:30:21 +01003428
Damien826005c2013-10-05 23:17:28 +01003429 } else {
Damienc025ebb2013-10-12 14:30:21 +01003430
3431 // choose the emit type
3432
Damien826005c2013-10-05 23:17:28 +01003433 switch (s->emit_options) {
Damien Georgee67ed5d2014-01-04 13:55:24 +00003434
3435#if MICROPY_EMIT_NATIVE
Damien George65cad122014-04-06 11:48:15 +01003436 case MP_EMIT_OPT_NATIVE_PYTHON:
3437 case MP_EMIT_OPT_VIPER:
Damiendc833822013-10-06 01:01:01 +01003438 if (emit_native == NULL) {
Damien George080a78b2016-12-07 11:17:17 +11003439 emit_native = NATIVE_EMITTER(new)(&comp->compile_error, max_num_labels);
Damien826005c2013-10-05 23:17:28 +01003440 }
Damien George080a78b2016-12-07 11:17:17 +11003441 comp->emit_method_table = &NATIVE_EMITTER(method_table);
Damienc025ebb2013-10-12 14:30:21 +01003442 comp->emit = emit_native;
Damien Georgea5190a72014-08-15 22:39:08 +01003443 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0);
Damien7af3d192013-10-07 00:02:49 +01003444 break;
Damien Georgee67ed5d2014-01-04 13:55:24 +00003445#endif // MICROPY_EMIT_NATIVE
Damien7af3d192013-10-07 00:02:49 +01003446
Damien826005c2013-10-05 23:17:28 +01003447 default:
Damien826005c2013-10-05 23:17:28 +01003448 comp->emit = emit_bc;
Damien George41125902015-03-26 16:44:14 +00003449 #if MICROPY_EMIT_NATIVE
Damien826005c2013-10-05 23:17:28 +01003450 comp->emit_method_table = &emit_bc_method_table;
Damien George41125902015-03-26 16:44:14 +00003451 #endif
Damien826005c2013-10-05 23:17:28 +01003452 break;
3453 }
Damienc025ebb2013-10-12 14:30:21 +01003454
Damien George1e1779e2015-01-14 00:20:28 +00003455 // need a pass to compute stack size
3456 compile_scope(comp, s, MP_PASS_STACK_SIZE);
3457
Damien George36db6bc2014-05-07 17:24:22 +01003458 // second last pass: compute code size
Damien Georgea91ac202014-10-05 19:01:34 +01003459 if (comp->compile_error == MP_OBJ_NULL) {
Damien George36db6bc2014-05-07 17:24:22 +01003460 compile_scope(comp, s, MP_PASS_CODE_SIZE);
3461 }
3462
3463 // final pass: emit code
Damien Georgea91ac202014-10-05 19:01:34 +01003464 if (comp->compile_error == MP_OBJ_NULL) {
Damien George36db6bc2014-05-07 17:24:22 +01003465 compile_scope(comp, s, MP_PASS_EMIT);
Damien Georgea26dc502014-04-12 17:54:52 +01003466 }
Damien6cdd3af2013-10-05 18:08:26 +01003467 }
Damien429d7192013-10-04 19:53:11 +01003468 }
3469
Damien Georgecfc4c332015-07-29 22:16:01 +00003470 if (comp->compile_error != MP_OBJ_NULL) {
3471 // if there is no line number for the error then use the line
3472 // number for the start of this scope
3473 compile_error_set_line(comp, comp->scope_cur->pn);
3474 // add a traceback to the exception using relevant source info
3475 mp_obj_exception_add_traceback(comp->compile_error, comp->source_file,
3476 comp->compile_error_line, comp->scope_cur->simple_name);
3477 }
3478
Damien George41d02b62014-01-24 22:42:28 +00003479 // free the emitters
Damien Georgea210c772015-03-26 15:49:53 +00003480
Damien Georgea210c772015-03-26 15:49:53 +00003481 emit_bc_free(emit_bc);
Damien George41d02b62014-01-24 22:42:28 +00003482#if MICROPY_EMIT_NATIVE
3483 if (emit_native != NULL) {
Damien George080a78b2016-12-07 11:17:17 +11003484 NATIVE_EMITTER(free)(emit_native);
Damien George41d02b62014-01-24 22:42:28 +00003485 }
3486#endif
Damien Georgead297a12016-12-09 13:17:49 +11003487 #if MICROPY_EMIT_INLINE_ASM
3488 if (comp->emit_inline_asm != NULL) {
3489 ASM_EMITTER(free)(comp->emit_inline_asm);
Damien George41d02b62014-01-24 22:42:28 +00003490 }
Damien Georgead297a12016-12-09 13:17:49 +11003491 #endif
Damien George41d02b62014-01-24 22:42:28 +00003492
Damien George52b5d762014-09-23 15:31:56 +00003493 // free the parse tree
Damien George58e0f4a2015-09-23 10:50:43 +01003494 mp_parse_tree_clear(parse_tree);
Damien George52b5d762014-09-23 15:31:56 +00003495
Damien George41d02b62014-01-24 22:42:28 +00003496 // free the scopes
Damien Georgedf8127a2014-04-13 11:04:33 +01003497 mp_raw_code_t *outer_raw_code = module_scope->raw_code;
Paul Sokolovskyfd313582014-01-23 23:05:47 +02003498 for (scope_t *s = module_scope; s;) {
3499 scope_t *next = s->next;
3500 scope_free(s);
3501 s = next;
3502 }
Damien5ac1b2e2013-10-18 19:58:12 +01003503
Damien George9d5e5c02015-09-24 13:15:57 +01003504 if (comp->compile_error != MP_OBJ_NULL) {
3505 nlr_raise(comp->compile_error);
Damien George1fb03172014-01-03 14:22:03 +00003506 } else {
Damien Georged4dba882015-11-13 13:38:28 +00003507 return outer_raw_code;
Damien George1fb03172014-01-03 14:22:03 +00003508 }
Damien429d7192013-10-04 19:53:11 +01003509}
Damien Georged4dba882015-11-13 13:38:28 +00003510
3511mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {
3512 mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, emit_opt, is_repl);
3513 // return function that executes the outer module
3514 return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);
3515}
Damien Georgedd5353a2015-12-18 12:35:44 +00003516
3517#endif // MICROPY_ENABLE_COMPILER