Port of MicroPython to the mbed platform. See micropython-repl for an interactive program.

Dependents:   micropython-repl

This a port of MicroPython to the mbed Classic platform.

This provides an interpreter running on the board's USB serial connection.

Getting Started

Import the micropython-repl program into your IDE workspace on developer.mbed.org. Compile and download to your board. Connect to the USB serial port in your usual manner. You should get a startup message similar to the following:

  MicroPython v1.7-155-gdddcdd8 on 2016-04-23; K64F with ARM
  Type "help()" for more information.
  >>>

Then you can start using micropython. For example:

  >>> from mbed import DigitalOut
  >>> from pins import LED1
  >>> led = DigitalOut(LED1)
  >>> led.write(1)

Requirements

You need approximately 100K of flash memory, so this will be no good for boards with smaller amounts of storage.

Caveats

This can be considered an alpha release of the port; things may not work; APIs may change in later releases. It is NOT an official part part the micropython project, so if anything doesn't work, blame me. If it does work, most of the credit is due to micropython.

  • Only a few of the mbed classes are available in micropython so far, and not all methods of those that are.
  • Only a few boards have their full range of pin names available; for others, only a few standard ones (USBTX, USBRX, LED1) are implemented.
  • The garbage collector is not yet implemented. The interpreter will gradually consume memory and then fail.
  • Exceptions from the mbed classes are not yet handled.
  • Asynchronous processing (e.g. events on inputs) is not supported.

Credits

  • Damien P. George and other contributors who created micropython.
  • Colin Hogben, author of this port.
Committer:
pythontech
Date:
Sat Apr 16 17:11:56 2016 +0000
Revision:
0:5868e8752d44
Child:
2:c89e95946844
Split off library from repl

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pythontech 0:5868e8752d44 1 /*
pythontech 0:5868e8752d44 2 * This file is part of the Micro Python project, http://micropython.org/
pythontech 0:5868e8752d44 3 *
pythontech 0:5868e8752d44 4 * The MIT License (MIT)
pythontech 0:5868e8752d44 5 *
pythontech 0:5868e8752d44 6 * Copyright (c) 2013-2015 Damien P. George
pythontech 0:5868e8752d44 7 *
pythontech 0:5868e8752d44 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
pythontech 0:5868e8752d44 9 * of this software and associated documentation files (the "Software"), to deal
pythontech 0:5868e8752d44 10 * in the Software without restriction, including without limitation the rights
pythontech 0:5868e8752d44 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
pythontech 0:5868e8752d44 12 * copies of the Software, and to permit persons to whom the Software is
pythontech 0:5868e8752d44 13 * furnished to do so, subject to the following conditions:
pythontech 0:5868e8752d44 14 *
pythontech 0:5868e8752d44 15 * The above copyright notice and this permission notice shall be included in
pythontech 0:5868e8752d44 16 * all copies or substantial portions of the Software.
pythontech 0:5868e8752d44 17 *
pythontech 0:5868e8752d44 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
pythontech 0:5868e8752d44 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
pythontech 0:5868e8752d44 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
pythontech 0:5868e8752d44 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
pythontech 0:5868e8752d44 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
pythontech 0:5868e8752d44 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
pythontech 0:5868e8752d44 24 * THE SOFTWARE.
pythontech 0:5868e8752d44 25 */
pythontech 0:5868e8752d44 26
pythontech 0:5868e8752d44 27 #include <stdbool.h>
pythontech 0:5868e8752d44 28 #include <stdint.h>
pythontech 0:5868e8752d44 29 #include <stdio.h>
pythontech 0:5868e8752d44 30 #include <string.h>
pythontech 0:5868e8752d44 31 #include <assert.h>
pythontech 0:5868e8752d44 32
pythontech 0:5868e8752d44 33 #include "py/scope.h"
pythontech 0:5868e8752d44 34 #include "py/emit.h"
pythontech 0:5868e8752d44 35 #include "py/compile.h"
pythontech 0:5868e8752d44 36 #include "py/runtime.h"
pythontech 0:5868e8752d44 37
pythontech 0:5868e8752d44 38 #if MICROPY_ENABLE_COMPILER
pythontech 0:5868e8752d44 39
pythontech 0:5868e8752d44 40 // TODO need to mangle __attr names
pythontech 0:5868e8752d44 41
pythontech 0:5868e8752d44 42 typedef enum {
pythontech 0:5868e8752d44 43 #define DEF_RULE(rule, comp, kind, ...) PN_##rule,
pythontech 0:5868e8752d44 44 #include "py/grammar.h"
pythontech 0:5868e8752d44 45 #undef DEF_RULE
pythontech 0:5868e8752d44 46 PN_maximum_number_of,
pythontech 0:5868e8752d44 47 PN_string, // special node for non-interned string
pythontech 0:5868e8752d44 48 PN_bytes, // special node for non-interned bytes
pythontech 0:5868e8752d44 49 PN_const_object, // special node for a constant, generic Python object
pythontech 0:5868e8752d44 50 } pn_kind_t;
pythontech 0:5868e8752d44 51
pythontech 0:5868e8752d44 52 #define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 53
pythontech 0:5868e8752d44 54 #if NEED_METHOD_TABLE
pythontech 0:5868e8752d44 55
pythontech 0:5868e8752d44 56 // we need a method table to do the lookup for the emitter functions
pythontech 0:5868e8752d44 57 #define EMIT(fun) (comp->emit_method_table->fun(comp->emit))
pythontech 0:5868e8752d44 58 #define EMIT_ARG(fun, ...) (comp->emit_method_table->fun(comp->emit, __VA_ARGS__))
pythontech 0:5868e8752d44 59 #define EMIT_LOAD_FAST(qst, local_num) (comp->emit_method_table->load_id.fast(comp->emit, qst, local_num))
pythontech 0:5868e8752d44 60 #define EMIT_LOAD_GLOBAL(qst) (comp->emit_method_table->load_id.global(comp->emit, qst))
pythontech 0:5868e8752d44 61
pythontech 0:5868e8752d44 62 #else
pythontech 0:5868e8752d44 63
pythontech 0:5868e8752d44 64 // if we only have the bytecode emitter enabled then we can do a direct call to the functions
pythontech 0:5868e8752d44 65 #define EMIT(fun) (mp_emit_bc_##fun(comp->emit))
pythontech 0:5868e8752d44 66 #define EMIT_ARG(fun, ...) (mp_emit_bc_##fun(comp->emit, __VA_ARGS__))
pythontech 0:5868e8752d44 67 #define EMIT_LOAD_FAST(qst, local_num) (mp_emit_bc_load_fast(comp->emit, qst, local_num))
pythontech 0:5868e8752d44 68 #define EMIT_LOAD_GLOBAL(qst) (mp_emit_bc_load_global(comp->emit, qst))
pythontech 0:5868e8752d44 69
pythontech 0:5868e8752d44 70 #endif
pythontech 0:5868e8752d44 71
pythontech 0:5868e8752d44 72 #define EMIT_INLINE_ASM(fun) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm))
pythontech 0:5868e8752d44 73 #define EMIT_INLINE_ASM_ARG(fun, ...) (comp->emit_inline_asm_method_table->fun(comp->emit_inline_asm, __VA_ARGS__))
pythontech 0:5868e8752d44 74
pythontech 0:5868e8752d44 75 // elements in this struct are ordered to make it compact
pythontech 0:5868e8752d44 76 typedef struct _compiler_t {
pythontech 0:5868e8752d44 77 qstr source_file;
pythontech 0:5868e8752d44 78
pythontech 0:5868e8752d44 79 uint8_t is_repl;
pythontech 0:5868e8752d44 80 uint8_t pass; // holds enum type pass_kind_t
pythontech 0:5868e8752d44 81 uint8_t func_arg_is_super; // used to compile special case of super() function call
pythontech 0:5868e8752d44 82 uint8_t have_star;
pythontech 0:5868e8752d44 83
pythontech 0:5868e8752d44 84 // try to keep compiler clean from nlr
pythontech 0:5868e8752d44 85 mp_obj_t compile_error; // set to an exception object if there's an error
pythontech 0:5868e8752d44 86 size_t compile_error_line; // set to best guess of line of error
pythontech 0:5868e8752d44 87
pythontech 0:5868e8752d44 88 uint next_label;
pythontech 0:5868e8752d44 89
pythontech 0:5868e8752d44 90 uint16_t num_dict_params;
pythontech 0:5868e8752d44 91 uint16_t num_default_params;
pythontech 0:5868e8752d44 92
pythontech 0:5868e8752d44 93 uint16_t break_label; // highest bit set indicates we are breaking out of a for loop
pythontech 0:5868e8752d44 94 uint16_t continue_label;
pythontech 0:5868e8752d44 95 uint16_t cur_except_level; // increased for SETUP_EXCEPT, SETUP_FINALLY; decreased for POP_BLOCK, POP_EXCEPT
pythontech 0:5868e8752d44 96 uint16_t break_continue_except_level;
pythontech 0:5868e8752d44 97
pythontech 0:5868e8752d44 98 scope_t *scope_head;
pythontech 0:5868e8752d44 99 scope_t *scope_cur;
pythontech 0:5868e8752d44 100
pythontech 0:5868e8752d44 101 emit_t *emit; // current emitter
pythontech 0:5868e8752d44 102 #if NEED_METHOD_TABLE
pythontech 0:5868e8752d44 103 const emit_method_table_t *emit_method_table; // current emit method table
pythontech 0:5868e8752d44 104 #endif
pythontech 0:5868e8752d44 105
pythontech 0:5868e8752d44 106 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 107 emit_inline_asm_t *emit_inline_asm; // current emitter for inline asm
pythontech 0:5868e8752d44 108 const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
pythontech 0:5868e8752d44 109 #endif
pythontech 0:5868e8752d44 110 } compiler_t;
pythontech 0:5868e8752d44 111
pythontech 0:5868e8752d44 112 STATIC void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 113 // if the line of the error is unknown then try to update it from the pn
pythontech 0:5868e8752d44 114 if (comp->compile_error_line == 0 && MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 115 comp->compile_error_line = ((mp_parse_node_struct_t*)pn)->source_line;
pythontech 0:5868e8752d44 116 }
pythontech 0:5868e8752d44 117 }
pythontech 0:5868e8752d44 118
pythontech 0:5868e8752d44 119 STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
pythontech 0:5868e8752d44 120 // only register the error if there has been no other error
pythontech 0:5868e8752d44 121 if (comp->compile_error == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 122 comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg);
pythontech 0:5868e8752d44 123 compile_error_set_line(comp, pn);
pythontech 0:5868e8752d44 124 }
pythontech 0:5868e8752d44 125 }
pythontech 0:5868e8752d44 126
pythontech 0:5868e8752d44 127 STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra);
pythontech 0:5868e8752d44 128 STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind);
pythontech 0:5868e8752d44 129 STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn);
pythontech 0:5868e8752d44 130
pythontech 0:5868e8752d44 131 STATIC uint comp_next_label(compiler_t *comp) {
pythontech 0:5868e8752d44 132 return comp->next_label++;
pythontech 0:5868e8752d44 133 }
pythontech 0:5868e8752d44 134
pythontech 0:5868e8752d44 135 STATIC void compile_increase_except_level(compiler_t *comp) {
pythontech 0:5868e8752d44 136 comp->cur_except_level += 1;
pythontech 0:5868e8752d44 137 if (comp->cur_except_level > comp->scope_cur->exc_stack_size) {
pythontech 0:5868e8752d44 138 comp->scope_cur->exc_stack_size = comp->cur_except_level;
pythontech 0:5868e8752d44 139 }
pythontech 0:5868e8752d44 140 }
pythontech 0:5868e8752d44 141
pythontech 0:5868e8752d44 142 STATIC void compile_decrease_except_level(compiler_t *comp) {
pythontech 0:5868e8752d44 143 assert(comp->cur_except_level > 0);
pythontech 0:5868e8752d44 144 comp->cur_except_level -= 1;
pythontech 0:5868e8752d44 145 }
pythontech 0:5868e8752d44 146
pythontech 0:5868e8752d44 147 STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) {
pythontech 0:5868e8752d44 148 scope_t *scope = scope_new(kind, pn, comp->source_file, emit_options);
pythontech 0:5868e8752d44 149 scope->parent = comp->scope_cur;
pythontech 0:5868e8752d44 150 scope->next = NULL;
pythontech 0:5868e8752d44 151 if (comp->scope_head == NULL) {
pythontech 0:5868e8752d44 152 comp->scope_head = scope;
pythontech 0:5868e8752d44 153 } else {
pythontech 0:5868e8752d44 154 scope_t *s = comp->scope_head;
pythontech 0:5868e8752d44 155 while (s->next != NULL) {
pythontech 0:5868e8752d44 156 s = s->next;
pythontech 0:5868e8752d44 157 }
pythontech 0:5868e8752d44 158 s->next = scope;
pythontech 0:5868e8752d44 159 }
pythontech 0:5868e8752d44 160 return scope;
pythontech 0:5868e8752d44 161 }
pythontech 0:5868e8752d44 162
pythontech 0:5868e8752d44 163 typedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn);
pythontech 0:5868e8752d44 164
pythontech 0:5868e8752d44 165 STATIC void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_list_kind, apply_list_fun_t f) {
pythontech 0:5868e8752d44 166 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) {
pythontech 0:5868e8752d44 167 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 168 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 169 for (int i = 0; i < num_nodes; i++) {
pythontech 0:5868e8752d44 170 f(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 171 }
pythontech 0:5868e8752d44 172 } else if (!MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 173 f(comp, pn);
pythontech 0:5868e8752d44 174 }
pythontech 0:5868e8752d44 175 }
pythontech 0:5868e8752d44 176
pythontech 0:5868e8752d44 177 STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 178 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 179 for (int i = 0; i < num_nodes; i++) {
pythontech 0:5868e8752d44 180 compile_node(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 181 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 182 // add line info for the error in case it didn't have a line number
pythontech 0:5868e8752d44 183 compile_error_set_line(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 184 return;
pythontech 0:5868e8752d44 185 }
pythontech 0:5868e8752d44 186 }
pythontech 0:5868e8752d44 187 }
pythontech 0:5868e8752d44 188
pythontech 0:5868e8752d44 189 STATIC void compile_load_id(compiler_t *comp, qstr qst) {
pythontech 0:5868e8752d44 190 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 191 mp_emit_common_get_id_for_load(comp->scope_cur, qst);
pythontech 0:5868e8752d44 192 } else {
pythontech 0:5868e8752d44 193 #if NEED_METHOD_TABLE
pythontech 0:5868e8752d44 194 mp_emit_common_id_op(comp->emit, &comp->emit_method_table->load_id, comp->scope_cur, qst);
pythontech 0:5868e8752d44 195 #else
pythontech 0:5868e8752d44 196 mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_load_id_ops, comp->scope_cur, qst);
pythontech 0:5868e8752d44 197 #endif
pythontech 0:5868e8752d44 198 }
pythontech 0:5868e8752d44 199 }
pythontech 0:5868e8752d44 200
pythontech 0:5868e8752d44 201 STATIC void compile_store_id(compiler_t *comp, qstr qst) {
pythontech 0:5868e8752d44 202 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 203 mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
pythontech 0:5868e8752d44 204 } else {
pythontech 0:5868e8752d44 205 #if NEED_METHOD_TABLE
pythontech 0:5868e8752d44 206 mp_emit_common_id_op(comp->emit, &comp->emit_method_table->store_id, comp->scope_cur, qst);
pythontech 0:5868e8752d44 207 #else
pythontech 0:5868e8752d44 208 mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_store_id_ops, comp->scope_cur, qst);
pythontech 0:5868e8752d44 209 #endif
pythontech 0:5868e8752d44 210 }
pythontech 0:5868e8752d44 211 }
pythontech 0:5868e8752d44 212
pythontech 0:5868e8752d44 213 STATIC void compile_delete_id(compiler_t *comp, qstr qst) {
pythontech 0:5868e8752d44 214 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 215 mp_emit_common_get_id_for_modification(comp->scope_cur, qst);
pythontech 0:5868e8752d44 216 } else {
pythontech 0:5868e8752d44 217 #if NEED_METHOD_TABLE
pythontech 0:5868e8752d44 218 mp_emit_common_id_op(comp->emit, &comp->emit_method_table->delete_id, comp->scope_cur, qst);
pythontech 0:5868e8752d44 219 #else
pythontech 0:5868e8752d44 220 mp_emit_common_id_op(comp->emit, &mp_emit_bc_method_table_delete_id_ops, comp->scope_cur, qst);
pythontech 0:5868e8752d44 221 #endif
pythontech 0:5868e8752d44 222 }
pythontech 0:5868e8752d44 223 }
pythontech 0:5868e8752d44 224
pythontech 0:5868e8752d44 225 STATIC void c_tuple(compiler_t *comp, mp_parse_node_t pn, mp_parse_node_struct_t *pns_list) {
pythontech 0:5868e8752d44 226 int total = 0;
pythontech 0:5868e8752d44 227 if (!MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 228 compile_node(comp, pn);
pythontech 0:5868e8752d44 229 total += 1;
pythontech 0:5868e8752d44 230 }
pythontech 0:5868e8752d44 231 if (pns_list != NULL) {
pythontech 0:5868e8752d44 232 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_list);
pythontech 0:5868e8752d44 233 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 234 compile_node(comp, pns_list->nodes[i]);
pythontech 0:5868e8752d44 235 }
pythontech 0:5868e8752d44 236 total += n;
pythontech 0:5868e8752d44 237 }
pythontech 0:5868e8752d44 238 EMIT_ARG(build_tuple, total);
pythontech 0:5868e8752d44 239 }
pythontech 0:5868e8752d44 240
pythontech 0:5868e8752d44 241 STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 242 // a simple tuple expression
pythontech 0:5868e8752d44 243 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
pythontech 0:5868e8752d44 244 }
pythontech 0:5868e8752d44 245
pythontech 0:5868e8752d44 246 STATIC bool node_is_const_false(mp_parse_node_t pn) {
pythontech 0:5868e8752d44 247 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_FALSE)
pythontech 0:5868e8752d44 248 || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) == 0);
pythontech 0:5868e8752d44 249 }
pythontech 0:5868e8752d44 250
pythontech 0:5868e8752d44 251 STATIC bool node_is_const_true(mp_parse_node_t pn) {
pythontech 0:5868e8752d44 252 return MP_PARSE_NODE_IS_TOKEN_KIND(pn, MP_TOKEN_KW_TRUE)
pythontech 0:5868e8752d44 253 || (MP_PARSE_NODE_IS_SMALL_INT(pn) && MP_PARSE_NODE_LEAF_SMALL_INT(pn) != 0);
pythontech 0:5868e8752d44 254 }
pythontech 0:5868e8752d44 255
pythontech 0:5868e8752d44 256 STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) {
pythontech 0:5868e8752d44 257 if (node_is_const_false(pn)) {
pythontech 0:5868e8752d44 258 if (jump_if == false) {
pythontech 0:5868e8752d44 259 EMIT_ARG(jump, label);
pythontech 0:5868e8752d44 260 }
pythontech 0:5868e8752d44 261 return;
pythontech 0:5868e8752d44 262 } else if (node_is_const_true(pn)) {
pythontech 0:5868e8752d44 263 if (jump_if == true) {
pythontech 0:5868e8752d44 264 EMIT_ARG(jump, label);
pythontech 0:5868e8752d44 265 }
pythontech 0:5868e8752d44 266 return;
pythontech 0:5868e8752d44 267 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 268 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 269 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 270 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test) {
pythontech 0:5868e8752d44 271 if (jump_if == false) {
pythontech 0:5868e8752d44 272 and_or_logic1:;
pythontech 0:5868e8752d44 273 uint label2 = comp_next_label(comp);
pythontech 0:5868e8752d44 274 for (int i = 0; i < n - 1; i++) {
pythontech 0:5868e8752d44 275 c_if_cond(comp, pns->nodes[i], !jump_if, label2);
pythontech 0:5868e8752d44 276 }
pythontech 0:5868e8752d44 277 c_if_cond(comp, pns->nodes[n - 1], jump_if, label);
pythontech 0:5868e8752d44 278 EMIT_ARG(label_assign, label2);
pythontech 0:5868e8752d44 279 } else {
pythontech 0:5868e8752d44 280 and_or_logic2:
pythontech 0:5868e8752d44 281 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 282 c_if_cond(comp, pns->nodes[i], jump_if, label);
pythontech 0:5868e8752d44 283 }
pythontech 0:5868e8752d44 284 }
pythontech 0:5868e8752d44 285 return;
pythontech 0:5868e8752d44 286 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_and_test) {
pythontech 0:5868e8752d44 287 if (jump_if == false) {
pythontech 0:5868e8752d44 288 goto and_or_logic2;
pythontech 0:5868e8752d44 289 } else {
pythontech 0:5868e8752d44 290 goto and_or_logic1;
pythontech 0:5868e8752d44 291 }
pythontech 0:5868e8752d44 292 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_not_test_2) {
pythontech 0:5868e8752d44 293 c_if_cond(comp, pns->nodes[0], !jump_if, label);
pythontech 0:5868e8752d44 294 return;
pythontech 0:5868e8752d44 295 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_atom_paren) {
pythontech 0:5868e8752d44 296 // cond is something in parenthesis
pythontech 0:5868e8752d44 297 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 298 // empty tuple, acts as false for the condition
pythontech 0:5868e8752d44 299 if (jump_if == false) {
pythontech 0:5868e8752d44 300 EMIT_ARG(jump, label);
pythontech 0:5868e8752d44 301 }
pythontech 0:5868e8752d44 302 } else {
pythontech 0:5868e8752d44 303 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
pythontech 0:5868e8752d44 304 // non-empty tuple, acts as true for the condition
pythontech 0:5868e8752d44 305 if (jump_if == true) {
pythontech 0:5868e8752d44 306 EMIT_ARG(jump, label);
pythontech 0:5868e8752d44 307 }
pythontech 0:5868e8752d44 308 }
pythontech 0:5868e8752d44 309 return;
pythontech 0:5868e8752d44 310 }
pythontech 0:5868e8752d44 311 }
pythontech 0:5868e8752d44 312
pythontech 0:5868e8752d44 313 // nothing special, fall back to default compiling for node and jump
pythontech 0:5868e8752d44 314 compile_node(comp, pn);
pythontech 0:5868e8752d44 315 EMIT_ARG(pop_jump_if, jump_if, label);
pythontech 0:5868e8752d44 316 }
pythontech 0:5868e8752d44 317
pythontech 0:5868e8752d44 318 typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t;
pythontech 0:5868e8752d44 319 STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind);
pythontech 0:5868e8752d44 320
pythontech 0:5868e8752d44 321 STATIC void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) {
pythontech 0:5868e8752d44 322 if (assign_kind != ASSIGN_AUG_STORE) {
pythontech 0:5868e8752d44 323 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 324 }
pythontech 0:5868e8752d44 325
pythontech 0:5868e8752d44 326 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 327 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 328 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
pythontech 0:5868e8752d44 329 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
pythontech 0:5868e8752d44 330 if (assign_kind != ASSIGN_AUG_STORE) {
pythontech 0:5868e8752d44 331 for (int i = 0; i < n - 1; i++) {
pythontech 0:5868e8752d44 332 compile_node(comp, pns1->nodes[i]);
pythontech 0:5868e8752d44 333 }
pythontech 0:5868e8752d44 334 }
pythontech 0:5868e8752d44 335 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
pythontech 0:5868e8752d44 336 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
pythontech 0:5868e8752d44 337 }
pythontech 0:5868e8752d44 338 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
pythontech 0:5868e8752d44 339 if (assign_kind == ASSIGN_AUG_STORE) {
pythontech 0:5868e8752d44 340 EMIT(rot_three);
pythontech 0:5868e8752d44 341 EMIT(store_subscr);
pythontech 0:5868e8752d44 342 } else {
pythontech 0:5868e8752d44 343 compile_node(comp, pns1->nodes[0]);
pythontech 0:5868e8752d44 344 if (assign_kind == ASSIGN_AUG_LOAD) {
pythontech 0:5868e8752d44 345 EMIT(dup_top_two);
pythontech 0:5868e8752d44 346 EMIT(load_subscr);
pythontech 0:5868e8752d44 347 } else {
pythontech 0:5868e8752d44 348 EMIT(store_subscr);
pythontech 0:5868e8752d44 349 }
pythontech 0:5868e8752d44 350 }
pythontech 0:5868e8752d44 351 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
pythontech 0:5868e8752d44 352 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
pythontech 0:5868e8752d44 353 if (assign_kind == ASSIGN_AUG_LOAD) {
pythontech 0:5868e8752d44 354 EMIT(dup_top);
pythontech 0:5868e8752d44 355 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
pythontech 0:5868e8752d44 356 } else {
pythontech 0:5868e8752d44 357 if (assign_kind == ASSIGN_AUG_STORE) {
pythontech 0:5868e8752d44 358 EMIT(rot_two);
pythontech 0:5868e8752d44 359 }
pythontech 0:5868e8752d44 360 EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
pythontech 0:5868e8752d44 361 }
pythontech 0:5868e8752d44 362 } else {
pythontech 0:5868e8752d44 363 goto cannot_assign;
pythontech 0:5868e8752d44 364 }
pythontech 0:5868e8752d44 365 } else {
pythontech 0:5868e8752d44 366 goto cannot_assign;
pythontech 0:5868e8752d44 367 }
pythontech 0:5868e8752d44 368
pythontech 0:5868e8752d44 369 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
pythontech 0:5868e8752d44 370 goto cannot_assign;
pythontech 0:5868e8752d44 371 }
pythontech 0:5868e8752d44 372
pythontech 0:5868e8752d44 373 return;
pythontech 0:5868e8752d44 374
pythontech 0:5868e8752d44 375 cannot_assign:
pythontech 0:5868e8752d44 376 compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
pythontech 0:5868e8752d44 377 }
pythontech 0:5868e8752d44 378
pythontech 0:5868e8752d44 379 // we need to allow for a caller passing in 1 initial node (node_head) followed by an array of nodes (nodes_tail)
pythontech 0:5868e8752d44 380 STATIC void c_assign_tuple(compiler_t *comp, mp_parse_node_t node_head, uint num_tail, mp_parse_node_t *nodes_tail) {
pythontech 0:5868e8752d44 381 uint num_head = (node_head == MP_PARSE_NODE_NULL) ? 0 : 1;
pythontech 0:5868e8752d44 382
pythontech 0:5868e8752d44 383 // look for star expression
pythontech 0:5868e8752d44 384 uint have_star_index = -1;
pythontech 0:5868e8752d44 385 if (num_head != 0 && MP_PARSE_NODE_IS_STRUCT_KIND(node_head, PN_star_expr)) {
pythontech 0:5868e8752d44 386 EMIT_ARG(unpack_ex, 0, num_tail);
pythontech 0:5868e8752d44 387 have_star_index = 0;
pythontech 0:5868e8752d44 388 }
pythontech 0:5868e8752d44 389 for (uint i = 0; i < num_tail; i++) {
pythontech 0:5868e8752d44 390 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {
pythontech 0:5868e8752d44 391 if (have_star_index == (uint)-1) {
pythontech 0:5868e8752d44 392 EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1);
pythontech 0:5868e8752d44 393 have_star_index = num_head + i;
pythontech 0:5868e8752d44 394 } else {
pythontech 0:5868e8752d44 395 compile_syntax_error(comp, nodes_tail[i], "multiple *x in assignment");
pythontech 0:5868e8752d44 396 return;
pythontech 0:5868e8752d44 397 }
pythontech 0:5868e8752d44 398 }
pythontech 0:5868e8752d44 399 }
pythontech 0:5868e8752d44 400 if (have_star_index == (uint)-1) {
pythontech 0:5868e8752d44 401 EMIT_ARG(unpack_sequence, num_head + num_tail);
pythontech 0:5868e8752d44 402 }
pythontech 0:5868e8752d44 403 if (num_head != 0) {
pythontech 0:5868e8752d44 404 if (0 == have_star_index) {
pythontech 0:5868e8752d44 405 c_assign(comp, ((mp_parse_node_struct_t*)node_head)->nodes[0], ASSIGN_STORE);
pythontech 0:5868e8752d44 406 } else {
pythontech 0:5868e8752d44 407 c_assign(comp, node_head, ASSIGN_STORE);
pythontech 0:5868e8752d44 408 }
pythontech 0:5868e8752d44 409 }
pythontech 0:5868e8752d44 410 for (uint i = 0; i < num_tail; i++) {
pythontech 0:5868e8752d44 411 if (num_head + i == have_star_index) {
pythontech 0:5868e8752d44 412 c_assign(comp, ((mp_parse_node_struct_t*)nodes_tail[i])->nodes[0], ASSIGN_STORE);
pythontech 0:5868e8752d44 413 } else {
pythontech 0:5868e8752d44 414 c_assign(comp, nodes_tail[i], ASSIGN_STORE);
pythontech 0:5868e8752d44 415 }
pythontech 0:5868e8752d44 416 }
pythontech 0:5868e8752d44 417 }
pythontech 0:5868e8752d44 418
pythontech 0:5868e8752d44 419 // assigns top of stack to pn
pythontech 0:5868e8752d44 420 STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
pythontech 0:5868e8752d44 421 assert(!MP_PARSE_NODE_IS_NULL(pn));
pythontech 0:5868e8752d44 422 if (MP_PARSE_NODE_IS_LEAF(pn)) {
pythontech 0:5868e8752d44 423 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 424 qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 425 switch (assign_kind) {
pythontech 0:5868e8752d44 426 case ASSIGN_STORE:
pythontech 0:5868e8752d44 427 case ASSIGN_AUG_STORE:
pythontech 0:5868e8752d44 428 compile_store_id(comp, arg);
pythontech 0:5868e8752d44 429 break;
pythontech 0:5868e8752d44 430 case ASSIGN_AUG_LOAD:
pythontech 0:5868e8752d44 431 default:
pythontech 0:5868e8752d44 432 compile_load_id(comp, arg);
pythontech 0:5868e8752d44 433 break;
pythontech 0:5868e8752d44 434 }
pythontech 0:5868e8752d44 435 } else {
pythontech 0:5868e8752d44 436 compile_syntax_error(comp, pn, "can't assign to literal");
pythontech 0:5868e8752d44 437 return;
pythontech 0:5868e8752d44 438 }
pythontech 0:5868e8752d44 439 } else {
pythontech 0:5868e8752d44 440 // pn must be a struct
pythontech 0:5868e8752d44 441 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 442 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
pythontech 0:5868e8752d44 443 case PN_power:
pythontech 0:5868e8752d44 444 // lhs is an index or attribute
pythontech 0:5868e8752d44 445 c_assign_power(comp, pns, assign_kind);
pythontech 0:5868e8752d44 446 break;
pythontech 0:5868e8752d44 447
pythontech 0:5868e8752d44 448 case PN_testlist_star_expr:
pythontech 0:5868e8752d44 449 case PN_exprlist:
pythontech 0:5868e8752d44 450 // lhs is a tuple
pythontech 0:5868e8752d44 451 if (assign_kind != ASSIGN_STORE) {
pythontech 0:5868e8752d44 452 goto bad_aug;
pythontech 0:5868e8752d44 453 }
pythontech 0:5868e8752d44 454 c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
pythontech 0:5868e8752d44 455 break;
pythontech 0:5868e8752d44 456
pythontech 0:5868e8752d44 457 case PN_atom_paren:
pythontech 0:5868e8752d44 458 // lhs is something in parenthesis
pythontech 0:5868e8752d44 459 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 460 // empty tuple
pythontech 0:5868e8752d44 461 goto cannot_assign;
pythontech 0:5868e8752d44 462 } else {
pythontech 0:5868e8752d44 463 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
pythontech 0:5868e8752d44 464 if (assign_kind != ASSIGN_STORE) {
pythontech 0:5868e8752d44 465 goto bad_aug;
pythontech 0:5868e8752d44 466 }
pythontech 0:5868e8752d44 467 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 468 goto testlist_comp;
pythontech 0:5868e8752d44 469 }
pythontech 0:5868e8752d44 470 break;
pythontech 0:5868e8752d44 471
pythontech 0:5868e8752d44 472 case PN_atom_bracket:
pythontech 0:5868e8752d44 473 // lhs is something in brackets
pythontech 0:5868e8752d44 474 if (assign_kind != ASSIGN_STORE) {
pythontech 0:5868e8752d44 475 goto bad_aug;
pythontech 0:5868e8752d44 476 }
pythontech 0:5868e8752d44 477 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 478 // empty list, assignment allowed
pythontech 0:5868e8752d44 479 c_assign_tuple(comp, MP_PARSE_NODE_NULL, 0, NULL);
pythontech 0:5868e8752d44 480 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
pythontech 0:5868e8752d44 481 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 482 goto testlist_comp;
pythontech 0:5868e8752d44 483 } else {
pythontech 0:5868e8752d44 484 // brackets around 1 item
pythontech 0:5868e8752d44 485 c_assign_tuple(comp, pns->nodes[0], 0, NULL);
pythontech 0:5868e8752d44 486 }
pythontech 0:5868e8752d44 487 break;
pythontech 0:5868e8752d44 488
pythontech 0:5868e8752d44 489 default:
pythontech 0:5868e8752d44 490 goto cannot_assign;
pythontech 0:5868e8752d44 491 }
pythontech 0:5868e8752d44 492 return;
pythontech 0:5868e8752d44 493
pythontech 0:5868e8752d44 494 testlist_comp:
pythontech 0:5868e8752d44 495 // lhs is a sequence
pythontech 0:5868e8752d44 496 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 497 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 498 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
pythontech 0:5868e8752d44 499 // sequence of one item, with trailing comma
pythontech 0:5868e8752d44 500 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
pythontech 0:5868e8752d44 501 c_assign_tuple(comp, pns->nodes[0], 0, NULL);
pythontech 0:5868e8752d44 502 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
pythontech 0:5868e8752d44 503 // sequence of many items
pythontech 0:5868e8752d44 504 uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
pythontech 0:5868e8752d44 505 c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes);
pythontech 0:5868e8752d44 506 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
pythontech 0:5868e8752d44 507 // TODO can we ever get here? can it be compiled?
pythontech 0:5868e8752d44 508 goto cannot_assign;
pythontech 0:5868e8752d44 509 } else {
pythontech 0:5868e8752d44 510 // sequence with 2 items
pythontech 0:5868e8752d44 511 goto sequence_with_2_items;
pythontech 0:5868e8752d44 512 }
pythontech 0:5868e8752d44 513 } else {
pythontech 0:5868e8752d44 514 // sequence with 2 items
pythontech 0:5868e8752d44 515 sequence_with_2_items:
pythontech 0:5868e8752d44 516 c_assign_tuple(comp, MP_PARSE_NODE_NULL, 2, pns->nodes);
pythontech 0:5868e8752d44 517 }
pythontech 0:5868e8752d44 518 return;
pythontech 0:5868e8752d44 519 }
pythontech 0:5868e8752d44 520 return;
pythontech 0:5868e8752d44 521
pythontech 0:5868e8752d44 522 cannot_assign:
pythontech 0:5868e8752d44 523 compile_syntax_error(comp, pn, "can't assign to expression");
pythontech 0:5868e8752d44 524 return;
pythontech 0:5868e8752d44 525
pythontech 0:5868e8752d44 526 bad_aug:
pythontech 0:5868e8752d44 527 compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
pythontech 0:5868e8752d44 528 }
pythontech 0:5868e8752d44 529
pythontech 0:5868e8752d44 530 // stuff for lambda and comprehensions and generators:
pythontech 0:5868e8752d44 531 // if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults
pythontech 0:5868e8752d44 532 // if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults
pythontech 0:5868e8752d44 533 // if both exist, the tuple is above the dictionary (ie the first pop gets the tuple)
pythontech 0:5868e8752d44 534 STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
pythontech 0:5868e8752d44 535 assert(n_pos_defaults >= 0);
pythontech 0:5868e8752d44 536 assert(n_kw_defaults >= 0);
pythontech 0:5868e8752d44 537
pythontech 0:5868e8752d44 538 // set flags
pythontech 0:5868e8752d44 539 if (n_kw_defaults > 0) {
pythontech 0:5868e8752d44 540 this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS;
pythontech 0:5868e8752d44 541 }
pythontech 0:5868e8752d44 542 this_scope->num_def_pos_args = n_pos_defaults;
pythontech 0:5868e8752d44 543
pythontech 0:5868e8752d44 544 // make closed over variables, if any
pythontech 0:5868e8752d44 545 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
pythontech 0:5868e8752d44 546 int nfree = 0;
pythontech 0:5868e8752d44 547 if (comp->scope_cur->kind != SCOPE_MODULE) {
pythontech 0:5868e8752d44 548 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
pythontech 0:5868e8752d44 549 id_info_t *id = &comp->scope_cur->id_info[i];
pythontech 0:5868e8752d44 550 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
pythontech 0:5868e8752d44 551 for (int j = 0; j < this_scope->id_info_len; j++) {
pythontech 0:5868e8752d44 552 id_info_t *id2 = &this_scope->id_info[j];
pythontech 0:5868e8752d44 553 if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
pythontech 0:5868e8752d44 554 // in Micro Python we load closures using LOAD_FAST
pythontech 0:5868e8752d44 555 EMIT_LOAD_FAST(id->qst, id->local_num);
pythontech 0:5868e8752d44 556 nfree += 1;
pythontech 0:5868e8752d44 557 }
pythontech 0:5868e8752d44 558 }
pythontech 0:5868e8752d44 559 }
pythontech 0:5868e8752d44 560 }
pythontech 0:5868e8752d44 561 }
pythontech 0:5868e8752d44 562
pythontech 0:5868e8752d44 563 // make the function/closure
pythontech 0:5868e8752d44 564 if (nfree == 0) {
pythontech 0:5868e8752d44 565 EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);
pythontech 0:5868e8752d44 566 } else {
pythontech 0:5868e8752d44 567 EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);
pythontech 0:5868e8752d44 568 }
pythontech 0:5868e8752d44 569 }
pythontech 0:5868e8752d44 570
pythontech 0:5868e8752d44 571 STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 572 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)
pythontech 0:5868e8752d44 573 || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_star)) {
pythontech 0:5868e8752d44 574 comp->have_star = true;
pythontech 0:5868e8752d44 575 /* don't need to distinguish bare from named star
pythontech 0:5868e8752d44 576 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 577 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 578 // bare star
pythontech 0:5868e8752d44 579 } else {
pythontech 0:5868e8752d44 580 // named star
pythontech 0:5868e8752d44 581 }
pythontech 0:5868e8752d44 582 */
pythontech 0:5868e8752d44 583
pythontech 0:5868e8752d44 584 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)
pythontech 0:5868e8752d44 585 || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_dbl_star)) {
pythontech 0:5868e8752d44 586 // named double star
pythontech 0:5868e8752d44 587 // TODO do we need to do anything with this?
pythontech 0:5868e8752d44 588
pythontech 0:5868e8752d44 589 } else {
pythontech 0:5868e8752d44 590 mp_parse_node_t pn_id;
pythontech 0:5868e8752d44 591 mp_parse_node_t pn_colon;
pythontech 0:5868e8752d44 592 mp_parse_node_t pn_equal;
pythontech 0:5868e8752d44 593 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 594 // this parameter is just an id
pythontech 0:5868e8752d44 595
pythontech 0:5868e8752d44 596 pn_id = pn;
pythontech 0:5868e8752d44 597 pn_colon = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 598 pn_equal = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 599
pythontech 0:5868e8752d44 600 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
pythontech 0:5868e8752d44 601 // this parameter has a colon and/or equal specifier
pythontech 0:5868e8752d44 602
pythontech 0:5868e8752d44 603 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 604 pn_id = pns->nodes[0];
pythontech 0:5868e8752d44 605 pn_colon = pns->nodes[1];
pythontech 0:5868e8752d44 606 pn_equal = pns->nodes[2];
pythontech 0:5868e8752d44 607
pythontech 0:5868e8752d44 608 } else {
pythontech 0:5868e8752d44 609 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_name)); // should be
pythontech 0:5868e8752d44 610 // this parameter has an equal specifier
pythontech 0:5868e8752d44 611
pythontech 0:5868e8752d44 612 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 613 pn_id = pns->nodes[0];
pythontech 0:5868e8752d44 614 pn_equal = pns->nodes[1];
pythontech 0:5868e8752d44 615 }
pythontech 0:5868e8752d44 616
pythontech 0:5868e8752d44 617 if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
pythontech 0:5868e8752d44 618 // this parameter does not have a default value
pythontech 0:5868e8752d44 619
pythontech 0:5868e8752d44 620 // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
pythontech 0:5868e8752d44 621 if (!comp->have_star && comp->num_default_params != 0) {
pythontech 0:5868e8752d44 622 compile_syntax_error(comp, pn, "non-default argument follows default argument");
pythontech 0:5868e8752d44 623 return;
pythontech 0:5868e8752d44 624 }
pythontech 0:5868e8752d44 625
pythontech 0:5868e8752d44 626 } else {
pythontech 0:5868e8752d44 627 // this parameter has a default value
pythontech 0:5868e8752d44 628 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
pythontech 0:5868e8752d44 629
pythontech 0:5868e8752d44 630 if (comp->have_star) {
pythontech 0:5868e8752d44 631 comp->num_dict_params += 1;
pythontech 0:5868e8752d44 632 // in Micro Python we put the default dict parameters into a dictionary using the bytecode
pythontech 0:5868e8752d44 633 if (comp->num_dict_params == 1) {
pythontech 0:5868e8752d44 634 // in Micro Python we put the default positional parameters into a tuple using the bytecode
pythontech 0:5868e8752d44 635 // we need to do this here before we start building the map for the default keywords
pythontech 0:5868e8752d44 636 if (comp->num_default_params > 0) {
pythontech 0:5868e8752d44 637 EMIT_ARG(build_tuple, comp->num_default_params);
pythontech 0:5868e8752d44 638 } else {
pythontech 0:5868e8752d44 639 EMIT(load_null); // sentinel indicating empty default positional args
pythontech 0:5868e8752d44 640 }
pythontech 0:5868e8752d44 641 // first default dict param, so make the map
pythontech 0:5868e8752d44 642 EMIT_ARG(build_map, 0);
pythontech 0:5868e8752d44 643 }
pythontech 0:5868e8752d44 644
pythontech 0:5868e8752d44 645 // compile value then key, then store it to the dict
pythontech 0:5868e8752d44 646 compile_node(comp, pn_equal);
pythontech 0:5868e8752d44 647 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
pythontech 0:5868e8752d44 648 EMIT(store_map);
pythontech 0:5868e8752d44 649 } else {
pythontech 0:5868e8752d44 650 comp->num_default_params += 1;
pythontech 0:5868e8752d44 651 compile_node(comp, pn_equal);
pythontech 0:5868e8752d44 652 }
pythontech 0:5868e8752d44 653 }
pythontech 0:5868e8752d44 654
pythontech 0:5868e8752d44 655 // TODO pn_colon not implemented
pythontech 0:5868e8752d44 656 (void)pn_colon;
pythontech 0:5868e8752d44 657 }
pythontech 0:5868e8752d44 658 }
pythontech 0:5868e8752d44 659
pythontech 0:5868e8752d44 660 STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) {
pythontech 0:5868e8752d44 661 // When we call compile_funcdef_lambdef_param below it can compile an arbitrary
pythontech 0:5868e8752d44 662 // expression for default arguments, which may contain a lambda. The lambda will
pythontech 0:5868e8752d44 663 // call here in a nested way, so we must save and restore the relevant state.
pythontech 0:5868e8752d44 664 bool orig_have_star = comp->have_star;
pythontech 0:5868e8752d44 665 uint16_t orig_num_dict_params = comp->num_dict_params;
pythontech 0:5868e8752d44 666 uint16_t orig_num_default_params = comp->num_default_params;
pythontech 0:5868e8752d44 667
pythontech 0:5868e8752d44 668 // compile default parameters
pythontech 0:5868e8752d44 669 comp->have_star = false;
pythontech 0:5868e8752d44 670 comp->num_dict_params = 0;
pythontech 0:5868e8752d44 671 comp->num_default_params = 0;
pythontech 0:5868e8752d44 672 apply_to_single_or_list(comp, pn_params, pn_list_kind, compile_funcdef_lambdef_param);
pythontech 0:5868e8752d44 673
pythontech 0:5868e8752d44 674 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 675 return;
pythontech 0:5868e8752d44 676 }
pythontech 0:5868e8752d44 677
pythontech 0:5868e8752d44 678 // in Micro Python we put the default positional parameters into a tuple using the bytecode
pythontech 0:5868e8752d44 679 // the default keywords args may have already made the tuple; if not, do it now
pythontech 0:5868e8752d44 680 if (comp->num_default_params > 0 && comp->num_dict_params == 0) {
pythontech 0:5868e8752d44 681 EMIT_ARG(build_tuple, comp->num_default_params);
pythontech 0:5868e8752d44 682 EMIT(load_null); // sentinel indicating empty default keyword args
pythontech 0:5868e8752d44 683 }
pythontech 0:5868e8752d44 684
pythontech 0:5868e8752d44 685 // make the function
pythontech 0:5868e8752d44 686 close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);
pythontech 0:5868e8752d44 687
pythontech 0:5868e8752d44 688 // restore state
pythontech 0:5868e8752d44 689 comp->have_star = orig_have_star;
pythontech 0:5868e8752d44 690 comp->num_dict_params = orig_num_dict_params;
pythontech 0:5868e8752d44 691 comp->num_default_params = orig_num_default_params;
pythontech 0:5868e8752d44 692 }
pythontech 0:5868e8752d44 693
pythontech 0:5868e8752d44 694 // leaves function object on stack
pythontech 0:5868e8752d44 695 // returns function name
pythontech 0:5868e8752d44 696 STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
pythontech 0:5868e8752d44 697 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 698 // create a new scope for this function
pythontech 0:5868e8752d44 699 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
pythontech 0:5868e8752d44 700 // store the function scope so the compiling function can use it at each pass
pythontech 0:5868e8752d44 701 pns->nodes[4] = (mp_parse_node_t)s;
pythontech 0:5868e8752d44 702 }
pythontech 0:5868e8752d44 703
pythontech 0:5868e8752d44 704 // get the scope for this function
pythontech 0:5868e8752d44 705 scope_t *fscope = (scope_t*)pns->nodes[4];
pythontech 0:5868e8752d44 706
pythontech 0:5868e8752d44 707 // compile the function definition
pythontech 0:5868e8752d44 708 compile_funcdef_lambdef(comp, fscope, pns->nodes[1], PN_typedargslist);
pythontech 0:5868e8752d44 709
pythontech 0:5868e8752d44 710 // return its name (the 'f' in "def f(...):")
pythontech 0:5868e8752d44 711 return fscope->simple_name;
pythontech 0:5868e8752d44 712 }
pythontech 0:5868e8752d44 713
pythontech 0:5868e8752d44 714 // leaves class object on stack
pythontech 0:5868e8752d44 715 // returns class name
pythontech 0:5868e8752d44 716 STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
pythontech 0:5868e8752d44 717 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 718 // create a new scope for this class
pythontech 0:5868e8752d44 719 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
pythontech 0:5868e8752d44 720 // store the class scope so the compiling function can use it at each pass
pythontech 0:5868e8752d44 721 pns->nodes[3] = (mp_parse_node_t)s;
pythontech 0:5868e8752d44 722 }
pythontech 0:5868e8752d44 723
pythontech 0:5868e8752d44 724 EMIT(load_build_class);
pythontech 0:5868e8752d44 725
pythontech 0:5868e8752d44 726 // scope for this class
pythontech 0:5868e8752d44 727 scope_t *cscope = (scope_t*)pns->nodes[3];
pythontech 0:5868e8752d44 728
pythontech 0:5868e8752d44 729 // compile the class
pythontech 0:5868e8752d44 730 close_over_variables_etc(comp, cscope, 0, 0);
pythontech 0:5868e8752d44 731
pythontech 0:5868e8752d44 732 // get its name
pythontech 0:5868e8752d44 733 EMIT_ARG(load_const_str, cscope->simple_name);
pythontech 0:5868e8752d44 734
pythontech 0:5868e8752d44 735 // nodes[1] has parent classes, if any
pythontech 0:5868e8752d44 736 // empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling
pythontech 0:5868e8752d44 737 mp_parse_node_t parents = pns->nodes[1];
pythontech 0:5868e8752d44 738 if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
pythontech 0:5868e8752d44 739 parents = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 740 }
pythontech 0:5868e8752d44 741 comp->func_arg_is_super = false;
pythontech 0:5868e8752d44 742 compile_trailer_paren_helper(comp, parents, false, 2);
pythontech 0:5868e8752d44 743
pythontech 0:5868e8752d44 744 // return its name (the 'C' in class C(...):")
pythontech 0:5868e8752d44 745 return cscope->simple_name;
pythontech 0:5868e8752d44 746 }
pythontech 0:5868e8752d44 747
pythontech 0:5868e8752d44 748 // returns true if it was a built-in decorator (even if the built-in had an error)
pythontech 0:5868e8752d44 749 STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
pythontech 0:5868e8752d44 750 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
pythontech 0:5868e8752d44 751 return false;
pythontech 0:5868e8752d44 752 }
pythontech 0:5868e8752d44 753
pythontech 0:5868e8752d44 754 if (name_len != 2) {
pythontech 0:5868e8752d44 755 compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator");
pythontech 0:5868e8752d44 756 return true;
pythontech 0:5868e8752d44 757 }
pythontech 0:5868e8752d44 758
pythontech 0:5868e8752d44 759 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
pythontech 0:5868e8752d44 760 if (attr == MP_QSTR_bytecode) {
pythontech 0:5868e8752d44 761 *emit_options = MP_EMIT_OPT_BYTECODE;
pythontech 0:5868e8752d44 762 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 763 } else if (attr == MP_QSTR_native) {
pythontech 0:5868e8752d44 764 *emit_options = MP_EMIT_OPT_NATIVE_PYTHON;
pythontech 0:5868e8752d44 765 } else if (attr == MP_QSTR_viper) {
pythontech 0:5868e8752d44 766 *emit_options = MP_EMIT_OPT_VIPER;
pythontech 0:5868e8752d44 767 #endif
pythontech 0:5868e8752d44 768 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 769 } else if (attr == MP_QSTR_asm_thumb) {
pythontech 0:5868e8752d44 770 *emit_options = MP_EMIT_OPT_ASM_THUMB;
pythontech 0:5868e8752d44 771 #endif
pythontech 0:5868e8752d44 772 } else {
pythontech 0:5868e8752d44 773 compile_syntax_error(comp, name_nodes[1], "invalid micropython decorator");
pythontech 0:5868e8752d44 774 }
pythontech 0:5868e8752d44 775
pythontech 0:5868e8752d44 776 return true;
pythontech 0:5868e8752d44 777 }
pythontech 0:5868e8752d44 778
pythontech 0:5868e8752d44 779 STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 780 // get the list of decorators
pythontech 0:5868e8752d44 781 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 782 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_decorators, &nodes);
pythontech 0:5868e8752d44 783
pythontech 0:5868e8752d44 784 // inherit emit options for this function/class definition
pythontech 0:5868e8752d44 785 uint emit_options = comp->scope_cur->emit_options;
pythontech 0:5868e8752d44 786
pythontech 0:5868e8752d44 787 // compile each decorator
pythontech 0:5868e8752d44 788 int num_built_in_decorators = 0;
pythontech 0:5868e8752d44 789 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 790 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
pythontech 0:5868e8752d44 791 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
pythontech 0:5868e8752d44 792
pythontech 0:5868e8752d44 793 // nodes[0] contains the decorator function, which is a dotted name
pythontech 0:5868e8752d44 794 mp_parse_node_t *name_nodes;
pythontech 0:5868e8752d44 795 int name_len = mp_parse_node_extract_list(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
pythontech 0:5868e8752d44 796
pythontech 0:5868e8752d44 797 // check for built-in decorators
pythontech 0:5868e8752d44 798 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
pythontech 0:5868e8752d44 799 // this was a built-in
pythontech 0:5868e8752d44 800 num_built_in_decorators += 1;
pythontech 0:5868e8752d44 801
pythontech 0:5868e8752d44 802 } else {
pythontech 0:5868e8752d44 803 // not a built-in, compile normally
pythontech 0:5868e8752d44 804
pythontech 0:5868e8752d44 805 // compile the decorator function
pythontech 0:5868e8752d44 806 compile_node(comp, name_nodes[0]);
pythontech 0:5868e8752d44 807 for (int j = 1; j < name_len; j++) {
pythontech 0:5868e8752d44 808 assert(MP_PARSE_NODE_IS_ID(name_nodes[j])); // should be
pythontech 0:5868e8752d44 809 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[j]));
pythontech 0:5868e8752d44 810 }
pythontech 0:5868e8752d44 811
pythontech 0:5868e8752d44 812 // nodes[1] contains arguments to the decorator function, if any
pythontech 0:5868e8752d44 813 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
pythontech 0:5868e8752d44 814 // call the decorator function with the arguments in nodes[1]
pythontech 0:5868e8752d44 815 comp->func_arg_is_super = false;
pythontech 0:5868e8752d44 816 compile_node(comp, pns_decorator->nodes[1]);
pythontech 0:5868e8752d44 817 }
pythontech 0:5868e8752d44 818 }
pythontech 0:5868e8752d44 819 }
pythontech 0:5868e8752d44 820
pythontech 0:5868e8752d44 821 // compile the body (funcdef or classdef) and get its name
pythontech 0:5868e8752d44 822 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 823 qstr body_name = 0;
pythontech 0:5868e8752d44 824 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
pythontech 0:5868e8752d44 825 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
pythontech 0:5868e8752d44 826 } else {
pythontech 0:5868e8752d44 827 assert(MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef); // should be
pythontech 0:5868e8752d44 828 body_name = compile_classdef_helper(comp, pns_body, emit_options);
pythontech 0:5868e8752d44 829 }
pythontech 0:5868e8752d44 830
pythontech 0:5868e8752d44 831 // call each decorator
pythontech 0:5868e8752d44 832 for (int i = 0; i < n - num_built_in_decorators; i++) {
pythontech 0:5868e8752d44 833 EMIT_ARG(call_function, 1, 0, 0);
pythontech 0:5868e8752d44 834 }
pythontech 0:5868e8752d44 835
pythontech 0:5868e8752d44 836 // store func/class object into name
pythontech 0:5868e8752d44 837 compile_store_id(comp, body_name);
pythontech 0:5868e8752d44 838 }
pythontech 0:5868e8752d44 839
pythontech 0:5868e8752d44 840 STATIC void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 841 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
pythontech 0:5868e8752d44 842 // store function object into function name
pythontech 0:5868e8752d44 843 compile_store_id(comp, fname);
pythontech 0:5868e8752d44 844 }
pythontech 0:5868e8752d44 845
pythontech 0:5868e8752d44 846 STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 847 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 848 compile_delete_id(comp, MP_PARSE_NODE_LEAF_ARG(pn));
pythontech 0:5868e8752d44 849 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_power)) {
pythontech 0:5868e8752d44 850 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 851
pythontech 0:5868e8752d44 852 compile_node(comp, pns->nodes[0]); // base of the power node
pythontech 0:5868e8752d44 853
pythontech 0:5868e8752d44 854 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 855 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 856 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_power_trailers) {
pythontech 0:5868e8752d44 857 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
pythontech 0:5868e8752d44 858 for (int i = 0; i < n - 1; i++) {
pythontech 0:5868e8752d44 859 compile_node(comp, pns1->nodes[i]);
pythontech 0:5868e8752d44 860 }
pythontech 0:5868e8752d44 861 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
pythontech 0:5868e8752d44 862 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
pythontech 0:5868e8752d44 863 }
pythontech 0:5868e8752d44 864 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
pythontech 0:5868e8752d44 865 compile_node(comp, pns1->nodes[0]);
pythontech 0:5868e8752d44 866 EMIT(delete_subscr);
pythontech 0:5868e8752d44 867 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
pythontech 0:5868e8752d44 868 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
pythontech 0:5868e8752d44 869 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
pythontech 0:5868e8752d44 870 } else {
pythontech 0:5868e8752d44 871 goto cannot_delete;
pythontech 0:5868e8752d44 872 }
pythontech 0:5868e8752d44 873 } else {
pythontech 0:5868e8752d44 874 goto cannot_delete;
pythontech 0:5868e8752d44 875 }
pythontech 0:5868e8752d44 876
pythontech 0:5868e8752d44 877 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
pythontech 0:5868e8752d44 878 goto cannot_delete;
pythontech 0:5868e8752d44 879 }
pythontech 0:5868e8752d44 880 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
pythontech 0:5868e8752d44 881 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
pythontech 0:5868e8752d44 882 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 883 goto cannot_delete;
pythontech 0:5868e8752d44 884 } else {
pythontech 0:5868e8752d44 885 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp));
pythontech 0:5868e8752d44 886 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 887 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
pythontech 0:5868e8752d44 888
pythontech 0:5868e8752d44 889 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 890 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 891 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
pythontech 0:5868e8752d44 892 // sequence of one item, with trailing comma
pythontech 0:5868e8752d44 893 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
pythontech 0:5868e8752d44 894 c_del_stmt(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 895 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
pythontech 0:5868e8752d44 896 // sequence of many items
pythontech 0:5868e8752d44 897 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
pythontech 0:5868e8752d44 898 c_del_stmt(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 899 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 900 c_del_stmt(comp, pns1->nodes[i]);
pythontech 0:5868e8752d44 901 }
pythontech 0:5868e8752d44 902 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
pythontech 0:5868e8752d44 903 // TODO not implemented; can't del comprehension? can we get here?
pythontech 0:5868e8752d44 904 goto cannot_delete;
pythontech 0:5868e8752d44 905 } else {
pythontech 0:5868e8752d44 906 // sequence with 2 items
pythontech 0:5868e8752d44 907 goto sequence_with_2_items;
pythontech 0:5868e8752d44 908 }
pythontech 0:5868e8752d44 909 } else {
pythontech 0:5868e8752d44 910 // sequence with 2 items
pythontech 0:5868e8752d44 911 sequence_with_2_items:
pythontech 0:5868e8752d44 912 c_del_stmt(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 913 c_del_stmt(comp, pns->nodes[1]);
pythontech 0:5868e8752d44 914 }
pythontech 0:5868e8752d44 915 }
pythontech 0:5868e8752d44 916 } else {
pythontech 0:5868e8752d44 917 // some arbitrary statment that we can't delete (eg del 1)
pythontech 0:5868e8752d44 918 goto cannot_delete;
pythontech 0:5868e8752d44 919 }
pythontech 0:5868e8752d44 920
pythontech 0:5868e8752d44 921 return;
pythontech 0:5868e8752d44 922
pythontech 0:5868e8752d44 923 cannot_delete:
pythontech 0:5868e8752d44 924 compile_syntax_error(comp, (mp_parse_node_t)pn, "can't delete expression");
pythontech 0:5868e8752d44 925 }
pythontech 0:5868e8752d44 926
pythontech 0:5868e8752d44 927 STATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 928 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
pythontech 0:5868e8752d44 929 }
pythontech 0:5868e8752d44 930
pythontech 0:5868e8752d44 931 STATIC void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 932 if (comp->break_label == 0) {
pythontech 0:5868e8752d44 933 compile_syntax_error(comp, (mp_parse_node_t)pns, "'break' outside loop");
pythontech 0:5868e8752d44 934 }
pythontech 0:5868e8752d44 935 assert(comp->cur_except_level >= comp->break_continue_except_level);
pythontech 0:5868e8752d44 936 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
pythontech 0:5868e8752d44 937 }
pythontech 0:5868e8752d44 938
pythontech 0:5868e8752d44 939 STATIC void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 940 if (comp->continue_label == 0) {
pythontech 0:5868e8752d44 941 compile_syntax_error(comp, (mp_parse_node_t)pns, "'continue' outside loop");
pythontech 0:5868e8752d44 942 }
pythontech 0:5868e8752d44 943 assert(comp->cur_except_level >= comp->break_continue_except_level);
pythontech 0:5868e8752d44 944 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
pythontech 0:5868e8752d44 945 }
pythontech 0:5868e8752d44 946
pythontech 0:5868e8752d44 947 STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 948 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
pythontech 0:5868e8752d44 949 compile_syntax_error(comp, (mp_parse_node_t)pns, "'return' outside function");
pythontech 0:5868e8752d44 950 return;
pythontech 0:5868e8752d44 951 }
pythontech 0:5868e8752d44 952 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 953 // no argument to 'return', so return None
pythontech 0:5868e8752d44 954 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 955 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
pythontech 0:5868e8752d44 956 // special case when returning an if-expression; to match CPython optimisation
pythontech 0:5868e8752d44 957 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 958 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];
pythontech 0:5868e8752d44 959
pythontech 0:5868e8752d44 960 uint l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 961 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
pythontech 0:5868e8752d44 962 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
pythontech 0:5868e8752d44 963 EMIT(return_value);
pythontech 0:5868e8752d44 964 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 965 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
pythontech 0:5868e8752d44 966 } else {
pythontech 0:5868e8752d44 967 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 968 }
pythontech 0:5868e8752d44 969 EMIT(return_value);
pythontech 0:5868e8752d44 970 }
pythontech 0:5868e8752d44 971
pythontech 0:5868e8752d44 972 STATIC void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 973 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 974 EMIT(pop_top);
pythontech 0:5868e8752d44 975 }
pythontech 0:5868e8752d44 976
pythontech 0:5868e8752d44 977 STATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 978 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 979 // raise
pythontech 0:5868e8752d44 980 EMIT_ARG(raise_varargs, 0);
pythontech 0:5868e8752d44 981 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
pythontech 0:5868e8752d44 982 // raise x from y
pythontech 0:5868e8752d44 983 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 984 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 985 compile_node(comp, pns->nodes[1]);
pythontech 0:5868e8752d44 986 EMIT_ARG(raise_varargs, 2);
pythontech 0:5868e8752d44 987 } else {
pythontech 0:5868e8752d44 988 // raise x
pythontech 0:5868e8752d44 989 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 990 EMIT_ARG(raise_varargs, 1);
pythontech 0:5868e8752d44 991 }
pythontech 0:5868e8752d44 992 }
pythontech 0:5868e8752d44 993
pythontech 0:5868e8752d44 994 // q_base holds the base of the name
pythontech 0:5868e8752d44 995 // eg a -> q_base=a
pythontech 0:5868e8752d44 996 // a.b.c -> q_base=a
pythontech 0:5868e8752d44 997 STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
pythontech 0:5868e8752d44 998 bool is_as = false;
pythontech 0:5868e8752d44 999 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
pythontech 0:5868e8752d44 1000 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 1001 // a name of the form x as y; unwrap it
pythontech 0:5868e8752d44 1002 *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
pythontech 0:5868e8752d44 1003 pn = pns->nodes[0];
pythontech 0:5868e8752d44 1004 is_as = true;
pythontech 0:5868e8752d44 1005 }
pythontech 0:5868e8752d44 1006 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 1007 // empty name (eg, from . import x)
pythontech 0:5868e8752d44 1008 *q_base = MP_QSTR_;
pythontech 0:5868e8752d44 1009 EMIT_ARG(import_name, MP_QSTR_); // import the empty string
pythontech 0:5868e8752d44 1010 } else if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 1011 // just a simple name
pythontech 0:5868e8752d44 1012 qstr q_full = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 1013 if (!is_as) {
pythontech 0:5868e8752d44 1014 *q_base = q_full;
pythontech 0:5868e8752d44 1015 }
pythontech 0:5868e8752d44 1016 EMIT_ARG(import_name, q_full);
pythontech 0:5868e8752d44 1017 } else {
pythontech 0:5868e8752d44 1018 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_name)); // should be
pythontech 0:5868e8752d44 1019 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 1020 {
pythontech 0:5868e8752d44 1021 // a name of the form a.b.c
pythontech 0:5868e8752d44 1022 if (!is_as) {
pythontech 0:5868e8752d44 1023 *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 1024 }
pythontech 0:5868e8752d44 1025 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1026 int len = n - 1;
pythontech 0:5868e8752d44 1027 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1028 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
pythontech 0:5868e8752d44 1029 }
pythontech 0:5868e8752d44 1030 byte *q_ptr;
pythontech 0:5868e8752d44 1031 byte *str_dest = qstr_build_start(len, &q_ptr);
pythontech 0:5868e8752d44 1032 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1033 if (i > 0) {
pythontech 0:5868e8752d44 1034 *str_dest++ = '.';
pythontech 0:5868e8752d44 1035 }
pythontech 0:5868e8752d44 1036 size_t str_src_len;
pythontech 0:5868e8752d44 1037 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
pythontech 0:5868e8752d44 1038 memcpy(str_dest, str_src, str_src_len);
pythontech 0:5868e8752d44 1039 str_dest += str_src_len;
pythontech 0:5868e8752d44 1040 }
pythontech 0:5868e8752d44 1041 qstr q_full = qstr_build_end(q_ptr);
pythontech 0:5868e8752d44 1042 EMIT_ARG(import_name, q_full);
pythontech 0:5868e8752d44 1043 if (is_as) {
pythontech 0:5868e8752d44 1044 for (int i = 1; i < n; i++) {
pythontech 0:5868e8752d44 1045 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
pythontech 0:5868e8752d44 1046 }
pythontech 0:5868e8752d44 1047 }
pythontech 0:5868e8752d44 1048 }
pythontech 0:5868e8752d44 1049 }
pythontech 0:5868e8752d44 1050 }
pythontech 0:5868e8752d44 1051
pythontech 0:5868e8752d44 1052 STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 1053 EMIT_ARG(load_const_small_int, 0); // level 0 import
pythontech 0:5868e8752d44 1054 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything
pythontech 0:5868e8752d44 1055 qstr q_base;
pythontech 0:5868e8752d44 1056 do_import_name(comp, pn, &q_base);
pythontech 0:5868e8752d44 1057 compile_store_id(comp, q_base);
pythontech 0:5868e8752d44 1058 }
pythontech 0:5868e8752d44 1059
pythontech 0:5868e8752d44 1060 STATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1061 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
pythontech 0:5868e8752d44 1062 }
pythontech 0:5868e8752d44 1063
pythontech 0:5868e8752d44 1064 STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1065 mp_parse_node_t pn_import_source = pns->nodes[0];
pythontech 0:5868e8752d44 1066
pythontech 0:5868e8752d44 1067 // extract the preceeding .'s (if any) for a relative import, to compute the import level
pythontech 0:5868e8752d44 1068 uint import_level = 0;
pythontech 0:5868e8752d44 1069 do {
pythontech 0:5868e8752d44 1070 mp_parse_node_t pn_rel;
pythontech 0:5868e8752d44 1071 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)) {
pythontech 0:5868e8752d44 1072 // This covers relative imports with dots only like "from .. import"
pythontech 0:5868e8752d44 1073 pn_rel = pn_import_source;
pythontech 0:5868e8752d44 1074 pn_import_source = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 1075 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_import_from_2b)) {
pythontech 0:5868e8752d44 1076 // This covers relative imports starting with dot(s) like "from .foo import"
pythontech 0:5868e8752d44 1077 mp_parse_node_struct_t *pns_2b = (mp_parse_node_struct_t*)pn_import_source;
pythontech 0:5868e8752d44 1078 pn_rel = pns_2b->nodes[0];
pythontech 0:5868e8752d44 1079 pn_import_source = pns_2b->nodes[1];
pythontech 0:5868e8752d44 1080 assert(!MP_PARSE_NODE_IS_NULL(pn_import_source)); // should not be
pythontech 0:5868e8752d44 1081 } else {
pythontech 0:5868e8752d44 1082 // Not a relative import
pythontech 0:5868e8752d44 1083 break;
pythontech 0:5868e8752d44 1084 }
pythontech 0:5868e8752d44 1085
pythontech 0:5868e8752d44 1086 // get the list of . and/or ...'s
pythontech 0:5868e8752d44 1087 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 1088 int n = mp_parse_node_extract_list(&pn_rel, PN_one_or_more_period_or_ellipsis, &nodes);
pythontech 0:5868e8752d44 1089
pythontech 0:5868e8752d44 1090 // count the total number of .'s
pythontech 0:5868e8752d44 1091 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1092 if (MP_PARSE_NODE_IS_TOKEN_KIND(nodes[i], MP_TOKEN_DEL_PERIOD)) {
pythontech 0:5868e8752d44 1093 import_level++;
pythontech 0:5868e8752d44 1094 } else {
pythontech 0:5868e8752d44 1095 // should be an MP_TOKEN_ELLIPSIS
pythontech 0:5868e8752d44 1096 import_level += 3;
pythontech 0:5868e8752d44 1097 }
pythontech 0:5868e8752d44 1098 }
pythontech 0:5868e8752d44 1099 } while (0);
pythontech 0:5868e8752d44 1100
pythontech 0:5868e8752d44 1101 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
pythontech 0:5868e8752d44 1102 EMIT_ARG(load_const_small_int, import_level);
pythontech 0:5868e8752d44 1103
pythontech 0:5868e8752d44 1104 // build the "fromlist" tuple
pythontech 0:5868e8752d44 1105 EMIT_ARG(load_const_str, MP_QSTR__star_);
pythontech 0:5868e8752d44 1106 EMIT_ARG(build_tuple, 1);
pythontech 0:5868e8752d44 1107
pythontech 0:5868e8752d44 1108 // do the import
pythontech 0:5868e8752d44 1109 qstr dummy_q;
pythontech 0:5868e8752d44 1110 do_import_name(comp, pn_import_source, &dummy_q);
pythontech 0:5868e8752d44 1111 EMIT(import_star);
pythontech 0:5868e8752d44 1112
pythontech 0:5868e8752d44 1113 } else {
pythontech 0:5868e8752d44 1114 EMIT_ARG(load_const_small_int, import_level);
pythontech 0:5868e8752d44 1115
pythontech 0:5868e8752d44 1116 // build the "fromlist" tuple
pythontech 0:5868e8752d44 1117 mp_parse_node_t *pn_nodes;
pythontech 0:5868e8752d44 1118 int n = mp_parse_node_extract_list(&pns->nodes[1], PN_import_as_names, &pn_nodes);
pythontech 0:5868e8752d44 1119 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1120 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
pythontech 0:5868e8752d44 1121 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
pythontech 0:5868e8752d44 1122 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
pythontech 0:5868e8752d44 1123 EMIT_ARG(load_const_str, id2);
pythontech 0:5868e8752d44 1124 }
pythontech 0:5868e8752d44 1125 EMIT_ARG(build_tuple, n);
pythontech 0:5868e8752d44 1126
pythontech 0:5868e8752d44 1127 // do the import
pythontech 0:5868e8752d44 1128 qstr dummy_q;
pythontech 0:5868e8752d44 1129 do_import_name(comp, pn_import_source, &dummy_q);
pythontech 0:5868e8752d44 1130 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1131 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
pythontech 0:5868e8752d44 1132 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
pythontech 0:5868e8752d44 1133 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
pythontech 0:5868e8752d44 1134 EMIT_ARG(import_from, id2);
pythontech 0:5868e8752d44 1135 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
pythontech 0:5868e8752d44 1136 compile_store_id(comp, id2);
pythontech 0:5868e8752d44 1137 } else {
pythontech 0:5868e8752d44 1138 compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
pythontech 0:5868e8752d44 1139 }
pythontech 0:5868e8752d44 1140 }
pythontech 0:5868e8752d44 1141 EMIT(pop_top);
pythontech 0:5868e8752d44 1142 }
pythontech 0:5868e8752d44 1143 }
pythontech 0:5868e8752d44 1144
pythontech 0:5868e8752d44 1145 STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
pythontech 0:5868e8752d44 1146 bool added;
pythontech 0:5868e8752d44 1147 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
pythontech 0:5868e8752d44 1148 if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
pythontech 0:5868e8752d44 1149 compile_syntax_error(comp, pn, "identifier redefined as global");
pythontech 0:5868e8752d44 1150 return;
pythontech 0:5868e8752d44 1151 }
pythontech 0:5868e8752d44 1152 id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
pythontech 0:5868e8752d44 1153
pythontech 0:5868e8752d44 1154 // if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL
pythontech 0:5868e8752d44 1155 id_info = scope_find_global(comp->scope_cur, qst);
pythontech 0:5868e8752d44 1156 if (id_info != NULL) {
pythontech 0:5868e8752d44 1157 id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
pythontech 0:5868e8752d44 1158 }
pythontech 0:5868e8752d44 1159 }
pythontech 0:5868e8752d44 1160
pythontech 0:5868e8752d44 1161 STATIC void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1162 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 1163 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 1164 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
pythontech 0:5868e8752d44 1165 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1166 compile_declare_global(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));
pythontech 0:5868e8752d44 1167 }
pythontech 0:5868e8752d44 1168 }
pythontech 0:5868e8752d44 1169 }
pythontech 0:5868e8752d44 1170
pythontech 0:5868e8752d44 1171 STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
pythontech 0:5868e8752d44 1172 bool added;
pythontech 0:5868e8752d44 1173 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
pythontech 0:5868e8752d44 1174 if (!added && id_info->kind != ID_INFO_KIND_FREE) {
pythontech 0:5868e8752d44 1175 compile_syntax_error(comp, pn, "identifier redefined as nonlocal");
pythontech 0:5868e8752d44 1176 return;
pythontech 0:5868e8752d44 1177 }
pythontech 0:5868e8752d44 1178 id_info_t *id_info2 = scope_find_local_in_parent(comp->scope_cur, qst);
pythontech 0:5868e8752d44 1179 if (id_info2 == NULL || !(id_info2->kind == ID_INFO_KIND_LOCAL || id_info2->kind == ID_INFO_KIND_CELL || id_info2->kind == ID_INFO_KIND_FREE)) {
pythontech 0:5868e8752d44 1180 compile_syntax_error(comp, pn, "no binding for nonlocal found");
pythontech 0:5868e8752d44 1181 return;
pythontech 0:5868e8752d44 1182 }
pythontech 0:5868e8752d44 1183 id_info->kind = ID_INFO_KIND_FREE;
pythontech 0:5868e8752d44 1184 scope_close_over_in_parents(comp->scope_cur, qst);
pythontech 0:5868e8752d44 1185 }
pythontech 0:5868e8752d44 1186
pythontech 0:5868e8752d44 1187 STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1188 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 1189 if (comp->scope_cur->kind == SCOPE_MODULE) {
pythontech 0:5868e8752d44 1190 compile_syntax_error(comp, (mp_parse_node_t)pns, "can't declare nonlocal in outer code");
pythontech 0:5868e8752d44 1191 return;
pythontech 0:5868e8752d44 1192 }
pythontech 0:5868e8752d44 1193 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 1194 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
pythontech 0:5868e8752d44 1195 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1196 compile_declare_nonlocal(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));
pythontech 0:5868e8752d44 1197 }
pythontech 0:5868e8752d44 1198 }
pythontech 0:5868e8752d44 1199 }
pythontech 0:5868e8752d44 1200
pythontech 0:5868e8752d44 1201 STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1202 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1203 c_if_cond(comp, pns->nodes[0], true, l_end);
pythontech 0:5868e8752d44 1204 EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
pythontech 0:5868e8752d44 1205 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
pythontech 0:5868e8752d44 1206 // assertion message
pythontech 0:5868e8752d44 1207 compile_node(comp, pns->nodes[1]);
pythontech 0:5868e8752d44 1208 EMIT_ARG(call_function, 1, 0, 0);
pythontech 0:5868e8752d44 1209 }
pythontech 0:5868e8752d44 1210 EMIT_ARG(raise_varargs, 1);
pythontech 0:5868e8752d44 1211 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1212 }
pythontech 0:5868e8752d44 1213
pythontech 0:5868e8752d44 1214 STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1215 // TODO proper and/or short circuiting
pythontech 0:5868e8752d44 1216
pythontech 0:5868e8752d44 1217 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1218
pythontech 0:5868e8752d44 1219 // optimisation: don't emit anything when "if False"
pythontech 0:5868e8752d44 1220 if (!node_is_const_false(pns->nodes[0])) {
pythontech 0:5868e8752d44 1221 uint l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 1222 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
pythontech 0:5868e8752d44 1223
pythontech 0:5868e8752d44 1224 compile_node(comp, pns->nodes[1]); // if block
pythontech 0:5868e8752d44 1225
pythontech 0:5868e8752d44 1226 // optimisation: skip everything else when "if True"
pythontech 0:5868e8752d44 1227 if (node_is_const_true(pns->nodes[0])) {
pythontech 0:5868e8752d44 1228 goto done;
pythontech 0:5868e8752d44 1229 }
pythontech 0:5868e8752d44 1230
pythontech 0:5868e8752d44 1231 if (
pythontech 0:5868e8752d44 1232 // optimisation: don't jump over non-existent elif/else blocks
pythontech 0:5868e8752d44 1233 !(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))
pythontech 0:5868e8752d44 1234 // optimisation: don't jump if last instruction was return
pythontech 0:5868e8752d44 1235 && !EMIT(last_emit_was_return_value)
pythontech 0:5868e8752d44 1236 ) {
pythontech 0:5868e8752d44 1237 // jump over elif/else blocks
pythontech 0:5868e8752d44 1238 EMIT_ARG(jump, l_end);
pythontech 0:5868e8752d44 1239 }
pythontech 0:5868e8752d44 1240
pythontech 0:5868e8752d44 1241 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 1242 }
pythontech 0:5868e8752d44 1243
pythontech 0:5868e8752d44 1244 // compile elif blocks (if any)
pythontech 0:5868e8752d44 1245 mp_parse_node_t *pn_elif;
pythontech 0:5868e8752d44 1246 int n_elif = mp_parse_node_extract_list(&pns->nodes[2], PN_if_stmt_elif_list, &pn_elif);
pythontech 0:5868e8752d44 1247 for (int i = 0; i < n_elif; i++) {
pythontech 0:5868e8752d44 1248 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_elif[i], PN_if_stmt_elif)); // should be
pythontech 0:5868e8752d44 1249 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pn_elif[i];
pythontech 0:5868e8752d44 1250
pythontech 0:5868e8752d44 1251 // optimisation: don't emit anything when "if False"
pythontech 0:5868e8752d44 1252 if (!node_is_const_false(pns_elif->nodes[0])) {
pythontech 0:5868e8752d44 1253 uint l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 1254 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
pythontech 0:5868e8752d44 1255
pythontech 0:5868e8752d44 1256 compile_node(comp, pns_elif->nodes[1]); // elif block
pythontech 0:5868e8752d44 1257
pythontech 0:5868e8752d44 1258 // optimisation: skip everything else when "elif True"
pythontech 0:5868e8752d44 1259 if (node_is_const_true(pns_elif->nodes[0])) {
pythontech 0:5868e8752d44 1260 goto done;
pythontech 0:5868e8752d44 1261 }
pythontech 0:5868e8752d44 1262
pythontech 0:5868e8752d44 1263 // optimisation: don't jump if last instruction was return
pythontech 0:5868e8752d44 1264 if (!EMIT(last_emit_was_return_value)) {
pythontech 0:5868e8752d44 1265 EMIT_ARG(jump, l_end);
pythontech 0:5868e8752d44 1266 }
pythontech 0:5868e8752d44 1267 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 1268 }
pythontech 0:5868e8752d44 1269 }
pythontech 0:5868e8752d44 1270
pythontech 0:5868e8752d44 1271 // compile else block
pythontech 0:5868e8752d44 1272 compile_node(comp, pns->nodes[3]); // can be null
pythontech 0:5868e8752d44 1273
pythontech 0:5868e8752d44 1274 done:
pythontech 0:5868e8752d44 1275 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1276 }
pythontech 0:5868e8752d44 1277
pythontech 0:5868e8752d44 1278 #define START_BREAK_CONTINUE_BLOCK \
pythontech 0:5868e8752d44 1279 uint16_t old_break_label = comp->break_label; \
pythontech 0:5868e8752d44 1280 uint16_t old_continue_label = comp->continue_label; \
pythontech 0:5868e8752d44 1281 uint16_t old_break_continue_except_level = comp->break_continue_except_level; \
pythontech 0:5868e8752d44 1282 uint break_label = comp_next_label(comp); \
pythontech 0:5868e8752d44 1283 uint continue_label = comp_next_label(comp); \
pythontech 0:5868e8752d44 1284 comp->break_label = break_label; \
pythontech 0:5868e8752d44 1285 comp->continue_label = continue_label; \
pythontech 0:5868e8752d44 1286 comp->break_continue_except_level = comp->cur_except_level;
pythontech 0:5868e8752d44 1287
pythontech 0:5868e8752d44 1288 #define END_BREAK_CONTINUE_BLOCK \
pythontech 0:5868e8752d44 1289 comp->break_label = old_break_label; \
pythontech 0:5868e8752d44 1290 comp->continue_label = old_continue_label; \
pythontech 0:5868e8752d44 1291 comp->break_continue_except_level = old_break_continue_except_level;
pythontech 0:5868e8752d44 1292
pythontech 0:5868e8752d44 1293 STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1294 START_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1295
pythontech 0:5868e8752d44 1296 if (!node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False"
pythontech 0:5868e8752d44 1297 uint top_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1298 if (!node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for "while True"
pythontech 0:5868e8752d44 1299 EMIT_ARG(jump, continue_label);
pythontech 0:5868e8752d44 1300 }
pythontech 0:5868e8752d44 1301 EMIT_ARG(label_assign, top_label);
pythontech 0:5868e8752d44 1302 compile_node(comp, pns->nodes[1]); // body
pythontech 0:5868e8752d44 1303 EMIT_ARG(label_assign, continue_label);
pythontech 0:5868e8752d44 1304 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
pythontech 0:5868e8752d44 1305 }
pythontech 0:5868e8752d44 1306
pythontech 0:5868e8752d44 1307 // break/continue apply to outer loop (if any) in the else block
pythontech 0:5868e8752d44 1308 END_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1309
pythontech 0:5868e8752d44 1310 compile_node(comp, pns->nodes[2]); // else
pythontech 0:5868e8752d44 1311
pythontech 0:5868e8752d44 1312 EMIT_ARG(label_assign, break_label);
pythontech 0:5868e8752d44 1313 }
pythontech 0:5868e8752d44 1314
pythontech 0:5868e8752d44 1315 // This function compiles an optimised for-loop of the form:
pythontech 0:5868e8752d44 1316 // for <var> in range(<start>, <end>, <step>):
pythontech 0:5868e8752d44 1317 // <body>
pythontech 0:5868e8752d44 1318 // else:
pythontech 0:5868e8752d44 1319 // <else>
pythontech 0:5868e8752d44 1320 // <var> must be an identifier and <step> must be a small-int.
pythontech 0:5868e8752d44 1321 //
pythontech 0:5868e8752d44 1322 // Semantics of for-loop require:
pythontech 0:5868e8752d44 1323 // - final failing value should not be stored in the loop variable
pythontech 0:5868e8752d44 1324 // - if the loop never runs, the loop variable should never be assigned
pythontech 0:5868e8752d44 1325 // - assignments to <var>, <end> or <step> in the body do not alter the loop
pythontech 0:5868e8752d44 1326 // (<step> is a constant for us, so no need to worry about it changing)
pythontech 0:5868e8752d44 1327 //
pythontech 0:5868e8752d44 1328 // If <end> is a small-int, then the stack during the for-loop contains just
pythontech 0:5868e8752d44 1329 // the current value of <var>. Otherwise, the stack contains <end> then the
pythontech 0:5868e8752d44 1330 // current value of <var>.
pythontech 0:5868e8752d44 1331 STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) {
pythontech 0:5868e8752d44 1332 START_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1333
pythontech 0:5868e8752d44 1334 uint top_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1335 uint entry_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1336
pythontech 0:5868e8752d44 1337 // put the end value on the stack if it's not a small-int constant
pythontech 0:5868e8752d44 1338 bool end_on_stack = !MP_PARSE_NODE_IS_SMALL_INT(pn_end);
pythontech 0:5868e8752d44 1339 if (end_on_stack) {
pythontech 0:5868e8752d44 1340 compile_node(comp, pn_end);
pythontech 0:5868e8752d44 1341 }
pythontech 0:5868e8752d44 1342
pythontech 0:5868e8752d44 1343 // compile: start
pythontech 0:5868e8752d44 1344 compile_node(comp, pn_start);
pythontech 0:5868e8752d44 1345
pythontech 0:5868e8752d44 1346 EMIT_ARG(jump, entry_label);
pythontech 0:5868e8752d44 1347 EMIT_ARG(label_assign, top_label);
pythontech 0:5868e8752d44 1348
pythontech 0:5868e8752d44 1349 // duplicate next value and store it to var
pythontech 0:5868e8752d44 1350 EMIT(dup_top);
pythontech 0:5868e8752d44 1351 c_assign(comp, pn_var, ASSIGN_STORE);
pythontech 0:5868e8752d44 1352
pythontech 0:5868e8752d44 1353 // compile body
pythontech 0:5868e8752d44 1354 compile_node(comp, pn_body);
pythontech 0:5868e8752d44 1355
pythontech 0:5868e8752d44 1356 EMIT_ARG(label_assign, continue_label);
pythontech 0:5868e8752d44 1357
pythontech 0:5868e8752d44 1358 // compile: var + step
pythontech 0:5868e8752d44 1359 compile_node(comp, pn_step);
pythontech 0:5868e8752d44 1360 EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);
pythontech 0:5868e8752d44 1361
pythontech 0:5868e8752d44 1362 EMIT_ARG(label_assign, entry_label);
pythontech 0:5868e8752d44 1363
pythontech 0:5868e8752d44 1364 // compile: if var <cond> end: goto top
pythontech 0:5868e8752d44 1365 if (end_on_stack) {
pythontech 0:5868e8752d44 1366 EMIT(dup_top_two);
pythontech 0:5868e8752d44 1367 EMIT(rot_two);
pythontech 0:5868e8752d44 1368 } else {
pythontech 0:5868e8752d44 1369 EMIT(dup_top);
pythontech 0:5868e8752d44 1370 compile_node(comp, pn_end);
pythontech 0:5868e8752d44 1371 }
pythontech 0:5868e8752d44 1372 assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
pythontech 0:5868e8752d44 1373 if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
pythontech 0:5868e8752d44 1374 EMIT_ARG(binary_op, MP_BINARY_OP_LESS);
pythontech 0:5868e8752d44 1375 } else {
pythontech 0:5868e8752d44 1376 EMIT_ARG(binary_op, MP_BINARY_OP_MORE);
pythontech 0:5868e8752d44 1377 }
pythontech 0:5868e8752d44 1378 EMIT_ARG(pop_jump_if, true, top_label);
pythontech 0:5868e8752d44 1379
pythontech 0:5868e8752d44 1380 // break/continue apply to outer loop (if any) in the else block
pythontech 0:5868e8752d44 1381 END_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1382
pythontech 0:5868e8752d44 1383 compile_node(comp, pn_else);
pythontech 0:5868e8752d44 1384
pythontech 0:5868e8752d44 1385 EMIT_ARG(label_assign, break_label);
pythontech 0:5868e8752d44 1386
pythontech 0:5868e8752d44 1387 // discard final value of var that failed the loop condition
pythontech 0:5868e8752d44 1388 EMIT(pop_top);
pythontech 0:5868e8752d44 1389
pythontech 0:5868e8752d44 1390 // discard <end> value if it's on the stack
pythontech 0:5868e8752d44 1391 if (end_on_stack) {
pythontech 0:5868e8752d44 1392 EMIT(pop_top);
pythontech 0:5868e8752d44 1393 }
pythontech 0:5868e8752d44 1394 }
pythontech 0:5868e8752d44 1395
pythontech 0:5868e8752d44 1396 STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1397 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
pythontech 0:5868e8752d44 1398 // this is actually slower, but uses no heap memory
pythontech 0:5868e8752d44 1399 // for viper it will be much, much faster
pythontech 0:5868e8752d44 1400 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_power)) {
pythontech 0:5868e8752d44 1401 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1402 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
pythontech 0:5868e8752d44 1403 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
pythontech 0:5868e8752d44 1404 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)
pythontech 0:5868e8752d44 1405 && MP_PARSE_NODE_IS_NULL(pns_it->nodes[2])) {
pythontech 0:5868e8752d44 1406 mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
pythontech 0:5868e8752d44 1407 mp_parse_node_t *args;
pythontech 0:5868e8752d44 1408 int n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args);
pythontech 0:5868e8752d44 1409 mp_parse_node_t pn_range_start;
pythontech 0:5868e8752d44 1410 mp_parse_node_t pn_range_end;
pythontech 0:5868e8752d44 1411 mp_parse_node_t pn_range_step;
pythontech 0:5868e8752d44 1412 bool optimize = false;
pythontech 0:5868e8752d44 1413 if (1 <= n_args && n_args <= 3) {
pythontech 0:5868e8752d44 1414 optimize = true;
pythontech 0:5868e8752d44 1415 if (n_args == 1) {
pythontech 0:5868e8752d44 1416 pn_range_start = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 0);
pythontech 0:5868e8752d44 1417 pn_range_end = args[0];
pythontech 0:5868e8752d44 1418 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
pythontech 0:5868e8752d44 1419 } else if (n_args == 2) {
pythontech 0:5868e8752d44 1420 pn_range_start = args[0];
pythontech 0:5868e8752d44 1421 pn_range_end = args[1];
pythontech 0:5868e8752d44 1422 pn_range_step = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, 1);
pythontech 0:5868e8752d44 1423 } else {
pythontech 0:5868e8752d44 1424 pn_range_start = args[0];
pythontech 0:5868e8752d44 1425 pn_range_end = args[1];
pythontech 0:5868e8752d44 1426 pn_range_step = args[2];
pythontech 0:5868e8752d44 1427 // We need to know sign of step. This is possible only if it's constant
pythontech 0:5868e8752d44 1428 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
pythontech 0:5868e8752d44 1429 optimize = false;
pythontech 0:5868e8752d44 1430 }
pythontech 0:5868e8752d44 1431 }
pythontech 0:5868e8752d44 1432 // arguments must be able to be compiled as standard expressions
pythontech 0:5868e8752d44 1433 if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_start)) {
pythontech 0:5868e8752d44 1434 int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_range_start);
pythontech 0:5868e8752d44 1435 if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {
pythontech 0:5868e8752d44 1436 optimize = false;
pythontech 0:5868e8752d44 1437 }
pythontech 0:5868e8752d44 1438 }
pythontech 0:5868e8752d44 1439 if (optimize && MP_PARSE_NODE_IS_STRUCT(pn_range_end)) {
pythontech 0:5868e8752d44 1440 int k = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_range_end);
pythontech 0:5868e8752d44 1441 if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument) {
pythontech 0:5868e8752d44 1442 optimize = false;
pythontech 0:5868e8752d44 1443 }
pythontech 0:5868e8752d44 1444 }
pythontech 0:5868e8752d44 1445 }
pythontech 0:5868e8752d44 1446 if (optimize) {
pythontech 0:5868e8752d44 1447 compile_for_stmt_optimised_range(comp, pns->nodes[0], pn_range_start, pn_range_end, pn_range_step, pns->nodes[2], pns->nodes[3]);
pythontech 0:5868e8752d44 1448 return;
pythontech 0:5868e8752d44 1449 }
pythontech 0:5868e8752d44 1450 }
pythontech 0:5868e8752d44 1451 }
pythontech 0:5868e8752d44 1452
pythontech 0:5868e8752d44 1453 START_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1454 comp->break_label |= MP_EMIT_BREAK_FROM_FOR;
pythontech 0:5868e8752d44 1455
pythontech 0:5868e8752d44 1456 uint pop_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1457
pythontech 0:5868e8752d44 1458 compile_node(comp, pns->nodes[1]); // iterator
pythontech 0:5868e8752d44 1459 EMIT(get_iter);
pythontech 0:5868e8752d44 1460 EMIT_ARG(label_assign, continue_label);
pythontech 0:5868e8752d44 1461 EMIT_ARG(for_iter, pop_label);
pythontech 0:5868e8752d44 1462 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
pythontech 0:5868e8752d44 1463 compile_node(comp, pns->nodes[2]); // body
pythontech 0:5868e8752d44 1464 if (!EMIT(last_emit_was_return_value)) {
pythontech 0:5868e8752d44 1465 EMIT_ARG(jump, continue_label);
pythontech 0:5868e8752d44 1466 }
pythontech 0:5868e8752d44 1467 EMIT_ARG(label_assign, pop_label);
pythontech 0:5868e8752d44 1468 EMIT(for_iter_end);
pythontech 0:5868e8752d44 1469
pythontech 0:5868e8752d44 1470 // break/continue apply to outer loop (if any) in the else block
pythontech 0:5868e8752d44 1471 END_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1472
pythontech 0:5868e8752d44 1473 compile_node(comp, pns->nodes[3]); // else (not tested)
pythontech 0:5868e8752d44 1474
pythontech 0:5868e8752d44 1475 EMIT_ARG(label_assign, break_label);
pythontech 0:5868e8752d44 1476 }
pythontech 0:5868e8752d44 1477
pythontech 0:5868e8752d44 1478 STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) {
pythontech 0:5868e8752d44 1479 // setup code
pythontech 0:5868e8752d44 1480 uint l1 = comp_next_label(comp);
pythontech 0:5868e8752d44 1481 uint success_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1482
pythontech 0:5868e8752d44 1483 EMIT_ARG(setup_except, l1);
pythontech 0:5868e8752d44 1484 compile_increase_except_level(comp);
pythontech 0:5868e8752d44 1485
pythontech 0:5868e8752d44 1486 compile_node(comp, pn_body); // body
pythontech 0:5868e8752d44 1487 EMIT(pop_block);
pythontech 0:5868e8752d44 1488 EMIT_ARG(jump, success_label); // jump over exception handler
pythontech 0:5868e8752d44 1489
pythontech 0:5868e8752d44 1490 EMIT_ARG(label_assign, l1); // start of exception handler
pythontech 0:5868e8752d44 1491 EMIT(start_except_handler);
pythontech 0:5868e8752d44 1492
pythontech 0:5868e8752d44 1493 uint l2 = comp_next_label(comp);
pythontech 0:5868e8752d44 1494
pythontech 0:5868e8752d44 1495 for (int i = 0; i < n_except; i++) {
pythontech 0:5868e8752d44 1496 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_excepts[i], PN_try_stmt_except)); // should be
pythontech 0:5868e8752d44 1497 mp_parse_node_struct_t *pns_except = (mp_parse_node_struct_t*)pn_excepts[i];
pythontech 0:5868e8752d44 1498
pythontech 0:5868e8752d44 1499 qstr qstr_exception_local = 0;
pythontech 0:5868e8752d44 1500 uint end_finally_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1501
pythontech 0:5868e8752d44 1502 if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
pythontech 0:5868e8752d44 1503 // this is a catch all exception handler
pythontech 0:5868e8752d44 1504 if (i + 1 != n_except) {
pythontech 0:5868e8752d44 1505 compile_syntax_error(comp, pn_excepts[i], "default 'except:' must be last");
pythontech 0:5868e8752d44 1506 compile_decrease_except_level(comp);
pythontech 0:5868e8752d44 1507 return;
pythontech 0:5868e8752d44 1508 }
pythontech 0:5868e8752d44 1509 } else {
pythontech 0:5868e8752d44 1510 // this exception handler requires a match to a certain type of exception
pythontech 0:5868e8752d44 1511 mp_parse_node_t pns_exception_expr = pns_except->nodes[0];
pythontech 0:5868e8752d44 1512 if (MP_PARSE_NODE_IS_STRUCT(pns_exception_expr)) {
pythontech 0:5868e8752d44 1513 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns_exception_expr;
pythontech 0:5868e8752d44 1514 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_try_stmt_as_name) {
pythontech 0:5868e8752d44 1515 // handler binds the exception to a local
pythontech 0:5868e8752d44 1516 pns_exception_expr = pns3->nodes[0];
pythontech 0:5868e8752d44 1517 qstr_exception_local = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]);
pythontech 0:5868e8752d44 1518 }
pythontech 0:5868e8752d44 1519 }
pythontech 0:5868e8752d44 1520 EMIT(dup_top);
pythontech 0:5868e8752d44 1521 compile_node(comp, pns_exception_expr);
pythontech 0:5868e8752d44 1522 EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
pythontech 0:5868e8752d44 1523 EMIT_ARG(pop_jump_if, false, end_finally_label);
pythontech 0:5868e8752d44 1524 }
pythontech 0:5868e8752d44 1525
pythontech 0:5868e8752d44 1526 EMIT(pop_top);
pythontech 0:5868e8752d44 1527
pythontech 0:5868e8752d44 1528 if (qstr_exception_local == 0) {
pythontech 0:5868e8752d44 1529 EMIT(pop_top);
pythontech 0:5868e8752d44 1530 } else {
pythontech 0:5868e8752d44 1531 compile_store_id(comp, qstr_exception_local);
pythontech 0:5868e8752d44 1532 }
pythontech 0:5868e8752d44 1533
pythontech 0:5868e8752d44 1534 EMIT(pop_top);
pythontech 0:5868e8752d44 1535
pythontech 0:5868e8752d44 1536 uint l3 = 0;
pythontech 0:5868e8752d44 1537 if (qstr_exception_local != 0) {
pythontech 0:5868e8752d44 1538 l3 = comp_next_label(comp);
pythontech 0:5868e8752d44 1539 EMIT_ARG(setup_finally, l3);
pythontech 0:5868e8752d44 1540 compile_increase_except_level(comp);
pythontech 0:5868e8752d44 1541 }
pythontech 0:5868e8752d44 1542 compile_node(comp, pns_except->nodes[1]);
pythontech 0:5868e8752d44 1543 if (qstr_exception_local != 0) {
pythontech 0:5868e8752d44 1544 EMIT(pop_block);
pythontech 0:5868e8752d44 1545 }
pythontech 0:5868e8752d44 1546 EMIT(pop_except);
pythontech 0:5868e8752d44 1547 if (qstr_exception_local != 0) {
pythontech 0:5868e8752d44 1548 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 1549 EMIT_ARG(label_assign, l3);
pythontech 0:5868e8752d44 1550 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 1551 compile_store_id(comp, qstr_exception_local);
pythontech 0:5868e8752d44 1552 compile_delete_id(comp, qstr_exception_local);
pythontech 0:5868e8752d44 1553
pythontech 0:5868e8752d44 1554 compile_decrease_except_level(comp);
pythontech 0:5868e8752d44 1555 EMIT(end_finally);
pythontech 0:5868e8752d44 1556 }
pythontech 0:5868e8752d44 1557 EMIT_ARG(jump, l2);
pythontech 0:5868e8752d44 1558 EMIT_ARG(label_assign, end_finally_label);
pythontech 0:5868e8752d44 1559 EMIT_ARG(adjust_stack_size, 3); // stack adjust for the 3 exception items
pythontech 0:5868e8752d44 1560 }
pythontech 0:5868e8752d44 1561
pythontech 0:5868e8752d44 1562 compile_decrease_except_level(comp);
pythontech 0:5868e8752d44 1563 EMIT(end_finally);
pythontech 0:5868e8752d44 1564 EMIT(end_except_handler);
pythontech 0:5868e8752d44 1565
pythontech 0:5868e8752d44 1566 EMIT_ARG(label_assign, success_label);
pythontech 0:5868e8752d44 1567 compile_node(comp, pn_else); // else block, can be null
pythontech 0:5868e8752d44 1568 EMIT_ARG(label_assign, l2);
pythontech 0:5868e8752d44 1569 }
pythontech 0:5868e8752d44 1570
pythontech 0:5868e8752d44 1571 STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) {
pythontech 0:5868e8752d44 1572 uint l_finally_block = comp_next_label(comp);
pythontech 0:5868e8752d44 1573
pythontech 0:5868e8752d44 1574 EMIT_ARG(setup_finally, l_finally_block);
pythontech 0:5868e8752d44 1575 compile_increase_except_level(comp);
pythontech 0:5868e8752d44 1576
pythontech 0:5868e8752d44 1577 if (n_except == 0) {
pythontech 0:5868e8752d44 1578 assert(MP_PARSE_NODE_IS_NULL(pn_else));
pythontech 0:5868e8752d44 1579 EMIT_ARG(adjust_stack_size, 3); // stack adjust for possible UNWIND_JUMP state
pythontech 0:5868e8752d44 1580 compile_node(comp, pn_body);
pythontech 0:5868e8752d44 1581 EMIT_ARG(adjust_stack_size, -3);
pythontech 0:5868e8752d44 1582 } else {
pythontech 0:5868e8752d44 1583 compile_try_except(comp, pn_body, n_except, pn_except, pn_else);
pythontech 0:5868e8752d44 1584 }
pythontech 0:5868e8752d44 1585 EMIT(pop_block);
pythontech 0:5868e8752d44 1586 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 1587 EMIT_ARG(label_assign, l_finally_block);
pythontech 0:5868e8752d44 1588 compile_node(comp, pn_finally);
pythontech 0:5868e8752d44 1589
pythontech 0:5868e8752d44 1590 compile_decrease_except_level(comp);
pythontech 0:5868e8752d44 1591 EMIT(end_finally);
pythontech 0:5868e8752d44 1592 }
pythontech 0:5868e8752d44 1593
pythontech 0:5868e8752d44 1594 STATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1595 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should be
pythontech 0:5868e8752d44 1596 {
pythontech 0:5868e8752d44 1597 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1598 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_finally) {
pythontech 0:5868e8752d44 1599 // just try-finally
pythontech 0:5868e8752d44 1600 compile_try_finally(comp, pns->nodes[0], 0, NULL, MP_PARSE_NODE_NULL, pns2->nodes[0]);
pythontech 0:5868e8752d44 1601 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_try_stmt_except_and_more) {
pythontech 0:5868e8752d44 1602 // try-except and possibly else and/or finally
pythontech 0:5868e8752d44 1603 mp_parse_node_t *pn_excepts;
pythontech 0:5868e8752d44 1604 int n_except = mp_parse_node_extract_list(&pns2->nodes[0], PN_try_stmt_except_list, &pn_excepts);
pythontech 0:5868e8752d44 1605 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[2])) {
pythontech 0:5868e8752d44 1606 // no finally
pythontech 0:5868e8752d44 1607 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1]);
pythontech 0:5868e8752d44 1608 } else {
pythontech 0:5868e8752d44 1609 // have finally
pythontech 0:5868e8752d44 1610 compile_try_finally(comp, pns->nodes[0], n_except, pn_excepts, pns2->nodes[1], ((mp_parse_node_struct_t*)pns2->nodes[2])->nodes[0]);
pythontech 0:5868e8752d44 1611 }
pythontech 0:5868e8752d44 1612 } else {
pythontech 0:5868e8752d44 1613 // just try-except
pythontech 0:5868e8752d44 1614 mp_parse_node_t *pn_excepts;
pythontech 0:5868e8752d44 1615 int n_except = mp_parse_node_extract_list(&pns->nodes[1], PN_try_stmt_except_list, &pn_excepts);
pythontech 0:5868e8752d44 1616 compile_try_except(comp, pns->nodes[0], n_except, pn_excepts, MP_PARSE_NODE_NULL);
pythontech 0:5868e8752d44 1617 }
pythontech 0:5868e8752d44 1618 }
pythontech 0:5868e8752d44 1619 }
pythontech 0:5868e8752d44 1620
pythontech 0:5868e8752d44 1621 STATIC void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) {
pythontech 0:5868e8752d44 1622 if (n == 0) {
pythontech 0:5868e8752d44 1623 // no more pre-bits, compile the body of the with
pythontech 0:5868e8752d44 1624 compile_node(comp, body);
pythontech 0:5868e8752d44 1625 } else {
pythontech 0:5868e8752d44 1626 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1627 if (MICROPY_EMIT_NATIVE && comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) {
pythontech 0:5868e8752d44 1628 // we need to allocate an extra label for the native emitter
pythontech 0:5868e8752d44 1629 // it will use l_end+1 as an auxiliary label
pythontech 0:5868e8752d44 1630 comp_next_label(comp);
pythontech 0:5868e8752d44 1631 }
pythontech 0:5868e8752d44 1632 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
pythontech 0:5868e8752d44 1633 // this pre-bit is of the form "a as b"
pythontech 0:5868e8752d44 1634 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
pythontech 0:5868e8752d44 1635 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1636 EMIT_ARG(setup_with, l_end);
pythontech 0:5868e8752d44 1637 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
pythontech 0:5868e8752d44 1638 } else {
pythontech 0:5868e8752d44 1639 // this pre-bit is just an expression
pythontech 0:5868e8752d44 1640 compile_node(comp, nodes[0]);
pythontech 0:5868e8752d44 1641 EMIT_ARG(setup_with, l_end);
pythontech 0:5868e8752d44 1642 EMIT(pop_top);
pythontech 0:5868e8752d44 1643 }
pythontech 0:5868e8752d44 1644 compile_increase_except_level(comp);
pythontech 0:5868e8752d44 1645 // compile additional pre-bits and the body
pythontech 0:5868e8752d44 1646 compile_with_stmt_helper(comp, n - 1, nodes + 1, body);
pythontech 0:5868e8752d44 1647 // finish this with block
pythontech 0:5868e8752d44 1648 EMIT_ARG(with_cleanup, l_end);
pythontech 0:5868e8752d44 1649 compile_decrease_except_level(comp);
pythontech 0:5868e8752d44 1650 EMIT(end_finally);
pythontech 0:5868e8752d44 1651 }
pythontech 0:5868e8752d44 1652 }
pythontech 0:5868e8752d44 1653
pythontech 0:5868e8752d44 1654 STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1655 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
pythontech 0:5868e8752d44 1656 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 1657 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);
pythontech 0:5868e8752d44 1658 assert(n > 0);
pythontech 0:5868e8752d44 1659
pythontech 0:5868e8752d44 1660 // compile in a nested fashion
pythontech 0:5868e8752d44 1661 compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
pythontech 0:5868e8752d44 1662 }
pythontech 0:5868e8752d44 1663
pythontech 0:5868e8752d44 1664 STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1665 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
pythontech 0:5868e8752d44 1666 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
pythontech 0:5868e8752d44 1667 // for REPL, evaluate then print the expression
pythontech 0:5868e8752d44 1668 compile_load_id(comp, MP_QSTR___repl_print__);
pythontech 0:5868e8752d44 1669 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1670 EMIT_ARG(call_function, 1, 0, 0);
pythontech 0:5868e8752d44 1671 EMIT(pop_top);
pythontech 0:5868e8752d44 1672
pythontech 0:5868e8752d44 1673 } else {
pythontech 0:5868e8752d44 1674 // for non-REPL, evaluate then discard the expression
pythontech 0:5868e8752d44 1675 if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
pythontech 0:5868e8752d44 1676 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)
pythontech 0:5868e8752d44 1677 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_bytes)
pythontech 0:5868e8752d44 1678 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
pythontech 0:5868e8752d44 1679 // do nothing with a lonely constant
pythontech 0:5868e8752d44 1680 } else {
pythontech 0:5868e8752d44 1681 compile_node(comp, pns->nodes[0]); // just an expression
pythontech 0:5868e8752d44 1682 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
pythontech 0:5868e8752d44 1683 }
pythontech 0:5868e8752d44 1684 }
pythontech 0:5868e8752d44 1685 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 1686 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1687 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
pythontech 0:5868e8752d44 1688 if (kind == PN_expr_stmt_augassign) {
pythontech 0:5868e8752d44 1689 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
pythontech 0:5868e8752d44 1690 compile_node(comp, pns1->nodes[1]); // rhs
pythontech 0:5868e8752d44 1691 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
pythontech 0:5868e8752d44 1692 mp_binary_op_t op;
pythontech 0:5868e8752d44 1693 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
pythontech 0:5868e8752d44 1694 case MP_TOKEN_DEL_PIPE_EQUAL: op = MP_BINARY_OP_INPLACE_OR; break;
pythontech 0:5868e8752d44 1695 case MP_TOKEN_DEL_CARET_EQUAL: op = MP_BINARY_OP_INPLACE_XOR; break;
pythontech 0:5868e8752d44 1696 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = MP_BINARY_OP_INPLACE_AND; break;
pythontech 0:5868e8752d44 1697 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = MP_BINARY_OP_INPLACE_LSHIFT; break;
pythontech 0:5868e8752d44 1698 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = MP_BINARY_OP_INPLACE_RSHIFT; break;
pythontech 0:5868e8752d44 1699 case MP_TOKEN_DEL_PLUS_EQUAL: op = MP_BINARY_OP_INPLACE_ADD; break;
pythontech 0:5868e8752d44 1700 case MP_TOKEN_DEL_MINUS_EQUAL: op = MP_BINARY_OP_INPLACE_SUBTRACT; break;
pythontech 0:5868e8752d44 1701 case MP_TOKEN_DEL_STAR_EQUAL: op = MP_BINARY_OP_INPLACE_MULTIPLY; break;
pythontech 0:5868e8752d44 1702 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
pythontech 0:5868e8752d44 1703 case MP_TOKEN_DEL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
pythontech 0:5868e8752d44 1704 case MP_TOKEN_DEL_PERCENT_EQUAL: op = MP_BINARY_OP_INPLACE_MODULO; break;
pythontech 0:5868e8752d44 1705 case MP_TOKEN_DEL_DBL_STAR_EQUAL: default: op = MP_BINARY_OP_INPLACE_POWER; break;
pythontech 0:5868e8752d44 1706 }
pythontech 0:5868e8752d44 1707 EMIT_ARG(binary_op, op);
pythontech 0:5868e8752d44 1708 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
pythontech 0:5868e8752d44 1709 } else if (kind == PN_expr_stmt_assign_list) {
pythontech 0:5868e8752d44 1710 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
pythontech 0:5868e8752d44 1711 compile_node(comp, pns1->nodes[rhs]); // rhs
pythontech 0:5868e8752d44 1712 // following CPython, we store left-most first
pythontech 0:5868e8752d44 1713 if (rhs > 0) {
pythontech 0:5868e8752d44 1714 EMIT(dup_top);
pythontech 0:5868e8752d44 1715 }
pythontech 0:5868e8752d44 1716 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1717 for (int i = 0; i < rhs; i++) {
pythontech 0:5868e8752d44 1718 if (i + 1 < rhs) {
pythontech 0:5868e8752d44 1719 EMIT(dup_top);
pythontech 0:5868e8752d44 1720 }
pythontech 0:5868e8752d44 1721 c_assign(comp, pns1->nodes[i], ASSIGN_STORE); // middle store
pythontech 0:5868e8752d44 1722 }
pythontech 0:5868e8752d44 1723 } else {
pythontech 0:5868e8752d44 1724 plain_assign:
pythontech 0:5868e8752d44 1725 if (MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
pythontech 0:5868e8752d44 1726 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
pythontech 0:5868e8752d44 1727 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
pythontech 0:5868e8752d44 1728 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 2
pythontech 0:5868e8752d44 1729 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
pythontech 0:5868e8752d44 1730 // optimisation for a, b = c, d
pythontech 0:5868e8752d44 1731 mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1732 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 1733 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
pythontech 0:5868e8752d44 1734 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) {
pythontech 0:5868e8752d44 1735 // can't optimise when it's a star expression on the lhs
pythontech 0:5868e8752d44 1736 goto no_optimisation;
pythontech 0:5868e8752d44 1737 }
pythontech 0:5868e8752d44 1738 compile_node(comp, pns10->nodes[0]); // rhs
pythontech 0:5868e8752d44 1739 compile_node(comp, pns10->nodes[1]); // rhs
pythontech 0:5868e8752d44 1740 EMIT(rot_two);
pythontech 0:5868e8752d44 1741 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1742 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1743 } else if (MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
pythontech 0:5868e8752d44 1744 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
pythontech 0:5868e8752d44 1745 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
pythontech 0:5868e8752d44 1746 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 3
pythontech 0:5868e8752d44 1747 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
pythontech 0:5868e8752d44 1748 // optimisation for a, b, c = d, e, f
pythontech 0:5868e8752d44 1749 mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1750 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 1751 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
pythontech 0:5868e8752d44 1752 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)
pythontech 0:5868e8752d44 1753 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) {
pythontech 0:5868e8752d44 1754 // can't optimise when it's a star expression on the lhs
pythontech 0:5868e8752d44 1755 goto no_optimisation;
pythontech 0:5868e8752d44 1756 }
pythontech 0:5868e8752d44 1757 compile_node(comp, pns10->nodes[0]); // rhs
pythontech 0:5868e8752d44 1758 compile_node(comp, pns10->nodes[1]); // rhs
pythontech 0:5868e8752d44 1759 compile_node(comp, pns10->nodes[2]); // rhs
pythontech 0:5868e8752d44 1760 EMIT(rot_three);
pythontech 0:5868e8752d44 1761 EMIT(rot_two);
pythontech 0:5868e8752d44 1762 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1763 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1764 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1765 } else {
pythontech 0:5868e8752d44 1766 no_optimisation:
pythontech 0:5868e8752d44 1767 compile_node(comp, pns->nodes[1]); // rhs
pythontech 0:5868e8752d44 1768 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1769 }
pythontech 0:5868e8752d44 1770 }
pythontech 0:5868e8752d44 1771 } else {
pythontech 0:5868e8752d44 1772 goto plain_assign;
pythontech 0:5868e8752d44 1773 }
pythontech 0:5868e8752d44 1774 }
pythontech 0:5868e8752d44 1775
pythontech 0:5868e8752d44 1776 STATIC void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, mp_binary_op_t binary_op) {
pythontech 0:5868e8752d44 1777 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1778 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1779 for (int i = 1; i < num_nodes; i += 1) {
pythontech 0:5868e8752d44 1780 compile_node(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 1781 EMIT_ARG(binary_op, binary_op);
pythontech 0:5868e8752d44 1782 }
pythontech 0:5868e8752d44 1783 }
pythontech 0:5868e8752d44 1784
pythontech 0:5868e8752d44 1785 STATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1786 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
pythontech 0:5868e8752d44 1787 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1788
pythontech 0:5868e8752d44 1789 uint l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 1790 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1791 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
pythontech 0:5868e8752d44 1792 compile_node(comp, pns->nodes[0]); // success value
pythontech 0:5868e8752d44 1793 EMIT_ARG(jump, l_end);
pythontech 0:5868e8752d44 1794 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 1795 EMIT_ARG(adjust_stack_size, -1); // adjust stack size
pythontech 0:5868e8752d44 1796 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
pythontech 0:5868e8752d44 1797 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1798 }
pythontech 0:5868e8752d44 1799
pythontech 0:5868e8752d44 1800 STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1801 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 1802 // create a new scope for this lambda
pythontech 0:5868e8752d44 1803 scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
pythontech 0:5868e8752d44 1804 // store the lambda scope so the compiling function (this one) can use it at each pass
pythontech 0:5868e8752d44 1805 pns->nodes[2] = (mp_parse_node_t)s;
pythontech 0:5868e8752d44 1806 }
pythontech 0:5868e8752d44 1807
pythontech 0:5868e8752d44 1808 // get the scope for this lambda
pythontech 0:5868e8752d44 1809 scope_t *this_scope = (scope_t*)pns->nodes[2];
pythontech 0:5868e8752d44 1810
pythontech 0:5868e8752d44 1811 // compile the lambda definition
pythontech 0:5868e8752d44 1812 compile_funcdef_lambdef(comp, this_scope, pns->nodes[0], PN_varargslist);
pythontech 0:5868e8752d44 1813 }
pythontech 0:5868e8752d44 1814
pythontech 0:5868e8752d44 1815 STATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns, bool cond) {
pythontech 0:5868e8752d44 1816 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1817 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1818 for (int i = 0; i < n; i += 1) {
pythontech 0:5868e8752d44 1819 compile_node(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 1820 if (i + 1 < n) {
pythontech 0:5868e8752d44 1821 EMIT_ARG(jump_if_or_pop, cond, l_end);
pythontech 0:5868e8752d44 1822 }
pythontech 0:5868e8752d44 1823 }
pythontech 0:5868e8752d44 1824 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1825 }
pythontech 0:5868e8752d44 1826
pythontech 0:5868e8752d44 1827 STATIC void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1828 compile_or_and_test(comp, pns, true);
pythontech 0:5868e8752d44 1829 }
pythontech 0:5868e8752d44 1830
pythontech 0:5868e8752d44 1831 STATIC void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1832 compile_or_and_test(comp, pns, false);
pythontech 0:5868e8752d44 1833 }
pythontech 0:5868e8752d44 1834
pythontech 0:5868e8752d44 1835 STATIC void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1836 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1837 EMIT_ARG(unary_op, MP_UNARY_OP_NOT);
pythontech 0:5868e8752d44 1838 }
pythontech 0:5868e8752d44 1839
pythontech 0:5868e8752d44 1840 STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1841 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1842 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1843 bool multi = (num_nodes > 3);
pythontech 0:5868e8752d44 1844 uint l_fail = 0;
pythontech 0:5868e8752d44 1845 if (multi) {
pythontech 0:5868e8752d44 1846 l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 1847 }
pythontech 0:5868e8752d44 1848 for (int i = 1; i + 1 < num_nodes; i += 2) {
pythontech 0:5868e8752d44 1849 compile_node(comp, pns->nodes[i + 1]);
pythontech 0:5868e8752d44 1850 if (i + 2 < num_nodes) {
pythontech 0:5868e8752d44 1851 EMIT(dup_top);
pythontech 0:5868e8752d44 1852 EMIT(rot_three);
pythontech 0:5868e8752d44 1853 }
pythontech 0:5868e8752d44 1854 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
pythontech 0:5868e8752d44 1855 mp_binary_op_t op;
pythontech 0:5868e8752d44 1856 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
pythontech 0:5868e8752d44 1857 case MP_TOKEN_OP_LESS: op = MP_BINARY_OP_LESS; break;
pythontech 0:5868e8752d44 1858 case MP_TOKEN_OP_MORE: op = MP_BINARY_OP_MORE; break;
pythontech 0:5868e8752d44 1859 case MP_TOKEN_OP_DBL_EQUAL: op = MP_BINARY_OP_EQUAL; break;
pythontech 0:5868e8752d44 1860 case MP_TOKEN_OP_LESS_EQUAL: op = MP_BINARY_OP_LESS_EQUAL; break;
pythontech 0:5868e8752d44 1861 case MP_TOKEN_OP_MORE_EQUAL: op = MP_BINARY_OP_MORE_EQUAL; break;
pythontech 0:5868e8752d44 1862 case MP_TOKEN_OP_NOT_EQUAL: op = MP_BINARY_OP_NOT_EQUAL; break;
pythontech 0:5868e8752d44 1863 case MP_TOKEN_KW_IN: default: op = MP_BINARY_OP_IN; break;
pythontech 0:5868e8752d44 1864 }
pythontech 0:5868e8752d44 1865 EMIT_ARG(binary_op, op);
pythontech 0:5868e8752d44 1866 } else {
pythontech 0:5868e8752d44 1867 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])); // should be
pythontech 0:5868e8752d44 1868 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
pythontech 0:5868e8752d44 1869 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
pythontech 0:5868e8752d44 1870 if (kind == PN_comp_op_not_in) {
pythontech 0:5868e8752d44 1871 EMIT_ARG(binary_op, MP_BINARY_OP_NOT_IN);
pythontech 0:5868e8752d44 1872 } else {
pythontech 0:5868e8752d44 1873 assert(kind == PN_comp_op_is); // should be
pythontech 0:5868e8752d44 1874 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
pythontech 0:5868e8752d44 1875 EMIT_ARG(binary_op, MP_BINARY_OP_IS);
pythontech 0:5868e8752d44 1876 } else {
pythontech 0:5868e8752d44 1877 EMIT_ARG(binary_op, MP_BINARY_OP_IS_NOT);
pythontech 0:5868e8752d44 1878 }
pythontech 0:5868e8752d44 1879 }
pythontech 0:5868e8752d44 1880 }
pythontech 0:5868e8752d44 1881 if (i + 2 < num_nodes) {
pythontech 0:5868e8752d44 1882 EMIT_ARG(jump_if_or_pop, false, l_fail);
pythontech 0:5868e8752d44 1883 }
pythontech 0:5868e8752d44 1884 }
pythontech 0:5868e8752d44 1885 if (multi) {
pythontech 0:5868e8752d44 1886 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1887 EMIT_ARG(jump, l_end);
pythontech 0:5868e8752d44 1888 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 1889 EMIT_ARG(adjust_stack_size, 1);
pythontech 0:5868e8752d44 1890 EMIT(rot_two);
pythontech 0:5868e8752d44 1891 EMIT(pop_top);
pythontech 0:5868e8752d44 1892 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1893 }
pythontech 0:5868e8752d44 1894 }
pythontech 0:5868e8752d44 1895
pythontech 0:5868e8752d44 1896 STATIC void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1897 compile_syntax_error(comp, (mp_parse_node_t)pns, "*x must be assignment target");
pythontech 0:5868e8752d44 1898 }
pythontech 0:5868e8752d44 1899
pythontech 0:5868e8752d44 1900 STATIC void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1901 c_binary_op(comp, pns, MP_BINARY_OP_OR);
pythontech 0:5868e8752d44 1902 }
pythontech 0:5868e8752d44 1903
pythontech 0:5868e8752d44 1904 STATIC void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1905 c_binary_op(comp, pns, MP_BINARY_OP_XOR);
pythontech 0:5868e8752d44 1906 }
pythontech 0:5868e8752d44 1907
pythontech 0:5868e8752d44 1908 STATIC void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1909 c_binary_op(comp, pns, MP_BINARY_OP_AND);
pythontech 0:5868e8752d44 1910 }
pythontech 0:5868e8752d44 1911
pythontech 0:5868e8752d44 1912 STATIC void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1913 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1914 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1915 for (int i = 1; i + 1 < num_nodes; i += 2) {
pythontech 0:5868e8752d44 1916 compile_node(comp, pns->nodes[i + 1]);
pythontech 0:5868e8752d44 1917 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
pythontech 0:5868e8752d44 1918 EMIT_ARG(binary_op, MP_BINARY_OP_LSHIFT);
pythontech 0:5868e8752d44 1919 } else {
pythontech 0:5868e8752d44 1920 assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)); // should be
pythontech 0:5868e8752d44 1921 EMIT_ARG(binary_op, MP_BINARY_OP_RSHIFT);
pythontech 0:5868e8752d44 1922 }
pythontech 0:5868e8752d44 1923 }
pythontech 0:5868e8752d44 1924 }
pythontech 0:5868e8752d44 1925
pythontech 0:5868e8752d44 1926 STATIC void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1927 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1928 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1929 for (int i = 1; i + 1 < num_nodes; i += 2) {
pythontech 0:5868e8752d44 1930 compile_node(comp, pns->nodes[i + 1]);
pythontech 0:5868e8752d44 1931 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
pythontech 0:5868e8752d44 1932 EMIT_ARG(binary_op, MP_BINARY_OP_ADD);
pythontech 0:5868e8752d44 1933 } else {
pythontech 0:5868e8752d44 1934 assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)); // should be
pythontech 0:5868e8752d44 1935 EMIT_ARG(binary_op, MP_BINARY_OP_SUBTRACT);
pythontech 0:5868e8752d44 1936 }
pythontech 0:5868e8752d44 1937 }
pythontech 0:5868e8752d44 1938 }
pythontech 0:5868e8752d44 1939
pythontech 0:5868e8752d44 1940 STATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1941 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1942 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1943 for (int i = 1; i + 1 < num_nodes; i += 2) {
pythontech 0:5868e8752d44 1944 compile_node(comp, pns->nodes[i + 1]);
pythontech 0:5868e8752d44 1945 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
pythontech 0:5868e8752d44 1946 EMIT_ARG(binary_op, MP_BINARY_OP_MULTIPLY);
pythontech 0:5868e8752d44 1947 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
pythontech 0:5868e8752d44 1948 EMIT_ARG(binary_op, MP_BINARY_OP_FLOOR_DIVIDE);
pythontech 0:5868e8752d44 1949 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
pythontech 0:5868e8752d44 1950 EMIT_ARG(binary_op, MP_BINARY_OP_TRUE_DIVIDE);
pythontech 0:5868e8752d44 1951 } else {
pythontech 0:5868e8752d44 1952 assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)); // should be
pythontech 0:5868e8752d44 1953 EMIT_ARG(binary_op, MP_BINARY_OP_MODULO);
pythontech 0:5868e8752d44 1954 }
pythontech 0:5868e8752d44 1955 }
pythontech 0:5868e8752d44 1956 }
pythontech 0:5868e8752d44 1957
pythontech 0:5868e8752d44 1958 STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1959 compile_node(comp, pns->nodes[1]);
pythontech 0:5868e8752d44 1960 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
pythontech 0:5868e8752d44 1961 EMIT_ARG(unary_op, MP_UNARY_OP_POSITIVE);
pythontech 0:5868e8752d44 1962 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
pythontech 0:5868e8752d44 1963 EMIT_ARG(unary_op, MP_UNARY_OP_NEGATIVE);
pythontech 0:5868e8752d44 1964 } else {
pythontech 0:5868e8752d44 1965 assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)); // should be
pythontech 0:5868e8752d44 1966 EMIT_ARG(unary_op, MP_UNARY_OP_INVERT);
pythontech 0:5868e8752d44 1967 }
pythontech 0:5868e8752d44 1968 }
pythontech 0:5868e8752d44 1969
pythontech 0:5868e8752d44 1970 STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1971 // this is to handle special super() call
pythontech 0:5868e8752d44 1972 comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
pythontech 0:5868e8752d44 1973
pythontech 0:5868e8752d44 1974 compile_generic_all_nodes(comp, pns);
pythontech 0:5868e8752d44 1975
pythontech 0:5868e8752d44 1976 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
pythontech 0:5868e8752d44 1977 EMIT_ARG(binary_op, MP_BINARY_OP_POWER);
pythontech 0:5868e8752d44 1978 }
pythontech 0:5868e8752d44 1979 }
pythontech 0:5868e8752d44 1980
pythontech 0:5868e8752d44 1981 STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) {
pythontech 0:5868e8752d44 1982 // function to call is on top of stack
pythontech 0:5868e8752d44 1983
pythontech 0:5868e8752d44 1984 // this is to handle special super() call
pythontech 0:5868e8752d44 1985 if (MP_PARSE_NODE_IS_NULL(pn_arglist) && comp->func_arg_is_super && comp->scope_cur->kind == SCOPE_FUNCTION) {
pythontech 0:5868e8752d44 1986 compile_load_id(comp, MP_QSTR___class__);
pythontech 0:5868e8752d44 1987 // look for first argument to function (assumes it's "self")
pythontech 0:5868e8752d44 1988 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
pythontech 0:5868e8752d44 1989 if (comp->scope_cur->id_info[i].flags & ID_FLAG_IS_PARAM) {
pythontech 0:5868e8752d44 1990 // first argument found; load it and call super
pythontech 0:5868e8752d44 1991 EMIT_LOAD_FAST(MP_QSTR_, comp->scope_cur->id_info[i].local_num);
pythontech 0:5868e8752d44 1992 EMIT_ARG(call_function, 2, 0, 0);
pythontech 0:5868e8752d44 1993 return;
pythontech 0:5868e8752d44 1994 }
pythontech 0:5868e8752d44 1995 }
pythontech 0:5868e8752d44 1996 compile_syntax_error(comp, MP_PARSE_NODE_NULL, "super() call cannot find self"); // really a TypeError
pythontech 0:5868e8752d44 1997 return;
pythontech 0:5868e8752d44 1998 }
pythontech 0:5868e8752d44 1999
pythontech 0:5868e8752d44 2000 // get the list of arguments
pythontech 0:5868e8752d44 2001 mp_parse_node_t *args;
pythontech 0:5868e8752d44 2002 int n_args = mp_parse_node_extract_list(&pn_arglist, PN_arglist, &args);
pythontech 0:5868e8752d44 2003
pythontech 0:5868e8752d44 2004 // compile the arguments
pythontech 0:5868e8752d44 2005 // Rather than calling compile_node on the list, we go through the list of args
pythontech 0:5868e8752d44 2006 // explicitly here so that we can count the number of arguments and give sensible
pythontech 0:5868e8752d44 2007 // error messages.
pythontech 0:5868e8752d44 2008 int n_positional = n_positional_extra;
pythontech 0:5868e8752d44 2009 uint n_keyword = 0;
pythontech 0:5868e8752d44 2010 uint star_flags = 0;
pythontech 0:5868e8752d44 2011 mp_parse_node_struct_t *star_args_node = NULL, *dblstar_args_node = NULL;
pythontech 0:5868e8752d44 2012 for (int i = 0; i < n_args; i++) {
pythontech 0:5868e8752d44 2013 if (MP_PARSE_NODE_IS_STRUCT(args[i])) {
pythontech 0:5868e8752d44 2014 mp_parse_node_struct_t *pns_arg = (mp_parse_node_struct_t*)args[i];
pythontech 0:5868e8752d44 2015 if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_star) {
pythontech 0:5868e8752d44 2016 if (star_flags & MP_EMIT_STAR_FLAG_SINGLE) {
pythontech 0:5868e8752d44 2017 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple *x");
pythontech 0:5868e8752d44 2018 return;
pythontech 0:5868e8752d44 2019 }
pythontech 0:5868e8752d44 2020 star_flags |= MP_EMIT_STAR_FLAG_SINGLE;
pythontech 0:5868e8752d44 2021 star_args_node = pns_arg;
pythontech 0:5868e8752d44 2022 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_dbl_star) {
pythontech 0:5868e8752d44 2023 if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) {
pythontech 0:5868e8752d44 2024 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple **x");
pythontech 0:5868e8752d44 2025 return;
pythontech 0:5868e8752d44 2026 }
pythontech 0:5868e8752d44 2027 star_flags |= MP_EMIT_STAR_FLAG_DOUBLE;
pythontech 0:5868e8752d44 2028 dblstar_args_node = pns_arg;
pythontech 0:5868e8752d44 2029 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) {
pythontech 0:5868e8752d44 2030 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_comp_for)) {
pythontech 0:5868e8752d44 2031 if (!MP_PARSE_NODE_IS_ID(pns_arg->nodes[0])) {
pythontech 0:5868e8752d44 2032 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "LHS of keyword arg must be an id");
pythontech 0:5868e8752d44 2033 return;
pythontech 0:5868e8752d44 2034 }
pythontech 0:5868e8752d44 2035 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]));
pythontech 0:5868e8752d44 2036 compile_node(comp, pns_arg->nodes[1]);
pythontech 0:5868e8752d44 2037 n_keyword += 1;
pythontech 0:5868e8752d44 2038 } else {
pythontech 0:5868e8752d44 2039 compile_comprehension(comp, pns_arg, SCOPE_GEN_EXPR);
pythontech 0:5868e8752d44 2040 n_positional++;
pythontech 0:5868e8752d44 2041 }
pythontech 0:5868e8752d44 2042 } else {
pythontech 0:5868e8752d44 2043 goto normal_argument;
pythontech 0:5868e8752d44 2044 }
pythontech 0:5868e8752d44 2045 } else {
pythontech 0:5868e8752d44 2046 normal_argument:
pythontech 0:5868e8752d44 2047 if (n_keyword > 0) {
pythontech 0:5868e8752d44 2048 compile_syntax_error(comp, args[i], "non-keyword arg after keyword arg");
pythontech 0:5868e8752d44 2049 return;
pythontech 0:5868e8752d44 2050 }
pythontech 0:5868e8752d44 2051 compile_node(comp, args[i]);
pythontech 0:5868e8752d44 2052 n_positional++;
pythontech 0:5868e8752d44 2053 }
pythontech 0:5868e8752d44 2054 }
pythontech 0:5868e8752d44 2055
pythontech 0:5868e8752d44 2056 // compile the star/double-star arguments if we had them
pythontech 0:5868e8752d44 2057 // if we had one but not the other then we load "null" as a place holder
pythontech 0:5868e8752d44 2058 if (star_flags != 0) {
pythontech 0:5868e8752d44 2059 if (star_args_node == NULL) {
pythontech 0:5868e8752d44 2060 EMIT(load_null);
pythontech 0:5868e8752d44 2061 } else {
pythontech 0:5868e8752d44 2062 compile_node(comp, star_args_node->nodes[0]);
pythontech 0:5868e8752d44 2063 }
pythontech 0:5868e8752d44 2064 if (dblstar_args_node == NULL) {
pythontech 0:5868e8752d44 2065 EMIT(load_null);
pythontech 0:5868e8752d44 2066 } else {
pythontech 0:5868e8752d44 2067 compile_node(comp, dblstar_args_node->nodes[0]);
pythontech 0:5868e8752d44 2068 }
pythontech 0:5868e8752d44 2069 }
pythontech 0:5868e8752d44 2070
pythontech 0:5868e8752d44 2071 // emit the function/method call
pythontech 0:5868e8752d44 2072 if (is_method_call) {
pythontech 0:5868e8752d44 2073 EMIT_ARG(call_method, n_positional, n_keyword, star_flags);
pythontech 0:5868e8752d44 2074 } else {
pythontech 0:5868e8752d44 2075 EMIT_ARG(call_function, n_positional, n_keyword, star_flags);
pythontech 0:5868e8752d44 2076 }
pythontech 0:5868e8752d44 2077 }
pythontech 0:5868e8752d44 2078
pythontech 0:5868e8752d44 2079 STATIC void compile_power_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2080 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2081 for (int i = 0; i < num_nodes; i++) {
pythontech 0:5868e8752d44 2082 if (i + 1 < num_nodes && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i], PN_trailer_period) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i + 1], PN_trailer_paren)) {
pythontech 0:5868e8752d44 2083 // optimisation for method calls a.f(...), following PyPy
pythontech 0:5868e8752d44 2084 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
pythontech 0:5868e8752d44 2085 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
pythontech 0:5868e8752d44 2086 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
pythontech 0:5868e8752d44 2087 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
pythontech 0:5868e8752d44 2088 i += 1;
pythontech 0:5868e8752d44 2089 } else {
pythontech 0:5868e8752d44 2090 compile_node(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 2091 }
pythontech 0:5868e8752d44 2092 comp->func_arg_is_super = false;
pythontech 0:5868e8752d44 2093 }
pythontech 0:5868e8752d44 2094 }
pythontech 0:5868e8752d44 2095
pythontech 0:5868e8752d44 2096 STATIC void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2097 // a list of strings
pythontech 0:5868e8752d44 2098
pythontech 0:5868e8752d44 2099 // check type of list (string or bytes) and count total number of bytes
pythontech 0:5868e8752d44 2100 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2101 size_t n_bytes = 0;
pythontech 0:5868e8752d44 2102 int string_kind = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 2103 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 2104 int pn_kind;
pythontech 0:5868e8752d44 2105 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[i])) {
pythontech 0:5868e8752d44 2106 pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
pythontech 0:5868e8752d44 2107 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
pythontech 0:5868e8752d44 2108 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
pythontech 0:5868e8752d44 2109 } else {
pythontech 0:5868e8752d44 2110 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i]));
pythontech 0:5868e8752d44 2111 mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
pythontech 0:5868e8752d44 2112 if (MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_string) {
pythontech 0:5868e8752d44 2113 pn_kind = MP_PARSE_NODE_STRING;
pythontech 0:5868e8752d44 2114 } else {
pythontech 0:5868e8752d44 2115 assert(MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_bytes);
pythontech 0:5868e8752d44 2116 pn_kind = MP_PARSE_NODE_BYTES;
pythontech 0:5868e8752d44 2117 }
pythontech 0:5868e8752d44 2118 n_bytes += pns_string->nodes[1];
pythontech 0:5868e8752d44 2119 }
pythontech 0:5868e8752d44 2120 if (i == 0) {
pythontech 0:5868e8752d44 2121 string_kind = pn_kind;
pythontech 0:5868e8752d44 2122 } else if (pn_kind != string_kind) {
pythontech 0:5868e8752d44 2123 compile_syntax_error(comp, (mp_parse_node_t)pns, "cannot mix bytes and nonbytes literals");
pythontech 0:5868e8752d44 2124 return;
pythontech 0:5868e8752d44 2125 }
pythontech 0:5868e8752d44 2126 }
pythontech 0:5868e8752d44 2127
pythontech 0:5868e8752d44 2128 // if we are not in the last pass, just load a dummy object
pythontech 0:5868e8752d44 2129 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2130 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2131 return;
pythontech 0:5868e8752d44 2132 }
pythontech 0:5868e8752d44 2133
pythontech 0:5868e8752d44 2134 // concatenate string/bytes
pythontech 0:5868e8752d44 2135 vstr_t vstr;
pythontech 0:5868e8752d44 2136 vstr_init_len(&vstr, n_bytes);
pythontech 0:5868e8752d44 2137 byte *s_dest = (byte*)vstr.buf;
pythontech 0:5868e8752d44 2138 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 2139 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[i])) {
pythontech 0:5868e8752d44 2140 size_t s_len;
pythontech 0:5868e8752d44 2141 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
pythontech 0:5868e8752d44 2142 memcpy(s_dest, s, s_len);
pythontech 0:5868e8752d44 2143 s_dest += s_len;
pythontech 0:5868e8752d44 2144 } else {
pythontech 0:5868e8752d44 2145 mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
pythontech 0:5868e8752d44 2146 memcpy(s_dest, (const char*)pns_string->nodes[0], pns_string->nodes[1]);
pythontech 0:5868e8752d44 2147 s_dest += pns_string->nodes[1];
pythontech 0:5868e8752d44 2148 }
pythontech 0:5868e8752d44 2149 }
pythontech 0:5868e8752d44 2150
pythontech 0:5868e8752d44 2151 // load the object
pythontech 0:5868e8752d44 2152 EMIT_ARG(load_const_obj, mp_obj_new_str_from_vstr(string_kind == MP_PARSE_NODE_STRING ? &mp_type_str : &mp_type_bytes, &vstr));
pythontech 0:5868e8752d44 2153 }
pythontech 0:5868e8752d44 2154
pythontech 0:5868e8752d44 2155 // pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
pythontech 0:5868e8752d44 2156 STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
pythontech 0:5868e8752d44 2157 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
pythontech 0:5868e8752d44 2158 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
pythontech 0:5868e8752d44 2159 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2160
pythontech 0:5868e8752d44 2161 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2162 // create a new scope for this comprehension
pythontech 0:5868e8752d44 2163 scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
pythontech 0:5868e8752d44 2164 // store the comprehension scope so the compiling function (this one) can use it at each pass
pythontech 0:5868e8752d44 2165 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
pythontech 0:5868e8752d44 2166 }
pythontech 0:5868e8752d44 2167
pythontech 0:5868e8752d44 2168 // get the scope for this comprehension
pythontech 0:5868e8752d44 2169 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
pythontech 0:5868e8752d44 2170
pythontech 0:5868e8752d44 2171 // compile the comprehension
pythontech 0:5868e8752d44 2172 close_over_variables_etc(comp, this_scope, 0, 0);
pythontech 0:5868e8752d44 2173
pythontech 0:5868e8752d44 2174 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
pythontech 0:5868e8752d44 2175 EMIT(get_iter);
pythontech 0:5868e8752d44 2176 EMIT_ARG(call_function, 1, 0, 0);
pythontech 0:5868e8752d44 2177 }
pythontech 0:5868e8752d44 2178
pythontech 0:5868e8752d44 2179 STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2180 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2181 // an empty tuple
pythontech 0:5868e8752d44 2182 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
pythontech 0:5868e8752d44 2183 } else {
pythontech 0:5868e8752d44 2184 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
pythontech 0:5868e8752d44 2185 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2186 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
pythontech 0:5868e8752d44 2187 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 2188 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2189 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
pythontech 0:5868e8752d44 2190 // tuple of one item, with trailing comma
pythontech 0:5868e8752d44 2191 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
pythontech 0:5868e8752d44 2192 c_tuple(comp, pns->nodes[0], NULL);
pythontech 0:5868e8752d44 2193 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
pythontech 0:5868e8752d44 2194 // tuple of many items
pythontech 0:5868e8752d44 2195 c_tuple(comp, pns->nodes[0], pns2);
pythontech 0:5868e8752d44 2196 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
pythontech 0:5868e8752d44 2197 // generator expression
pythontech 0:5868e8752d44 2198 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
pythontech 0:5868e8752d44 2199 } else {
pythontech 0:5868e8752d44 2200 // tuple with 2 items
pythontech 0:5868e8752d44 2201 goto tuple_with_2_items;
pythontech 0:5868e8752d44 2202 }
pythontech 0:5868e8752d44 2203 } else {
pythontech 0:5868e8752d44 2204 // tuple with 2 items
pythontech 0:5868e8752d44 2205 tuple_with_2_items:
pythontech 0:5868e8752d44 2206 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
pythontech 0:5868e8752d44 2207 }
pythontech 0:5868e8752d44 2208 }
pythontech 0:5868e8752d44 2209 }
pythontech 0:5868e8752d44 2210
pythontech 0:5868e8752d44 2211 STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2212 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2213 // empty list
pythontech 0:5868e8752d44 2214 EMIT_ARG(build_list, 0);
pythontech 0:5868e8752d44 2215 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
pythontech 0:5868e8752d44 2216 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2217 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
pythontech 0:5868e8752d44 2218 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
pythontech 0:5868e8752d44 2219 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
pythontech 0:5868e8752d44 2220 // list of one item, with trailing comma
pythontech 0:5868e8752d44 2221 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
pythontech 0:5868e8752d44 2222 compile_node(comp, pns2->nodes[0]);
pythontech 0:5868e8752d44 2223 EMIT_ARG(build_list, 1);
pythontech 0:5868e8752d44 2224 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
pythontech 0:5868e8752d44 2225 // list of many items
pythontech 0:5868e8752d44 2226 compile_node(comp, pns2->nodes[0]);
pythontech 0:5868e8752d44 2227 compile_generic_all_nodes(comp, pns3);
pythontech 0:5868e8752d44 2228 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
pythontech 0:5868e8752d44 2229 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
pythontech 0:5868e8752d44 2230 // list comprehension
pythontech 0:5868e8752d44 2231 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
pythontech 0:5868e8752d44 2232 } else {
pythontech 0:5868e8752d44 2233 // list with 2 items
pythontech 0:5868e8752d44 2234 goto list_with_2_items;
pythontech 0:5868e8752d44 2235 }
pythontech 0:5868e8752d44 2236 } else {
pythontech 0:5868e8752d44 2237 // list with 2 items
pythontech 0:5868e8752d44 2238 list_with_2_items:
pythontech 0:5868e8752d44 2239 compile_node(comp, pns2->nodes[0]);
pythontech 0:5868e8752d44 2240 compile_node(comp, pns2->nodes[1]);
pythontech 0:5868e8752d44 2241 EMIT_ARG(build_list, 2);
pythontech 0:5868e8752d44 2242 }
pythontech 0:5868e8752d44 2243 } else {
pythontech 0:5868e8752d44 2244 // list with 1 item
pythontech 0:5868e8752d44 2245 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2246 EMIT_ARG(build_list, 1);
pythontech 0:5868e8752d44 2247 }
pythontech 0:5868e8752d44 2248 }
pythontech 0:5868e8752d44 2249
pythontech 0:5868e8752d44 2250 STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2251 mp_parse_node_t pn = pns->nodes[0];
pythontech 0:5868e8752d44 2252 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 2253 // empty dict
pythontech 0:5868e8752d44 2254 EMIT_ARG(build_map, 0);
pythontech 0:5868e8752d44 2255 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 2256 pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2257 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
pythontech 0:5868e8752d44 2258 // dict with one element
pythontech 0:5868e8752d44 2259 EMIT_ARG(build_map, 1);
pythontech 0:5868e8752d44 2260 compile_node(comp, pn);
pythontech 0:5868e8752d44 2261 EMIT(store_map);
pythontech 0:5868e8752d44 2262 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
pythontech 0:5868e8752d44 2263 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
pythontech 0:5868e8752d44 2264 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2265 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
pythontech 0:5868e8752d44 2266 // dict/set with multiple elements
pythontech 0:5868e8752d44 2267
pythontech 0:5868e8752d44 2268 // get tail elements (2nd, 3rd, ...)
pythontech 0:5868e8752d44 2269 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 2270 int n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
pythontech 0:5868e8752d44 2271
pythontech 0:5868e8752d44 2272 // first element sets whether it's a dict or set
pythontech 0:5868e8752d44 2273 bool is_dict;
pythontech 0:5868e8752d44 2274 if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
pythontech 0:5868e8752d44 2275 // a dictionary
pythontech 0:5868e8752d44 2276 EMIT_ARG(build_map, 1 + n);
pythontech 0:5868e8752d44 2277 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2278 EMIT(store_map);
pythontech 0:5868e8752d44 2279 is_dict = true;
pythontech 0:5868e8752d44 2280 } else {
pythontech 0:5868e8752d44 2281 // a set
pythontech 0:5868e8752d44 2282 compile_node(comp, pns->nodes[0]); // 1st value of set
pythontech 0:5868e8752d44 2283 is_dict = false;
pythontech 0:5868e8752d44 2284 }
pythontech 0:5868e8752d44 2285
pythontech 0:5868e8752d44 2286 // process rest of elements
pythontech 0:5868e8752d44 2287 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 2288 mp_parse_node_t pn_i = nodes[i];
pythontech 0:5868e8752d44 2289 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn_i, PN_dictorsetmaker_item);
pythontech 0:5868e8752d44 2290 compile_node(comp, pn_i);
pythontech 0:5868e8752d44 2291 if (is_dict) {
pythontech 0:5868e8752d44 2292 if (!is_key_value) {
pythontech 0:5868e8752d44 2293 compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dictionary");
pythontech 0:5868e8752d44 2294 return;
pythontech 0:5868e8752d44 2295 }
pythontech 0:5868e8752d44 2296 EMIT(store_map);
pythontech 0:5868e8752d44 2297 } else {
pythontech 0:5868e8752d44 2298 if (is_key_value) {
pythontech 0:5868e8752d44 2299 compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
pythontech 0:5868e8752d44 2300 return;
pythontech 0:5868e8752d44 2301 }
pythontech 0:5868e8752d44 2302 }
pythontech 0:5868e8752d44 2303 }
pythontech 0:5868e8752d44 2304
pythontech 0:5868e8752d44 2305 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 2306 // if it's a set, build it
pythontech 0:5868e8752d44 2307 if (!is_dict) {
pythontech 0:5868e8752d44 2308 EMIT_ARG(build_set, 1 + n);
pythontech 0:5868e8752d44 2309 }
pythontech 0:5868e8752d44 2310 #endif
pythontech 0:5868e8752d44 2311 } else {
pythontech 0:5868e8752d44 2312 assert(MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for); // should be
pythontech 0:5868e8752d44 2313 // dict/set comprehension
pythontech 0:5868e8752d44 2314 if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
pythontech 0:5868e8752d44 2315 // a dictionary comprehension
pythontech 0:5868e8752d44 2316 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
pythontech 0:5868e8752d44 2317 } else {
pythontech 0:5868e8752d44 2318 // a set comprehension
pythontech 0:5868e8752d44 2319 compile_comprehension(comp, pns, SCOPE_SET_COMP);
pythontech 0:5868e8752d44 2320 }
pythontech 0:5868e8752d44 2321 }
pythontech 0:5868e8752d44 2322 } else {
pythontech 0:5868e8752d44 2323 // set with one element
pythontech 0:5868e8752d44 2324 goto set_with_one_element;
pythontech 0:5868e8752d44 2325 }
pythontech 0:5868e8752d44 2326 } else {
pythontech 0:5868e8752d44 2327 // set with one element
pythontech 0:5868e8752d44 2328 set_with_one_element:
pythontech 0:5868e8752d44 2329 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 2330 compile_node(comp, pn);
pythontech 0:5868e8752d44 2331 EMIT_ARG(build_set, 1);
pythontech 0:5868e8752d44 2332 #else
pythontech 0:5868e8752d44 2333 assert(0);
pythontech 0:5868e8752d44 2334 #endif
pythontech 0:5868e8752d44 2335 }
pythontech 0:5868e8752d44 2336 }
pythontech 0:5868e8752d44 2337
pythontech 0:5868e8752d44 2338 STATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2339 compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
pythontech 0:5868e8752d44 2340 }
pythontech 0:5868e8752d44 2341
pythontech 0:5868e8752d44 2342 STATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2343 // object who's index we want is on top of stack
pythontech 0:5868e8752d44 2344 compile_node(comp, pns->nodes[0]); // the index
pythontech 0:5868e8752d44 2345 EMIT(load_subscr);
pythontech 0:5868e8752d44 2346 }
pythontech 0:5868e8752d44 2347
pythontech 0:5868e8752d44 2348 STATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2349 // object who's attribute we want is on top of stack
pythontech 0:5868e8752d44 2350 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
pythontech 0:5868e8752d44 2351 }
pythontech 0:5868e8752d44 2352
pythontech 0:5868e8752d44 2353 #if MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 2354 STATIC void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2355 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
pythontech 0:5868e8752d44 2356 mp_parse_node_t pn = pns->nodes[0];
pythontech 0:5868e8752d44 2357 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 2358 // [?:]
pythontech 0:5868e8752d44 2359 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2360 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2361 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 2362 pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2363 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
pythontech 0:5868e8752d44 2364 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2365 pn = pns->nodes[0];
pythontech 0:5868e8752d44 2366 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 2367 // [?::]
pythontech 0:5868e8752d44 2368 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2369 } else {
pythontech 0:5868e8752d44 2370 // [?::x]
pythontech 0:5868e8752d44 2371 compile_node(comp, pn);
pythontech 0:5868e8752d44 2372 EMIT_ARG(build_slice, 3);
pythontech 0:5868e8752d44 2373 }
pythontech 0:5868e8752d44 2374 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
pythontech 0:5868e8752d44 2375 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2376 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
pythontech 0:5868e8752d44 2377 pns = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2378 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
pythontech 0:5868e8752d44 2379 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2380 // [?:x:]
pythontech 0:5868e8752d44 2381 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2382 } else {
pythontech 0:5868e8752d44 2383 // [?:x:x]
pythontech 0:5868e8752d44 2384 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2385 EMIT_ARG(build_slice, 3);
pythontech 0:5868e8752d44 2386 }
pythontech 0:5868e8752d44 2387 } else {
pythontech 0:5868e8752d44 2388 // [?:x]
pythontech 0:5868e8752d44 2389 compile_node(comp, pn);
pythontech 0:5868e8752d44 2390 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2391 }
pythontech 0:5868e8752d44 2392 } else {
pythontech 0:5868e8752d44 2393 // [?:x]
pythontech 0:5868e8752d44 2394 compile_node(comp, pn);
pythontech 0:5868e8752d44 2395 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2396 }
pythontech 0:5868e8752d44 2397 }
pythontech 0:5868e8752d44 2398
pythontech 0:5868e8752d44 2399 STATIC void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2400 compile_node(comp, pns->nodes[0]); // start of slice
pythontech 0:5868e8752d44 2401 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
pythontech 0:5868e8752d44 2402 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
pythontech 0:5868e8752d44 2403 }
pythontech 0:5868e8752d44 2404
pythontech 0:5868e8752d44 2405 STATIC void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2406 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2407 compile_subscript_3_helper(comp, pns);
pythontech 0:5868e8752d44 2408 }
pythontech 0:5868e8752d44 2409 #endif // MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 2410
pythontech 0:5868e8752d44 2411 STATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2412 // if this is called then we are compiling a dict key:value pair
pythontech 0:5868e8752d44 2413 compile_node(comp, pns->nodes[1]); // value
pythontech 0:5868e8752d44 2414 compile_node(comp, pns->nodes[0]); // key
pythontech 0:5868e8752d44 2415 }
pythontech 0:5868e8752d44 2416
pythontech 0:5868e8752d44 2417 STATIC void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2418 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
pythontech 0:5868e8752d44 2419 // store class object into class name
pythontech 0:5868e8752d44 2420 compile_store_id(comp, cname);
pythontech 0:5868e8752d44 2421 }
pythontech 0:5868e8752d44 2422
pythontech 0:5868e8752d44 2423 STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2424 if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {
pythontech 0:5868e8752d44 2425 compile_syntax_error(comp, (mp_parse_node_t)pns, "'yield' outside function");
pythontech 0:5868e8752d44 2426 return;
pythontech 0:5868e8752d44 2427 }
pythontech 0:5868e8752d44 2428 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2429 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2430 EMIT(yield_value);
pythontech 0:5868e8752d44 2431 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
pythontech 0:5868e8752d44 2432 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2433 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2434 EMIT(get_iter);
pythontech 0:5868e8752d44 2435 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2436 EMIT(yield_from);
pythontech 0:5868e8752d44 2437 } else {
pythontech 0:5868e8752d44 2438 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2439 EMIT(yield_value);
pythontech 0:5868e8752d44 2440 }
pythontech 0:5868e8752d44 2441 }
pythontech 0:5868e8752d44 2442
pythontech 0:5868e8752d44 2443 STATIC void compile_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2444 // only create and load the actual str object on the last pass
pythontech 0:5868e8752d44 2445 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2446 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2447 } else {
pythontech 0:5868e8752d44 2448 EMIT_ARG(load_const_obj, mp_obj_new_str((const char*)pns->nodes[0], pns->nodes[1], false));
pythontech 0:5868e8752d44 2449 }
pythontech 0:5868e8752d44 2450 }
pythontech 0:5868e8752d44 2451
pythontech 0:5868e8752d44 2452 STATIC void compile_bytes(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2453 // only create and load the actual bytes object on the last pass
pythontech 0:5868e8752d44 2454 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2455 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2456 } else {
pythontech 0:5868e8752d44 2457 EMIT_ARG(load_const_obj, mp_obj_new_bytes((const byte*)pns->nodes[0], pns->nodes[1]));
pythontech 0:5868e8752d44 2458 }
pythontech 0:5868e8752d44 2459 }
pythontech 0:5868e8752d44 2460
pythontech 0:5868e8752d44 2461 STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2462 #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
pythontech 0:5868e8752d44 2463 // nodes are 32-bit pointers, but need to extract 64-bit object
pythontech 0:5868e8752d44 2464 EMIT_ARG(load_const_obj, (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
pythontech 0:5868e8752d44 2465 #else
pythontech 0:5868e8752d44 2466 EMIT_ARG(load_const_obj, (mp_obj_t)pns->nodes[0]);
pythontech 0:5868e8752d44 2467 #endif
pythontech 0:5868e8752d44 2468 }
pythontech 0:5868e8752d44 2469
pythontech 0:5868e8752d44 2470 typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
pythontech 0:5868e8752d44 2471 STATIC compile_function_t compile_function[] = {
pythontech 0:5868e8752d44 2472 #define nc NULL
pythontech 0:5868e8752d44 2473 #define c(f) compile_##f
pythontech 0:5868e8752d44 2474 #define DEF_RULE(rule, comp, kind, ...) comp,
pythontech 0:5868e8752d44 2475 #include "py/grammar.h"
pythontech 0:5868e8752d44 2476 #undef nc
pythontech 0:5868e8752d44 2477 #undef c
pythontech 0:5868e8752d44 2478 #undef DEF_RULE
pythontech 0:5868e8752d44 2479 NULL,
pythontech 0:5868e8752d44 2480 compile_string,
pythontech 0:5868e8752d44 2481 compile_bytes,
pythontech 0:5868e8752d44 2482 compile_const_object,
pythontech 0:5868e8752d44 2483 };
pythontech 0:5868e8752d44 2484
pythontech 0:5868e8752d44 2485 STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2486 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 2487 // pass
pythontech 0:5868e8752d44 2488 } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
pythontech 0:5868e8752d44 2489 mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
pythontech 0:5868e8752d44 2490 #if MICROPY_DYNAMIC_COMPILER
pythontech 0:5868e8752d44 2491 mp_uint_t sign_mask = -(1 << (mp_dynamic_compiler.small_int_bits - 1));
pythontech 0:5868e8752d44 2492 if ((arg & sign_mask) == 0 || (arg & sign_mask) == sign_mask) {
pythontech 0:5868e8752d44 2493 // integer fits in target runtime's small-int
pythontech 0:5868e8752d44 2494 EMIT_ARG(load_const_small_int, arg);
pythontech 0:5868e8752d44 2495 } else {
pythontech 0:5868e8752d44 2496 // integer doesn't fit, so create a multi-precision int object
pythontech 0:5868e8752d44 2497 // (but only create the actual object on the last pass)
pythontech 0:5868e8752d44 2498 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2499 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2500 } else {
pythontech 0:5868e8752d44 2501 EMIT_ARG(load_const_obj, mp_obj_new_int_from_ll(arg));
pythontech 0:5868e8752d44 2502 }
pythontech 0:5868e8752d44 2503 }
pythontech 0:5868e8752d44 2504 #else
pythontech 0:5868e8752d44 2505 EMIT_ARG(load_const_small_int, arg);
pythontech 0:5868e8752d44 2506 #endif
pythontech 0:5868e8752d44 2507 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
pythontech 0:5868e8752d44 2508 uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 2509 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
pythontech 0:5868e8752d44 2510 case MP_PARSE_NODE_ID: compile_load_id(comp, arg); break;
pythontech 0:5868e8752d44 2511 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg); break;
pythontech 0:5868e8752d44 2512 case MP_PARSE_NODE_BYTES:
pythontech 0:5868e8752d44 2513 // only create and load the actual bytes object on the last pass
pythontech 0:5868e8752d44 2514 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2515 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2516 } else {
pythontech 0:5868e8752d44 2517 size_t len;
pythontech 0:5868e8752d44 2518 const byte *data = qstr_data(arg, &len);
pythontech 0:5868e8752d44 2519 EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len));
pythontech 0:5868e8752d44 2520 }
pythontech 0:5868e8752d44 2521 break;
pythontech 0:5868e8752d44 2522 case MP_PARSE_NODE_TOKEN: default:
pythontech 0:5868e8752d44 2523 if (arg == MP_TOKEN_NEWLINE) {
pythontech 0:5868e8752d44 2524 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
pythontech 0:5868e8752d44 2525 // or when single_input lets through a NEWLINE (user enters a blank line)
pythontech 0:5868e8752d44 2526 // do nothing
pythontech 0:5868e8752d44 2527 } else {
pythontech 0:5868e8752d44 2528 EMIT_ARG(load_const_tok, arg);
pythontech 0:5868e8752d44 2529 }
pythontech 0:5868e8752d44 2530 break;
pythontech 0:5868e8752d44 2531 }
pythontech 0:5868e8752d44 2532 } else {
pythontech 0:5868e8752d44 2533 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2534 EMIT_ARG(set_source_line, pns->source_line);
pythontech 0:5868e8752d44 2535 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
pythontech 0:5868e8752d44 2536 if (f == NULL) {
pythontech 0:5868e8752d44 2537 #if MICROPY_DEBUG_PRINTERS
pythontech 0:5868e8752d44 2538 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
pythontech 0:5868e8752d44 2539 mp_parse_node_print(pn, 0);
pythontech 0:5868e8752d44 2540 #endif
pythontech 0:5868e8752d44 2541 compile_syntax_error(comp, pn, "internal compiler error");
pythontech 0:5868e8752d44 2542 } else {
pythontech 0:5868e8752d44 2543 f(comp, pns);
pythontech 0:5868e8752d44 2544 }
pythontech 0:5868e8752d44 2545 }
pythontech 0:5868e8752d44 2546 }
pythontech 0:5868e8752d44 2547
pythontech 0:5868e8752d44 2548 STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star) {
pythontech 0:5868e8752d44 2549 // check that **kw is last
pythontech 0:5868e8752d44 2550 if ((comp->scope_cur->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
pythontech 0:5868e8752d44 2551 compile_syntax_error(comp, pn, "invalid syntax");
pythontech 0:5868e8752d44 2552 return;
pythontech 0:5868e8752d44 2553 }
pythontech 0:5868e8752d44 2554
pythontech 0:5868e8752d44 2555 qstr param_name = MP_QSTR_NULL;
pythontech 0:5868e8752d44 2556 uint param_flag = ID_FLAG_IS_PARAM;
pythontech 0:5868e8752d44 2557 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 2558 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 2559 if (comp->have_star) {
pythontech 0:5868e8752d44 2560 // comes after a star, so counts as a keyword-only parameter
pythontech 0:5868e8752d44 2561 comp->scope_cur->num_kwonly_args += 1;
pythontech 0:5868e8752d44 2562 } else {
pythontech 0:5868e8752d44 2563 // comes before a star, so counts as a positional parameter
pythontech 0:5868e8752d44 2564 comp->scope_cur->num_pos_args += 1;
pythontech 0:5868e8752d44 2565 }
pythontech 0:5868e8752d44 2566 } else {
pythontech 0:5868e8752d44 2567 assert(MP_PARSE_NODE_IS_STRUCT(pn));
pythontech 0:5868e8752d44 2568 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2569 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
pythontech 0:5868e8752d44 2570 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2571 if (comp->have_star) {
pythontech 0:5868e8752d44 2572 // comes after a star, so counts as a keyword-only parameter
pythontech 0:5868e8752d44 2573 comp->scope_cur->num_kwonly_args += 1;
pythontech 0:5868e8752d44 2574 } else {
pythontech 0:5868e8752d44 2575 // comes before a star, so counts as a positional parameter
pythontech 0:5868e8752d44 2576 comp->scope_cur->num_pos_args += 1;
pythontech 0:5868e8752d44 2577 }
pythontech 0:5868e8752d44 2578 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
pythontech 0:5868e8752d44 2579 if (comp->have_star) {
pythontech 0:5868e8752d44 2580 // more than one star
pythontech 0:5868e8752d44 2581 compile_syntax_error(comp, pn, "invalid syntax");
pythontech 0:5868e8752d44 2582 return;
pythontech 0:5868e8752d44 2583 }
pythontech 0:5868e8752d44 2584 comp->have_star = true;
pythontech 0:5868e8752d44 2585 param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM;
pythontech 0:5868e8752d44 2586 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2587 // bare star
pythontech 0:5868e8752d44 2588 // TODO see http://www.python.org/dev/peps/pep-3102/
pythontech 0:5868e8752d44 2589 //assert(comp->scope_cur->num_dict_params == 0);
pythontech 0:5868e8752d44 2590 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
pythontech 0:5868e8752d44 2591 // named star
pythontech 0:5868e8752d44 2592 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
pythontech 0:5868e8752d44 2593 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2594 } else {
pythontech 0:5868e8752d44 2595 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)); // should be
pythontech 0:5868e8752d44 2596 // named star with possible annotation
pythontech 0:5868e8752d44 2597 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
pythontech 0:5868e8752d44 2598 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2599 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2600 }
pythontech 0:5868e8752d44 2601 } else {
pythontech 0:5868e8752d44 2602 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star); // should be
pythontech 0:5868e8752d44 2603 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2604 param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM;
pythontech 0:5868e8752d44 2605 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
pythontech 0:5868e8752d44 2606 }
pythontech 0:5868e8752d44 2607 }
pythontech 0:5868e8752d44 2608
pythontech 0:5868e8752d44 2609 if (param_name != MP_QSTR_NULL) {
pythontech 0:5868e8752d44 2610 bool added;
pythontech 0:5868e8752d44 2611 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
pythontech 0:5868e8752d44 2612 if (!added) {
pythontech 0:5868e8752d44 2613 compile_syntax_error(comp, pn, "name reused for argument");
pythontech 0:5868e8752d44 2614 return;
pythontech 0:5868e8752d44 2615 }
pythontech 0:5868e8752d44 2616 id_info->kind = ID_INFO_KIND_LOCAL;
pythontech 0:5868e8752d44 2617 id_info->flags = param_flag;
pythontech 0:5868e8752d44 2618 }
pythontech 0:5868e8752d44 2619 }
pythontech 0:5868e8752d44 2620
pythontech 0:5868e8752d44 2621 STATIC void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2622 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star);
pythontech 0:5868e8752d44 2623 }
pythontech 0:5868e8752d44 2624
pythontech 0:5868e8752d44 2625 STATIC void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2626 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star);
pythontech 0:5868e8752d44 2627 }
pythontech 0:5868e8752d44 2628
pythontech 0:5868e8752d44 2629 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 2630 STATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2631 if (!MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 2632 // no annotation
pythontech 0:5868e8752d44 2633 return;
pythontech 0:5868e8752d44 2634 }
pythontech 0:5868e8752d44 2635
pythontech 0:5868e8752d44 2636 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2637 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_name) {
pythontech 0:5868e8752d44 2638 // named parameter with possible annotation
pythontech 0:5868e8752d44 2639 // fallthrough
pythontech 0:5868e8752d44 2640 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_star) {
pythontech 0:5868e8752d44 2641 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
pythontech 0:5868e8752d44 2642 // named star with possible annotation
pythontech 0:5868e8752d44 2643 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2644 // fallthrough
pythontech 0:5868e8752d44 2645 } else {
pythontech 0:5868e8752d44 2646 // no annotation
pythontech 0:5868e8752d44 2647 return;
pythontech 0:5868e8752d44 2648 }
pythontech 0:5868e8752d44 2649 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star) {
pythontech 0:5868e8752d44 2650 // double star with possible annotation
pythontech 0:5868e8752d44 2651 // fallthrough
pythontech 0:5868e8752d44 2652 } else {
pythontech 0:5868e8752d44 2653 // no annotation
pythontech 0:5868e8752d44 2654 return;
pythontech 0:5868e8752d44 2655 }
pythontech 0:5868e8752d44 2656
pythontech 0:5868e8752d44 2657 mp_parse_node_t pn_annotation = pns->nodes[1];
pythontech 0:5868e8752d44 2658
pythontech 0:5868e8752d44 2659 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
pythontech 0:5868e8752d44 2660 qstr param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2661 id_info_t *id_info = scope_find(comp->scope_cur, param_name);
pythontech 0:5868e8752d44 2662 assert(id_info != NULL);
pythontech 0:5868e8752d44 2663
pythontech 0:5868e8752d44 2664 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
pythontech 0:5868e8752d44 2665 qstr arg_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
pythontech 0:5868e8752d44 2666 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ARG, id_info->local_num, arg_type);
pythontech 0:5868e8752d44 2667 } else {
pythontech 0:5868e8752d44 2668 compile_syntax_error(comp, pn_annotation, "parameter annotation must be an identifier");
pythontech 0:5868e8752d44 2669 }
pythontech 0:5868e8752d44 2670 }
pythontech 0:5868e8752d44 2671 }
pythontech 0:5868e8752d44 2672 #endif // MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 2673
pythontech 0:5868e8752d44 2674 STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pns_comp_for, mp_parse_node_t pn_inner_expr, int for_depth) {
pythontech 0:5868e8752d44 2675 uint l_top = comp_next_label(comp);
pythontech 0:5868e8752d44 2676 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 2677 EMIT_ARG(label_assign, l_top);
pythontech 0:5868e8752d44 2678 EMIT_ARG(for_iter, l_end);
pythontech 0:5868e8752d44 2679 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
pythontech 0:5868e8752d44 2680 mp_parse_node_t pn_iter = pns_comp_for->nodes[2];
pythontech 0:5868e8752d44 2681
pythontech 0:5868e8752d44 2682 tail_recursion:
pythontech 0:5868e8752d44 2683 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
pythontech 0:5868e8752d44 2684 // no more nested if/for; compile inner expression
pythontech 0:5868e8752d44 2685 compile_node(comp, pn_inner_expr);
pythontech 0:5868e8752d44 2686 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
pythontech 0:5868e8752d44 2687 EMIT_ARG(list_append, for_depth + 2);
pythontech 0:5868e8752d44 2688 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
pythontech 0:5868e8752d44 2689 EMIT_ARG(map_add, for_depth + 2);
pythontech 0:5868e8752d44 2690 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 2691 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
pythontech 0:5868e8752d44 2692 EMIT_ARG(set_add, for_depth + 2);
pythontech 0:5868e8752d44 2693 #endif
pythontech 0:5868e8752d44 2694 } else {
pythontech 0:5868e8752d44 2695 EMIT(yield_value);
pythontech 0:5868e8752d44 2696 EMIT(pop_top);
pythontech 0:5868e8752d44 2697 }
pythontech 0:5868e8752d44 2698 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
pythontech 0:5868e8752d44 2699 // if condition
pythontech 0:5868e8752d44 2700 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
pythontech 0:5868e8752d44 2701 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
pythontech 0:5868e8752d44 2702 pn_iter = pns_comp_if->nodes[1];
pythontech 0:5868e8752d44 2703 goto tail_recursion;
pythontech 0:5868e8752d44 2704 } else {
pythontech 0:5868e8752d44 2705 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)); // should be
pythontech 0:5868e8752d44 2706 // for loop
pythontech 0:5868e8752d44 2707 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
pythontech 0:5868e8752d44 2708 compile_node(comp, pns_comp_for2->nodes[1]);
pythontech 0:5868e8752d44 2709 EMIT(get_iter);
pythontech 0:5868e8752d44 2710 compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1);
pythontech 0:5868e8752d44 2711 }
pythontech 0:5868e8752d44 2712
pythontech 0:5868e8752d44 2713 EMIT_ARG(jump, l_top);
pythontech 0:5868e8752d44 2714 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 2715 EMIT(for_iter_end);
pythontech 0:5868e8752d44 2716 }
pythontech 0:5868e8752d44 2717
pythontech 0:5868e8752d44 2718 STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2719 #if MICROPY_ENABLE_DOC_STRING
pythontech 0:5868e8752d44 2720 // see http://www.python.org/dev/peps/pep-0257/
pythontech 0:5868e8752d44 2721
pythontech 0:5868e8752d44 2722 // look for the first statement
pythontech 0:5868e8752d44 2723 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
pythontech 0:5868e8752d44 2724 // a statement; fall through
pythontech 0:5868e8752d44 2725 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
pythontech 0:5868e8752d44 2726 // file input; find the first non-newline node
pythontech 0:5868e8752d44 2727 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2728 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2729 for (int i = 0; i < num_nodes; i++) {
pythontech 0:5868e8752d44 2730 pn = pns->nodes[i];
pythontech 0:5868e8752d44 2731 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)) {
pythontech 0:5868e8752d44 2732 // not a newline, so this is the first statement; finish search
pythontech 0:5868e8752d44 2733 break;
pythontech 0:5868e8752d44 2734 }
pythontech 0:5868e8752d44 2735 }
pythontech 0:5868e8752d44 2736 // 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
pythontech 0:5868e8752d44 2737 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
pythontech 0:5868e8752d44 2738 // a list of statements; get the first one
pythontech 0:5868e8752d44 2739 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
pythontech 0:5868e8752d44 2740 } else {
pythontech 0:5868e8752d44 2741 return;
pythontech 0:5868e8752d44 2742 }
pythontech 0:5868e8752d44 2743
pythontech 0:5868e8752d44 2744 // check the first statement for a doc string
pythontech 0:5868e8752d44 2745 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
pythontech 0:5868e8752d44 2746 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2747 if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])
pythontech 0:5868e8752d44 2748 && MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)
pythontech 0:5868e8752d44 2749 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)) {
pythontech 0:5868e8752d44 2750 // compile the doc string
pythontech 0:5868e8752d44 2751 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2752 // store the doc string
pythontech 0:5868e8752d44 2753 compile_store_id(comp, MP_QSTR___doc__);
pythontech 0:5868e8752d44 2754 }
pythontech 0:5868e8752d44 2755 }
pythontech 0:5868e8752d44 2756 #else
pythontech 0:5868e8752d44 2757 (void)comp;
pythontech 0:5868e8752d44 2758 (void)pn;
pythontech 0:5868e8752d44 2759 #endif
pythontech 0:5868e8752d44 2760 }
pythontech 0:5868e8752d44 2761
pythontech 0:5868e8752d44 2762 STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
pythontech 0:5868e8752d44 2763 comp->pass = pass;
pythontech 0:5868e8752d44 2764 comp->scope_cur = scope;
pythontech 0:5868e8752d44 2765 comp->next_label = 1;
pythontech 0:5868e8752d44 2766 EMIT_ARG(start_pass, pass, scope);
pythontech 0:5868e8752d44 2767
pythontech 0:5868e8752d44 2768 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2769 // reset maximum stack sizes in scope
pythontech 0:5868e8752d44 2770 // they will be computed in this first pass
pythontech 0:5868e8752d44 2771 scope->stack_size = 0;
pythontech 0:5868e8752d44 2772 scope->exc_stack_size = 0;
pythontech 0:5868e8752d44 2773 }
pythontech 0:5868e8752d44 2774
pythontech 0:5868e8752d44 2775 // compile
pythontech 0:5868e8752d44 2776 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
pythontech 0:5868e8752d44 2777 assert(scope->kind == SCOPE_MODULE);
pythontech 0:5868e8752d44 2778 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 2779 compile_node(comp, pns->nodes[0]); // compile the expression
pythontech 0:5868e8752d44 2780 EMIT(return_value);
pythontech 0:5868e8752d44 2781 } else if (scope->kind == SCOPE_MODULE) {
pythontech 0:5868e8752d44 2782 if (!comp->is_repl) {
pythontech 0:5868e8752d44 2783 check_for_doc_string(comp, scope->pn);
pythontech 0:5868e8752d44 2784 }
pythontech 0:5868e8752d44 2785 compile_node(comp, scope->pn);
pythontech 0:5868e8752d44 2786 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2787 EMIT(return_value);
pythontech 0:5868e8752d44 2788 } else if (scope->kind == SCOPE_FUNCTION) {
pythontech 0:5868e8752d44 2789 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 2790 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 2791 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
pythontech 0:5868e8752d44 2792
pythontech 0:5868e8752d44 2793 // work out number of parameters, keywords and default parameters, and add them to the id_info array
pythontech 0:5868e8752d44 2794 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
pythontech 0:5868e8752d44 2795 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2796 comp->have_star = false;
pythontech 0:5868e8752d44 2797 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
pythontech 0:5868e8752d44 2798 }
pythontech 0:5868e8752d44 2799 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 2800 else if (scope->emit_options == MP_EMIT_OPT_VIPER) {
pythontech 0:5868e8752d44 2801 // compile annotations; only needed on latter compiler passes
pythontech 0:5868e8752d44 2802 // only needed for viper emitter
pythontech 0:5868e8752d44 2803
pythontech 0:5868e8752d44 2804 // argument annotations
pythontech 0:5868e8752d44 2805 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_annotations);
pythontech 0:5868e8752d44 2806
pythontech 0:5868e8752d44 2807 // pns->nodes[2] is return/whole function annotation
pythontech 0:5868e8752d44 2808 mp_parse_node_t pn_annotation = pns->nodes[2];
pythontech 0:5868e8752d44 2809 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
pythontech 0:5868e8752d44 2810 // nodes[2] can be null or a test-expr
pythontech 0:5868e8752d44 2811 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
pythontech 0:5868e8752d44 2812 qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
pythontech 0:5868e8752d44 2813 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_RETURN, 0, ret_type);
pythontech 0:5868e8752d44 2814 } else {
pythontech 0:5868e8752d44 2815 compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier");
pythontech 0:5868e8752d44 2816 }
pythontech 0:5868e8752d44 2817 }
pythontech 0:5868e8752d44 2818 }
pythontech 0:5868e8752d44 2819 #endif // MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 2820
pythontech 0:5868e8752d44 2821 compile_node(comp, pns->nodes[3]); // 3 is function body
pythontech 0:5868e8752d44 2822 // emit return if it wasn't the last opcode
pythontech 0:5868e8752d44 2823 if (!EMIT(last_emit_was_return_value)) {
pythontech 0:5868e8752d44 2824 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2825 EMIT(return_value);
pythontech 0:5868e8752d44 2826 }
pythontech 0:5868e8752d44 2827 } else if (scope->kind == SCOPE_LAMBDA) {
pythontech 0:5868e8752d44 2828 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 2829 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 2830 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
pythontech 0:5868e8752d44 2831
pythontech 0:5868e8752d44 2832 // work out number of parameters, keywords and default parameters, and add them to the id_info array
pythontech 0:5868e8752d44 2833 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
pythontech 0:5868e8752d44 2834 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2835 comp->have_star = false;
pythontech 0:5868e8752d44 2836 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
pythontech 0:5868e8752d44 2837 }
pythontech 0:5868e8752d44 2838
pythontech 0:5868e8752d44 2839 compile_node(comp, pns->nodes[1]); // 1 is lambda body
pythontech 0:5868e8752d44 2840
pythontech 0:5868e8752d44 2841 // if the lambda is a generator, then we return None, not the result of the expression of the lambda
pythontech 0:5868e8752d44 2842 if (scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
pythontech 0:5868e8752d44 2843 EMIT(pop_top);
pythontech 0:5868e8752d44 2844 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2845 }
pythontech 0:5868e8752d44 2846 EMIT(return_value);
pythontech 0:5868e8752d44 2847 } else if (scope->kind == SCOPE_LIST_COMP || scope->kind == SCOPE_DICT_COMP || scope->kind == SCOPE_SET_COMP || scope->kind == SCOPE_GEN_EXPR) {
pythontech 0:5868e8752d44 2848 // a bit of a hack at the moment
pythontech 0:5868e8752d44 2849
pythontech 0:5868e8752d44 2850 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 2851 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 2852 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
pythontech 0:5868e8752d44 2853 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
pythontech 0:5868e8752d44 2854 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2855
pythontech 0:5868e8752d44 2856 // We need a unique name for the comprehension argument (the iterator).
pythontech 0:5868e8752d44 2857 // CPython uses .0, but we should be able to use anything that won't
pythontech 0:5868e8752d44 2858 // clash with a user defined variable. Best to use an existing qstr,
pythontech 0:5868e8752d44 2859 // so we use the blank qstr.
pythontech 0:5868e8752d44 2860 qstr qstr_arg = MP_QSTR_;
pythontech 0:5868e8752d44 2861 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2862 bool added;
pythontech 0:5868e8752d44 2863 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
pythontech 0:5868e8752d44 2864 assert(added);
pythontech 0:5868e8752d44 2865 id_info->kind = ID_INFO_KIND_LOCAL;
pythontech 0:5868e8752d44 2866 scope->num_pos_args = 1;
pythontech 0:5868e8752d44 2867 }
pythontech 0:5868e8752d44 2868
pythontech 0:5868e8752d44 2869 if (scope->kind == SCOPE_LIST_COMP) {
pythontech 0:5868e8752d44 2870 EMIT_ARG(build_list, 0);
pythontech 0:5868e8752d44 2871 } else if (scope->kind == SCOPE_DICT_COMP) {
pythontech 0:5868e8752d44 2872 EMIT_ARG(build_map, 0);
pythontech 0:5868e8752d44 2873 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 2874 } else if (scope->kind == SCOPE_SET_COMP) {
pythontech 0:5868e8752d44 2875 EMIT_ARG(build_set, 0);
pythontech 0:5868e8752d44 2876 #endif
pythontech 0:5868e8752d44 2877 }
pythontech 0:5868e8752d44 2878
pythontech 0:5868e8752d44 2879 compile_load_id(comp, qstr_arg);
pythontech 0:5868e8752d44 2880 compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0);
pythontech 0:5868e8752d44 2881
pythontech 0:5868e8752d44 2882 if (scope->kind == SCOPE_GEN_EXPR) {
pythontech 0:5868e8752d44 2883 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2884 }
pythontech 0:5868e8752d44 2885 EMIT(return_value);
pythontech 0:5868e8752d44 2886 } else {
pythontech 0:5868e8752d44 2887 assert(scope->kind == SCOPE_CLASS);
pythontech 0:5868e8752d44 2888 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 2889 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 2890 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
pythontech 0:5868e8752d44 2891
pythontech 0:5868e8752d44 2892 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2893 bool added;
pythontech 0:5868e8752d44 2894 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
pythontech 0:5868e8752d44 2895 assert(added);
pythontech 0:5868e8752d44 2896 id_info->kind = ID_INFO_KIND_LOCAL;
pythontech 0:5868e8752d44 2897 }
pythontech 0:5868e8752d44 2898
pythontech 0:5868e8752d44 2899 compile_load_id(comp, MP_QSTR___name__);
pythontech 0:5868e8752d44 2900 compile_store_id(comp, MP_QSTR___module__);
pythontech 0:5868e8752d44 2901 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
pythontech 0:5868e8752d44 2902 compile_store_id(comp, MP_QSTR___qualname__);
pythontech 0:5868e8752d44 2903
pythontech 0:5868e8752d44 2904 check_for_doc_string(comp, pns->nodes[2]);
pythontech 0:5868e8752d44 2905 compile_node(comp, pns->nodes[2]); // 2 is class body
pythontech 0:5868e8752d44 2906
pythontech 0:5868e8752d44 2907 id_info_t *id = scope_find(scope, MP_QSTR___class__);
pythontech 0:5868e8752d44 2908 assert(id != NULL);
pythontech 0:5868e8752d44 2909 if (id->kind == ID_INFO_KIND_LOCAL) {
pythontech 0:5868e8752d44 2910 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2911 } else {
pythontech 0:5868e8752d44 2912 EMIT_LOAD_FAST(MP_QSTR___class__, id->local_num);
pythontech 0:5868e8752d44 2913 }
pythontech 0:5868e8752d44 2914 EMIT(return_value);
pythontech 0:5868e8752d44 2915 }
pythontech 0:5868e8752d44 2916
pythontech 0:5868e8752d44 2917 EMIT(end_pass);
pythontech 0:5868e8752d44 2918
pythontech 0:5868e8752d44 2919 // make sure we match all the exception levels
pythontech 0:5868e8752d44 2920 assert(comp->cur_except_level == 0);
pythontech 0:5868e8752d44 2921 }
pythontech 0:5868e8752d44 2922
pythontech 0:5868e8752d44 2923 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 2924 // requires 3 passes: SCOPE, CODE_SIZE, EMIT
pythontech 0:5868e8752d44 2925 STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
pythontech 0:5868e8752d44 2926 comp->pass = pass;
pythontech 0:5868e8752d44 2927 comp->scope_cur = scope;
pythontech 0:5868e8752d44 2928 comp->next_label = 1;
pythontech 0:5868e8752d44 2929
pythontech 0:5868e8752d44 2930 if (scope->kind != SCOPE_FUNCTION) {
pythontech 0:5868e8752d44 2931 compile_syntax_error(comp, MP_PARSE_NODE_NULL, "inline assembler must be a function");
pythontech 0:5868e8752d44 2932 return;
pythontech 0:5868e8752d44 2933 }
pythontech 0:5868e8752d44 2934
pythontech 0:5868e8752d44 2935 if (comp->pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2936 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur, &comp->compile_error);
pythontech 0:5868e8752d44 2937 }
pythontech 0:5868e8752d44 2938
pythontech 0:5868e8752d44 2939 // get the function definition parse node
pythontech 0:5868e8752d44 2940 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 2941 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 2942 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
pythontech 0:5868e8752d44 2943
pythontech 0:5868e8752d44 2944 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
pythontech 0:5868e8752d44 2945
pythontech 0:5868e8752d44 2946 // parameters are in pns->nodes[1]
pythontech 0:5868e8752d44 2947 if (comp->pass == MP_PASS_CODE_SIZE) {
pythontech 0:5868e8752d44 2948 mp_parse_node_t *pn_params;
pythontech 0:5868e8752d44 2949 int n_params = mp_parse_node_extract_list(&pns->nodes[1], PN_typedargslist, &pn_params);
pythontech 0:5868e8752d44 2950 scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
pythontech 0:5868e8752d44 2951 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 2952 goto inline_asm_error;
pythontech 0:5868e8752d44 2953 }
pythontech 0:5868e8752d44 2954 }
pythontech 0:5868e8752d44 2955
pythontech 0:5868e8752d44 2956 // pns->nodes[2] is function return annotation
pythontech 0:5868e8752d44 2957 mp_uint_t type_sig = MP_NATIVE_TYPE_INT;
pythontech 0:5868e8752d44 2958 mp_parse_node_t pn_annotation = pns->nodes[2];
pythontech 0:5868e8752d44 2959 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
pythontech 0:5868e8752d44 2960 // nodes[2] can be null or a test-expr
pythontech 0:5868e8752d44 2961 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
pythontech 0:5868e8752d44 2962 qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
pythontech 0:5868e8752d44 2963 switch (ret_type) {
pythontech 0:5868e8752d44 2964 case MP_QSTR_object: type_sig = MP_NATIVE_TYPE_OBJ; break;
pythontech 0:5868e8752d44 2965 case MP_QSTR_bool: type_sig = MP_NATIVE_TYPE_BOOL; break;
pythontech 0:5868e8752d44 2966 case MP_QSTR_int: type_sig = MP_NATIVE_TYPE_INT; break;
pythontech 0:5868e8752d44 2967 case MP_QSTR_uint: type_sig = MP_NATIVE_TYPE_UINT; break;
pythontech 0:5868e8752d44 2968 default: compile_syntax_error(comp, pn_annotation, "unknown type"); return;
pythontech 0:5868e8752d44 2969 }
pythontech 0:5868e8752d44 2970 } else {
pythontech 0:5868e8752d44 2971 compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier");
pythontech 0:5868e8752d44 2972 }
pythontech 0:5868e8752d44 2973 }
pythontech 0:5868e8752d44 2974
pythontech 0:5868e8752d44 2975 mp_parse_node_t pn_body = pns->nodes[3]; // body
pythontech 0:5868e8752d44 2976 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 2977 int num = mp_parse_node_extract_list(&pn_body, PN_suite_block_stmts, &nodes);
pythontech 0:5868e8752d44 2978
pythontech 0:5868e8752d44 2979 for (int i = 0; i < num; i++) {
pythontech 0:5868e8752d44 2980 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
pythontech 0:5868e8752d44 2981 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
pythontech 0:5868e8752d44 2982 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_pass_stmt) {
pythontech 0:5868e8752d44 2983 // no instructions
pythontech 0:5868e8752d44 2984 continue;
pythontech 0:5868e8752d44 2985 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_expr_stmt) {
pythontech 0:5868e8752d44 2986 // not an instruction; error
pythontech 0:5868e8752d44 2987 not_an_instruction:
pythontech 0:5868e8752d44 2988 compile_syntax_error(comp, nodes[i], "expecting an assembler instruction");
pythontech 0:5868e8752d44 2989 return;
pythontech 0:5868e8752d44 2990 }
pythontech 0:5868e8752d44 2991
pythontech 0:5868e8752d44 2992 // check structure of parse node
pythontech 0:5868e8752d44 2993 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
pythontech 0:5868e8752d44 2994 if (!MP_PARSE_NODE_IS_NULL(pns2->nodes[1])) {
pythontech 0:5868e8752d44 2995 goto not_an_instruction;
pythontech 0:5868e8752d44 2996 }
pythontech 0:5868e8752d44 2997 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
pythontech 0:5868e8752d44 2998 if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_power) {
pythontech 0:5868e8752d44 2999 goto not_an_instruction;
pythontech 0:5868e8752d44 3000 }
pythontech 0:5868e8752d44 3001 if (!MP_PARSE_NODE_IS_ID(pns2->nodes[0])) {
pythontech 0:5868e8752d44 3002 goto not_an_instruction;
pythontech 0:5868e8752d44 3003 }
pythontech 0:5868e8752d44 3004 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren)) {
pythontech 0:5868e8752d44 3005 goto not_an_instruction;
pythontech 0:5868e8752d44 3006 }
pythontech 0:5868e8752d44 3007 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[2]));
pythontech 0:5868e8752d44 3008
pythontech 0:5868e8752d44 3009 // parse node looks like an instruction
pythontech 0:5868e8752d44 3010 // get instruction name and args
pythontech 0:5868e8752d44 3011 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
pythontech 0:5868e8752d44 3012 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
pythontech 0:5868e8752d44 3013 mp_parse_node_t *pn_arg;
pythontech 0:5868e8752d44 3014 int n_args = mp_parse_node_extract_list(&pns2->nodes[0], PN_arglist, &pn_arg);
pythontech 0:5868e8752d44 3015
pythontech 0:5868e8752d44 3016 // emit instructions
pythontech 0:5868e8752d44 3017 if (op == MP_QSTR_label) {
pythontech 0:5868e8752d44 3018 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
pythontech 0:5868e8752d44 3019 compile_syntax_error(comp, nodes[i], "'label' requires 1 argument");
pythontech 0:5868e8752d44 3020 return;
pythontech 0:5868e8752d44 3021 }
pythontech 0:5868e8752d44 3022 uint lab = comp_next_label(comp);
pythontech 0:5868e8752d44 3023 if (pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3024 if (!EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]))) {
pythontech 0:5868e8752d44 3025 compile_syntax_error(comp, nodes[i], "label redefined");
pythontech 0:5868e8752d44 3026 return;
pythontech 0:5868e8752d44 3027 }
pythontech 0:5868e8752d44 3028 }
pythontech 0:5868e8752d44 3029 } else if (op == MP_QSTR_align) {
pythontech 0:5868e8752d44 3030 if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
pythontech 0:5868e8752d44 3031 compile_syntax_error(comp, nodes[i], "'align' requires 1 argument");
pythontech 0:5868e8752d44 3032 return;
pythontech 0:5868e8752d44 3033 }
pythontech 0:5868e8752d44 3034 if (pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3035 EMIT_INLINE_ASM_ARG(align, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));
pythontech 0:5868e8752d44 3036 }
pythontech 0:5868e8752d44 3037 } else if (op == MP_QSTR_data) {
pythontech 0:5868e8752d44 3038 if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
pythontech 0:5868e8752d44 3039 compile_syntax_error(comp, nodes[i], "'data' requires at least 2 arguments");
pythontech 0:5868e8752d44 3040 return;
pythontech 0:5868e8752d44 3041 }
pythontech 0:5868e8752d44 3042 if (pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3043 mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
pythontech 0:5868e8752d44 3044 for (uint j = 1; j < n_args; j++) {
pythontech 0:5868e8752d44 3045 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[j])) {
pythontech 0:5868e8752d44 3046 compile_syntax_error(comp, nodes[i], "'data' requires integer arguments");
pythontech 0:5868e8752d44 3047 return;
pythontech 0:5868e8752d44 3048 }
pythontech 0:5868e8752d44 3049 EMIT_INLINE_ASM_ARG(data, bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j]));
pythontech 0:5868e8752d44 3050 }
pythontech 0:5868e8752d44 3051 }
pythontech 0:5868e8752d44 3052 } else {
pythontech 0:5868e8752d44 3053 if (pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3054 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
pythontech 0:5868e8752d44 3055 }
pythontech 0:5868e8752d44 3056 }
pythontech 0:5868e8752d44 3057
pythontech 0:5868e8752d44 3058 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3059 pns = pns2; // this is the parse node that had the error
pythontech 0:5868e8752d44 3060 goto inline_asm_error;
pythontech 0:5868e8752d44 3061 }
pythontech 0:5868e8752d44 3062 }
pythontech 0:5868e8752d44 3063
pythontech 0:5868e8752d44 3064 if (comp->pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3065 EMIT_INLINE_ASM_ARG(end_pass, type_sig);
pythontech 0:5868e8752d44 3066 }
pythontech 0:5868e8752d44 3067
pythontech 0:5868e8752d44 3068 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3069 // inline assembler had an error; set line for its exception
pythontech 0:5868e8752d44 3070 inline_asm_error:
pythontech 0:5868e8752d44 3071 comp->compile_error_line = pns->source_line;
pythontech 0:5868e8752d44 3072 }
pythontech 0:5868e8752d44 3073 }
pythontech 0:5868e8752d44 3074 #endif
pythontech 0:5868e8752d44 3075
pythontech 0:5868e8752d44 3076 STATIC void scope_compute_things(scope_t *scope) {
pythontech 0:5868e8752d44 3077 // in Micro Python we put the *x parameter after all other parameters (except **y)
pythontech 0:5868e8752d44 3078 if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {
pythontech 0:5868e8752d44 3079 id_info_t *id_param = NULL;
pythontech 0:5868e8752d44 3080 for (int i = scope->id_info_len - 1; i >= 0; i--) {
pythontech 0:5868e8752d44 3081 id_info_t *id = &scope->id_info[i];
pythontech 0:5868e8752d44 3082 if (id->flags & ID_FLAG_IS_STAR_PARAM) {
pythontech 0:5868e8752d44 3083 if (id_param != NULL) {
pythontech 0:5868e8752d44 3084 // swap star param with last param
pythontech 0:5868e8752d44 3085 id_info_t temp = *id_param; *id_param = *id; *id = temp;
pythontech 0:5868e8752d44 3086 }
pythontech 0:5868e8752d44 3087 break;
pythontech 0:5868e8752d44 3088 } else if (id_param == NULL && id->flags == ID_FLAG_IS_PARAM) {
pythontech 0:5868e8752d44 3089 id_param = id;
pythontech 0:5868e8752d44 3090 }
pythontech 0:5868e8752d44 3091 }
pythontech 0:5868e8752d44 3092 }
pythontech 0:5868e8752d44 3093
pythontech 0:5868e8752d44 3094 // in functions, turn implicit globals into explicit globals
pythontech 0:5868e8752d44 3095 // compute the index of each local
pythontech 0:5868e8752d44 3096 scope->num_locals = 0;
pythontech 0:5868e8752d44 3097 for (int i = 0; i < scope->id_info_len; i++) {
pythontech 0:5868e8752d44 3098 id_info_t *id = &scope->id_info[i];
pythontech 0:5868e8752d44 3099 if (scope->kind == SCOPE_CLASS && id->qst == MP_QSTR___class__) {
pythontech 0:5868e8752d44 3100 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
pythontech 0:5868e8752d44 3101 continue;
pythontech 0:5868e8752d44 3102 }
pythontech 0:5868e8752d44 3103 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
pythontech 0:5868e8752d44 3104 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
pythontech 0:5868e8752d44 3105 }
pythontech 0:5868e8752d44 3106 // params always count for 1 local, even if they are a cell
pythontech 0:5868e8752d44 3107 if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) {
pythontech 0:5868e8752d44 3108 id->local_num = scope->num_locals++;
pythontech 0:5868e8752d44 3109 }
pythontech 0:5868e8752d44 3110 }
pythontech 0:5868e8752d44 3111
pythontech 0:5868e8752d44 3112 // compute the index of cell vars
pythontech 0:5868e8752d44 3113 for (int i = 0; i < scope->id_info_len; i++) {
pythontech 0:5868e8752d44 3114 id_info_t *id = &scope->id_info[i];
pythontech 0:5868e8752d44 3115 // in Micro Python the cells come right after the fast locals
pythontech 0:5868e8752d44 3116 // parameters are not counted here, since they remain at the start
pythontech 0:5868e8752d44 3117 // of the locals, even if they are cell vars
pythontech 0:5868e8752d44 3118 if (id->kind == ID_INFO_KIND_CELL && !(id->flags & ID_FLAG_IS_PARAM)) {
pythontech 0:5868e8752d44 3119 id->local_num = scope->num_locals;
pythontech 0:5868e8752d44 3120 scope->num_locals += 1;
pythontech 0:5868e8752d44 3121 }
pythontech 0:5868e8752d44 3122 }
pythontech 0:5868e8752d44 3123
pythontech 0:5868e8752d44 3124 // compute the index of free vars
pythontech 0:5868e8752d44 3125 // make sure they are in the order of the parent scope
pythontech 0:5868e8752d44 3126 if (scope->parent != NULL) {
pythontech 0:5868e8752d44 3127 int num_free = 0;
pythontech 0:5868e8752d44 3128 for (int i = 0; i < scope->parent->id_info_len; i++) {
pythontech 0:5868e8752d44 3129 id_info_t *id = &scope->parent->id_info[i];
pythontech 0:5868e8752d44 3130 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
pythontech 0:5868e8752d44 3131 for (int j = 0; j < scope->id_info_len; j++) {
pythontech 0:5868e8752d44 3132 id_info_t *id2 = &scope->id_info[j];
pythontech 0:5868e8752d44 3133 if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
pythontech 0:5868e8752d44 3134 assert(!(id2->flags & ID_FLAG_IS_PARAM)); // free vars should not be params
pythontech 0:5868e8752d44 3135 // in Micro Python the frees come first, before the params
pythontech 0:5868e8752d44 3136 id2->local_num = num_free;
pythontech 0:5868e8752d44 3137 num_free += 1;
pythontech 0:5868e8752d44 3138 }
pythontech 0:5868e8752d44 3139 }
pythontech 0:5868e8752d44 3140 }
pythontech 0:5868e8752d44 3141 }
pythontech 0:5868e8752d44 3142 // in Micro Python shift all other locals after the free locals
pythontech 0:5868e8752d44 3143 if (num_free > 0) {
pythontech 0:5868e8752d44 3144 for (int i = 0; i < scope->id_info_len; i++) {
pythontech 0:5868e8752d44 3145 id_info_t *id = &scope->id_info[i];
pythontech 0:5868e8752d44 3146 if (id->kind != ID_INFO_KIND_FREE || (id->flags & ID_FLAG_IS_PARAM)) {
pythontech 0:5868e8752d44 3147 id->local_num += num_free;
pythontech 0:5868e8752d44 3148 }
pythontech 0:5868e8752d44 3149 }
pythontech 0:5868e8752d44 3150 scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function
pythontech 0:5868e8752d44 3151 scope->num_locals += num_free;
pythontech 0:5868e8752d44 3152 }
pythontech 0:5868e8752d44 3153 }
pythontech 0:5868e8752d44 3154 }
pythontech 0:5868e8752d44 3155
pythontech 0:5868e8752d44 3156 #if !MICROPY_PERSISTENT_CODE_SAVE
pythontech 0:5868e8752d44 3157 STATIC
pythontech 0:5868e8752d44 3158 #endif
pythontech 0:5868e8752d44 3159 mp_raw_code_t *mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {
pythontech 0:5868e8752d44 3160 // put compiler state on the stack, it's relatively small
pythontech 0:5868e8752d44 3161 compiler_t comp_state = {0};
pythontech 0:5868e8752d44 3162 compiler_t *comp = &comp_state;
pythontech 0:5868e8752d44 3163
pythontech 0:5868e8752d44 3164 comp->source_file = source_file;
pythontech 0:5868e8752d44 3165 comp->is_repl = is_repl;
pythontech 0:5868e8752d44 3166
pythontech 0:5868e8752d44 3167 // create the module scope
pythontech 0:5868e8752d44 3168 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, parse_tree->root, emit_opt);
pythontech 0:5868e8752d44 3169
pythontech 0:5868e8752d44 3170 // create standard emitter; it's used at least for MP_PASS_SCOPE
pythontech 0:5868e8752d44 3171 emit_t *emit_bc = emit_bc_new();
pythontech 0:5868e8752d44 3172
pythontech 0:5868e8752d44 3173 // compile pass 1
pythontech 0:5868e8752d44 3174 comp->emit = emit_bc;
pythontech 0:5868e8752d44 3175 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3176 comp->emit_method_table = &emit_bc_method_table;
pythontech 0:5868e8752d44 3177 #endif
pythontech 0:5868e8752d44 3178 uint max_num_labels = 0;
pythontech 0:5868e8752d44 3179 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
pythontech 0:5868e8752d44 3180 if (false) {
pythontech 0:5868e8752d44 3181 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3182 } else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) {
pythontech 0:5868e8752d44 3183 compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);
pythontech 0:5868e8752d44 3184 #endif
pythontech 0:5868e8752d44 3185 } else {
pythontech 0:5868e8752d44 3186 compile_scope(comp, s, MP_PASS_SCOPE);
pythontech 0:5868e8752d44 3187 }
pythontech 0:5868e8752d44 3188
pythontech 0:5868e8752d44 3189 // update maximim number of labels needed
pythontech 0:5868e8752d44 3190 if (comp->next_label > max_num_labels) {
pythontech 0:5868e8752d44 3191 max_num_labels = comp->next_label;
pythontech 0:5868e8752d44 3192 }
pythontech 0:5868e8752d44 3193 }
pythontech 0:5868e8752d44 3194
pythontech 0:5868e8752d44 3195 // compute some things related to scope and identifiers
pythontech 0:5868e8752d44 3196 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
pythontech 0:5868e8752d44 3197 scope_compute_things(s);
pythontech 0:5868e8752d44 3198 }
pythontech 0:5868e8752d44 3199
pythontech 0:5868e8752d44 3200 // set max number of labels now that it's calculated
pythontech 0:5868e8752d44 3201 emit_bc_set_max_num_labels(emit_bc, max_num_labels);
pythontech 0:5868e8752d44 3202
pythontech 0:5868e8752d44 3203 // compile pass 2 and 3
pythontech 0:5868e8752d44 3204 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3205 emit_t *emit_native = NULL;
pythontech 0:5868e8752d44 3206 #endif
pythontech 0:5868e8752d44 3207 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3208 emit_inline_asm_t *emit_inline_thumb = NULL;
pythontech 0:5868e8752d44 3209 #endif
pythontech 0:5868e8752d44 3210 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
pythontech 0:5868e8752d44 3211 if (false) {
pythontech 0:5868e8752d44 3212 // dummy
pythontech 0:5868e8752d44 3213
pythontech 0:5868e8752d44 3214 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3215 } else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) {
pythontech 0:5868e8752d44 3216 // inline assembly for thumb
pythontech 0:5868e8752d44 3217 if (emit_inline_thumb == NULL) {
pythontech 0:5868e8752d44 3218 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
pythontech 0:5868e8752d44 3219 }
pythontech 0:5868e8752d44 3220 comp->emit = NULL;
pythontech 0:5868e8752d44 3221 comp->emit_inline_asm = emit_inline_thumb;
pythontech 0:5868e8752d44 3222 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
pythontech 0:5868e8752d44 3223 compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
pythontech 0:5868e8752d44 3224 if (comp->compile_error == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3225 compile_scope_inline_asm(comp, s, MP_PASS_EMIT);
pythontech 0:5868e8752d44 3226 }
pythontech 0:5868e8752d44 3227 #endif
pythontech 0:5868e8752d44 3228
pythontech 0:5868e8752d44 3229 } else {
pythontech 0:5868e8752d44 3230
pythontech 0:5868e8752d44 3231 // choose the emit type
pythontech 0:5868e8752d44 3232
pythontech 0:5868e8752d44 3233 switch (s->emit_options) {
pythontech 0:5868e8752d44 3234
pythontech 0:5868e8752d44 3235 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3236 case MP_EMIT_OPT_NATIVE_PYTHON:
pythontech 0:5868e8752d44 3237 case MP_EMIT_OPT_VIPER:
pythontech 0:5868e8752d44 3238 #if MICROPY_EMIT_X64
pythontech 0:5868e8752d44 3239 if (emit_native == NULL) {
pythontech 0:5868e8752d44 3240 emit_native = emit_native_x64_new(&comp->compile_error, max_num_labels);
pythontech 0:5868e8752d44 3241 }
pythontech 0:5868e8752d44 3242 comp->emit_method_table = &emit_native_x64_method_table;
pythontech 0:5868e8752d44 3243 #elif MICROPY_EMIT_X86
pythontech 0:5868e8752d44 3244 if (emit_native == NULL) {
pythontech 0:5868e8752d44 3245 emit_native = emit_native_x86_new(&comp->compile_error, max_num_labels);
pythontech 0:5868e8752d44 3246 }
pythontech 0:5868e8752d44 3247 comp->emit_method_table = &emit_native_x86_method_table;
pythontech 0:5868e8752d44 3248 #elif MICROPY_EMIT_THUMB
pythontech 0:5868e8752d44 3249 if (emit_native == NULL) {
pythontech 0:5868e8752d44 3250 emit_native = emit_native_thumb_new(&comp->compile_error, max_num_labels);
pythontech 0:5868e8752d44 3251 }
pythontech 0:5868e8752d44 3252 comp->emit_method_table = &emit_native_thumb_method_table;
pythontech 0:5868e8752d44 3253 #elif MICROPY_EMIT_ARM
pythontech 0:5868e8752d44 3254 if (emit_native == NULL) {
pythontech 0:5868e8752d44 3255 emit_native = emit_native_arm_new(&comp->compile_error, max_num_labels);
pythontech 0:5868e8752d44 3256 }
pythontech 0:5868e8752d44 3257 comp->emit_method_table = &emit_native_arm_method_table;
pythontech 0:5868e8752d44 3258 #endif
pythontech 0:5868e8752d44 3259 comp->emit = emit_native;
pythontech 0:5868e8752d44 3260 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0);
pythontech 0:5868e8752d44 3261 break;
pythontech 0:5868e8752d44 3262 #endif // MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3263
pythontech 0:5868e8752d44 3264 default:
pythontech 0:5868e8752d44 3265 comp->emit = emit_bc;
pythontech 0:5868e8752d44 3266 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3267 comp->emit_method_table = &emit_bc_method_table;
pythontech 0:5868e8752d44 3268 #endif
pythontech 0:5868e8752d44 3269 break;
pythontech 0:5868e8752d44 3270 }
pythontech 0:5868e8752d44 3271
pythontech 0:5868e8752d44 3272 // need a pass to compute stack size
pythontech 0:5868e8752d44 3273 compile_scope(comp, s, MP_PASS_STACK_SIZE);
pythontech 0:5868e8752d44 3274
pythontech 0:5868e8752d44 3275 // second last pass: compute code size
pythontech 0:5868e8752d44 3276 if (comp->compile_error == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3277 compile_scope(comp, s, MP_PASS_CODE_SIZE);
pythontech 0:5868e8752d44 3278 }
pythontech 0:5868e8752d44 3279
pythontech 0:5868e8752d44 3280 // final pass: emit code
pythontech 0:5868e8752d44 3281 if (comp->compile_error == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3282 compile_scope(comp, s, MP_PASS_EMIT);
pythontech 0:5868e8752d44 3283 }
pythontech 0:5868e8752d44 3284 }
pythontech 0:5868e8752d44 3285 }
pythontech 0:5868e8752d44 3286
pythontech 0:5868e8752d44 3287 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3288 // if there is no line number for the error then use the line
pythontech 0:5868e8752d44 3289 // number for the start of this scope
pythontech 0:5868e8752d44 3290 compile_error_set_line(comp, comp->scope_cur->pn);
pythontech 0:5868e8752d44 3291 // add a traceback to the exception using relevant source info
pythontech 0:5868e8752d44 3292 mp_obj_exception_add_traceback(comp->compile_error, comp->source_file,
pythontech 0:5868e8752d44 3293 comp->compile_error_line, comp->scope_cur->simple_name);
pythontech 0:5868e8752d44 3294 }
pythontech 0:5868e8752d44 3295
pythontech 0:5868e8752d44 3296 // free the emitters
pythontech 0:5868e8752d44 3297
pythontech 0:5868e8752d44 3298 emit_bc_free(emit_bc);
pythontech 0:5868e8752d44 3299 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3300 if (emit_native != NULL) {
pythontech 0:5868e8752d44 3301 #if MICROPY_EMIT_X64
pythontech 0:5868e8752d44 3302 emit_native_x64_free(emit_native);
pythontech 0:5868e8752d44 3303 #elif MICROPY_EMIT_X86
pythontech 0:5868e8752d44 3304 emit_native_x86_free(emit_native);
pythontech 0:5868e8752d44 3305 #elif MICROPY_EMIT_THUMB
pythontech 0:5868e8752d44 3306 emit_native_thumb_free(emit_native);
pythontech 0:5868e8752d44 3307 #elif MICROPY_EMIT_ARM
pythontech 0:5868e8752d44 3308 emit_native_arm_free(emit_native);
pythontech 0:5868e8752d44 3309 #endif
pythontech 0:5868e8752d44 3310 }
pythontech 0:5868e8752d44 3311 #endif
pythontech 0:5868e8752d44 3312 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3313 if (emit_inline_thumb != NULL) {
pythontech 0:5868e8752d44 3314 emit_inline_thumb_free(emit_inline_thumb);
pythontech 0:5868e8752d44 3315 }
pythontech 0:5868e8752d44 3316 #endif
pythontech 0:5868e8752d44 3317
pythontech 0:5868e8752d44 3318 // free the parse tree
pythontech 0:5868e8752d44 3319 mp_parse_tree_clear(parse_tree);
pythontech 0:5868e8752d44 3320
pythontech 0:5868e8752d44 3321 // free the scopes
pythontech 0:5868e8752d44 3322 mp_raw_code_t *outer_raw_code = module_scope->raw_code;
pythontech 0:5868e8752d44 3323 for (scope_t *s = module_scope; s;) {
pythontech 0:5868e8752d44 3324 scope_t *next = s->next;
pythontech 0:5868e8752d44 3325 scope_free(s);
pythontech 0:5868e8752d44 3326 s = next;
pythontech 0:5868e8752d44 3327 }
pythontech 0:5868e8752d44 3328
pythontech 0:5868e8752d44 3329 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3330 nlr_raise(comp->compile_error);
pythontech 0:5868e8752d44 3331 } else {
pythontech 0:5868e8752d44 3332 return outer_raw_code;
pythontech 0:5868e8752d44 3333 }
pythontech 0:5868e8752d44 3334 }
pythontech 0:5868e8752d44 3335
pythontech 0:5868e8752d44 3336 mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {
pythontech 0:5868e8752d44 3337 mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, emit_opt, is_repl);
pythontech 0:5868e8752d44 3338 // return function that executes the outer module
pythontech 0:5868e8752d44 3339 return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);
pythontech 0:5868e8752d44 3340 }
pythontech 0:5868e8752d44 3341
pythontech 0:5868e8752d44 3342 #endif // MICROPY_ENABLE_COMPILER