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:
Colin Hogben
Date:
Wed Apr 27 22:11:29 2016 +0100
Revision:
10:33521d742af1
Parent:
2:c89e95946844
Update README and version

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
Colin Hogben 2:c89e95946844 321 STATIC void c_assign_atom_expr(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];
Colin Hogben 2:c89e95946844 328 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_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 return;
pythontech 0:5868e8752d44 370
pythontech 0:5868e8752d44 371 cannot_assign:
pythontech 0:5868e8752d44 372 compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
pythontech 0:5868e8752d44 373 }
pythontech 0:5868e8752d44 374
pythontech 0:5868e8752d44 375 // 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 376 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 377 uint num_head = (node_head == MP_PARSE_NODE_NULL) ? 0 : 1;
pythontech 0:5868e8752d44 378
pythontech 0:5868e8752d44 379 // look for star expression
pythontech 0:5868e8752d44 380 uint have_star_index = -1;
pythontech 0:5868e8752d44 381 if (num_head != 0 && MP_PARSE_NODE_IS_STRUCT_KIND(node_head, PN_star_expr)) {
pythontech 0:5868e8752d44 382 EMIT_ARG(unpack_ex, 0, num_tail);
pythontech 0:5868e8752d44 383 have_star_index = 0;
pythontech 0:5868e8752d44 384 }
pythontech 0:5868e8752d44 385 for (uint i = 0; i < num_tail; i++) {
pythontech 0:5868e8752d44 386 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes_tail[i], PN_star_expr)) {
pythontech 0:5868e8752d44 387 if (have_star_index == (uint)-1) {
pythontech 0:5868e8752d44 388 EMIT_ARG(unpack_ex, num_head + i, num_tail - i - 1);
pythontech 0:5868e8752d44 389 have_star_index = num_head + i;
pythontech 0:5868e8752d44 390 } else {
pythontech 0:5868e8752d44 391 compile_syntax_error(comp, nodes_tail[i], "multiple *x in assignment");
pythontech 0:5868e8752d44 392 return;
pythontech 0:5868e8752d44 393 }
pythontech 0:5868e8752d44 394 }
pythontech 0:5868e8752d44 395 }
pythontech 0:5868e8752d44 396 if (have_star_index == (uint)-1) {
pythontech 0:5868e8752d44 397 EMIT_ARG(unpack_sequence, num_head + num_tail);
pythontech 0:5868e8752d44 398 }
pythontech 0:5868e8752d44 399 if (num_head != 0) {
pythontech 0:5868e8752d44 400 if (0 == have_star_index) {
pythontech 0:5868e8752d44 401 c_assign(comp, ((mp_parse_node_struct_t*)node_head)->nodes[0], ASSIGN_STORE);
pythontech 0:5868e8752d44 402 } else {
pythontech 0:5868e8752d44 403 c_assign(comp, node_head, ASSIGN_STORE);
pythontech 0:5868e8752d44 404 }
pythontech 0:5868e8752d44 405 }
pythontech 0:5868e8752d44 406 for (uint i = 0; i < num_tail; i++) {
pythontech 0:5868e8752d44 407 if (num_head + i == have_star_index) {
pythontech 0:5868e8752d44 408 c_assign(comp, ((mp_parse_node_struct_t*)nodes_tail[i])->nodes[0], ASSIGN_STORE);
pythontech 0:5868e8752d44 409 } else {
pythontech 0:5868e8752d44 410 c_assign(comp, nodes_tail[i], ASSIGN_STORE);
pythontech 0:5868e8752d44 411 }
pythontech 0:5868e8752d44 412 }
pythontech 0:5868e8752d44 413 }
pythontech 0:5868e8752d44 414
pythontech 0:5868e8752d44 415 // assigns top of stack to pn
pythontech 0:5868e8752d44 416 STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
pythontech 0:5868e8752d44 417 assert(!MP_PARSE_NODE_IS_NULL(pn));
pythontech 0:5868e8752d44 418 if (MP_PARSE_NODE_IS_LEAF(pn)) {
pythontech 0:5868e8752d44 419 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 420 qstr arg = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 421 switch (assign_kind) {
pythontech 0:5868e8752d44 422 case ASSIGN_STORE:
pythontech 0:5868e8752d44 423 case ASSIGN_AUG_STORE:
pythontech 0:5868e8752d44 424 compile_store_id(comp, arg);
pythontech 0:5868e8752d44 425 break;
pythontech 0:5868e8752d44 426 case ASSIGN_AUG_LOAD:
pythontech 0:5868e8752d44 427 default:
pythontech 0:5868e8752d44 428 compile_load_id(comp, arg);
pythontech 0:5868e8752d44 429 break;
pythontech 0:5868e8752d44 430 }
pythontech 0:5868e8752d44 431 } else {
pythontech 0:5868e8752d44 432 compile_syntax_error(comp, pn, "can't assign to literal");
pythontech 0:5868e8752d44 433 return;
pythontech 0:5868e8752d44 434 }
pythontech 0:5868e8752d44 435 } else {
pythontech 0:5868e8752d44 436 // pn must be a struct
pythontech 0:5868e8752d44 437 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 438 switch (MP_PARSE_NODE_STRUCT_KIND(pns)) {
Colin Hogben 2:c89e95946844 439 case PN_atom_expr_normal:
pythontech 0:5868e8752d44 440 // lhs is an index or attribute
Colin Hogben 2:c89e95946844 441 c_assign_atom_expr(comp, pns, assign_kind);
pythontech 0:5868e8752d44 442 break;
pythontech 0:5868e8752d44 443
pythontech 0:5868e8752d44 444 case PN_testlist_star_expr:
pythontech 0:5868e8752d44 445 case PN_exprlist:
pythontech 0:5868e8752d44 446 // lhs is a tuple
pythontech 0:5868e8752d44 447 if (assign_kind != ASSIGN_STORE) {
pythontech 0:5868e8752d44 448 goto bad_aug;
pythontech 0:5868e8752d44 449 }
pythontech 0:5868e8752d44 450 c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
pythontech 0:5868e8752d44 451 break;
pythontech 0:5868e8752d44 452
pythontech 0:5868e8752d44 453 case PN_atom_paren:
pythontech 0:5868e8752d44 454 // lhs is something in parenthesis
pythontech 0:5868e8752d44 455 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 456 // empty tuple
pythontech 0:5868e8752d44 457 goto cannot_assign;
pythontech 0:5868e8752d44 458 } else {
pythontech 0:5868e8752d44 459 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
pythontech 0:5868e8752d44 460 if (assign_kind != ASSIGN_STORE) {
pythontech 0:5868e8752d44 461 goto bad_aug;
pythontech 0:5868e8752d44 462 }
pythontech 0:5868e8752d44 463 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 464 goto testlist_comp;
pythontech 0:5868e8752d44 465 }
pythontech 0:5868e8752d44 466 break;
pythontech 0:5868e8752d44 467
pythontech 0:5868e8752d44 468 case PN_atom_bracket:
pythontech 0:5868e8752d44 469 // lhs is something in brackets
pythontech 0:5868e8752d44 470 if (assign_kind != ASSIGN_STORE) {
pythontech 0:5868e8752d44 471 goto bad_aug;
pythontech 0:5868e8752d44 472 }
pythontech 0:5868e8752d44 473 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 474 // empty list, assignment allowed
pythontech 0:5868e8752d44 475 c_assign_tuple(comp, MP_PARSE_NODE_NULL, 0, NULL);
pythontech 0:5868e8752d44 476 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
pythontech 0:5868e8752d44 477 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 478 goto testlist_comp;
pythontech 0:5868e8752d44 479 } else {
pythontech 0:5868e8752d44 480 // brackets around 1 item
pythontech 0:5868e8752d44 481 c_assign_tuple(comp, pns->nodes[0], 0, NULL);
pythontech 0:5868e8752d44 482 }
pythontech 0:5868e8752d44 483 break;
pythontech 0:5868e8752d44 484
pythontech 0:5868e8752d44 485 default:
pythontech 0:5868e8752d44 486 goto cannot_assign;
pythontech 0:5868e8752d44 487 }
pythontech 0:5868e8752d44 488 return;
pythontech 0:5868e8752d44 489
pythontech 0:5868e8752d44 490 testlist_comp:
pythontech 0:5868e8752d44 491 // lhs is a sequence
pythontech 0:5868e8752d44 492 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 493 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 494 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
pythontech 0:5868e8752d44 495 // sequence of one item, with trailing comma
pythontech 0:5868e8752d44 496 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
pythontech 0:5868e8752d44 497 c_assign_tuple(comp, pns->nodes[0], 0, NULL);
pythontech 0:5868e8752d44 498 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
pythontech 0:5868e8752d44 499 // sequence of many items
pythontech 0:5868e8752d44 500 uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns2);
pythontech 0:5868e8752d44 501 c_assign_tuple(comp, pns->nodes[0], n, pns2->nodes);
pythontech 0:5868e8752d44 502 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
pythontech 0:5868e8752d44 503 // TODO can we ever get here? can it be compiled?
pythontech 0:5868e8752d44 504 goto cannot_assign;
pythontech 0:5868e8752d44 505 } else {
pythontech 0:5868e8752d44 506 // sequence with 2 items
pythontech 0:5868e8752d44 507 goto sequence_with_2_items;
pythontech 0:5868e8752d44 508 }
pythontech 0:5868e8752d44 509 } else {
pythontech 0:5868e8752d44 510 // sequence with 2 items
pythontech 0:5868e8752d44 511 sequence_with_2_items:
pythontech 0:5868e8752d44 512 c_assign_tuple(comp, MP_PARSE_NODE_NULL, 2, pns->nodes);
pythontech 0:5868e8752d44 513 }
pythontech 0:5868e8752d44 514 return;
pythontech 0:5868e8752d44 515 }
pythontech 0:5868e8752d44 516 return;
pythontech 0:5868e8752d44 517
pythontech 0:5868e8752d44 518 cannot_assign:
pythontech 0:5868e8752d44 519 compile_syntax_error(comp, pn, "can't assign to expression");
pythontech 0:5868e8752d44 520 return;
pythontech 0:5868e8752d44 521
pythontech 0:5868e8752d44 522 bad_aug:
pythontech 0:5868e8752d44 523 compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
pythontech 0:5868e8752d44 524 }
pythontech 0:5868e8752d44 525
pythontech 0:5868e8752d44 526 // stuff for lambda and comprehensions and generators:
pythontech 0:5868e8752d44 527 // if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults
pythontech 0:5868e8752d44 528 // if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults
pythontech 0:5868e8752d44 529 // if both exist, the tuple is above the dictionary (ie the first pop gets the tuple)
pythontech 0:5868e8752d44 530 STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) {
pythontech 0:5868e8752d44 531 assert(n_pos_defaults >= 0);
pythontech 0:5868e8752d44 532 assert(n_kw_defaults >= 0);
pythontech 0:5868e8752d44 533
pythontech 0:5868e8752d44 534 // set flags
pythontech 0:5868e8752d44 535 if (n_kw_defaults > 0) {
pythontech 0:5868e8752d44 536 this_scope->scope_flags |= MP_SCOPE_FLAG_DEFKWARGS;
pythontech 0:5868e8752d44 537 }
pythontech 0:5868e8752d44 538 this_scope->num_def_pos_args = n_pos_defaults;
pythontech 0:5868e8752d44 539
pythontech 0:5868e8752d44 540 // make closed over variables, if any
pythontech 0:5868e8752d44 541 // ensure they are closed over in the order defined in the outer scope (mainly to agree with CPython)
pythontech 0:5868e8752d44 542 int nfree = 0;
pythontech 0:5868e8752d44 543 if (comp->scope_cur->kind != SCOPE_MODULE) {
pythontech 0:5868e8752d44 544 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
pythontech 0:5868e8752d44 545 id_info_t *id = &comp->scope_cur->id_info[i];
pythontech 0:5868e8752d44 546 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
pythontech 0:5868e8752d44 547 for (int j = 0; j < this_scope->id_info_len; j++) {
pythontech 0:5868e8752d44 548 id_info_t *id2 = &this_scope->id_info[j];
pythontech 0:5868e8752d44 549 if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
pythontech 0:5868e8752d44 550 // in Micro Python we load closures using LOAD_FAST
pythontech 0:5868e8752d44 551 EMIT_LOAD_FAST(id->qst, id->local_num);
pythontech 0:5868e8752d44 552 nfree += 1;
pythontech 0:5868e8752d44 553 }
pythontech 0:5868e8752d44 554 }
pythontech 0:5868e8752d44 555 }
pythontech 0:5868e8752d44 556 }
pythontech 0:5868e8752d44 557 }
pythontech 0:5868e8752d44 558
pythontech 0:5868e8752d44 559 // make the function/closure
pythontech 0:5868e8752d44 560 if (nfree == 0) {
pythontech 0:5868e8752d44 561 EMIT_ARG(make_function, this_scope, n_pos_defaults, n_kw_defaults);
pythontech 0:5868e8752d44 562 } else {
pythontech 0:5868e8752d44 563 EMIT_ARG(make_closure, this_scope, nfree, n_pos_defaults, n_kw_defaults);
pythontech 0:5868e8752d44 564 }
pythontech 0:5868e8752d44 565 }
pythontech 0:5868e8752d44 566
pythontech 0:5868e8752d44 567 STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 568 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)
pythontech 0:5868e8752d44 569 || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_star)) {
pythontech 0:5868e8752d44 570 comp->have_star = true;
pythontech 0:5868e8752d44 571 /* don't need to distinguish bare from named star
pythontech 0:5868e8752d44 572 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 573 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 574 // bare star
pythontech 0:5868e8752d44 575 } else {
pythontech 0:5868e8752d44 576 // named star
pythontech 0:5868e8752d44 577 }
pythontech 0:5868e8752d44 578 */
pythontech 0:5868e8752d44 579
pythontech 0:5868e8752d44 580 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)
pythontech 0:5868e8752d44 581 || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_dbl_star)) {
pythontech 0:5868e8752d44 582 // named double star
pythontech 0:5868e8752d44 583 // TODO do we need to do anything with this?
pythontech 0:5868e8752d44 584
pythontech 0:5868e8752d44 585 } else {
pythontech 0:5868e8752d44 586 mp_parse_node_t pn_id;
pythontech 0:5868e8752d44 587 mp_parse_node_t pn_colon;
pythontech 0:5868e8752d44 588 mp_parse_node_t pn_equal;
pythontech 0:5868e8752d44 589 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 590 // this parameter is just an id
pythontech 0:5868e8752d44 591
pythontech 0:5868e8752d44 592 pn_id = pn;
pythontech 0:5868e8752d44 593 pn_colon = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 594 pn_equal = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 595
pythontech 0:5868e8752d44 596 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
pythontech 0:5868e8752d44 597 // this parameter has a colon and/or equal specifier
pythontech 0:5868e8752d44 598
pythontech 0:5868e8752d44 599 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 600 pn_id = pns->nodes[0];
pythontech 0:5868e8752d44 601 pn_colon = pns->nodes[1];
pythontech 0:5868e8752d44 602 pn_equal = pns->nodes[2];
pythontech 0:5868e8752d44 603
pythontech 0:5868e8752d44 604 } else {
pythontech 0:5868e8752d44 605 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_name)); // should be
pythontech 0:5868e8752d44 606 // this parameter has an equal specifier
pythontech 0:5868e8752d44 607
pythontech 0:5868e8752d44 608 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 609 pn_id = pns->nodes[0];
pythontech 0:5868e8752d44 610 pn_equal = pns->nodes[1];
pythontech 0:5868e8752d44 611 }
pythontech 0:5868e8752d44 612
pythontech 0:5868e8752d44 613 if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
pythontech 0:5868e8752d44 614 // this parameter does not have a default value
pythontech 0:5868e8752d44 615
pythontech 0:5868e8752d44 616 // check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
pythontech 0:5868e8752d44 617 if (!comp->have_star && comp->num_default_params != 0) {
pythontech 0:5868e8752d44 618 compile_syntax_error(comp, pn, "non-default argument follows default argument");
pythontech 0:5868e8752d44 619 return;
pythontech 0:5868e8752d44 620 }
pythontech 0:5868e8752d44 621
pythontech 0:5868e8752d44 622 } else {
pythontech 0:5868e8752d44 623 // this parameter has a default value
pythontech 0:5868e8752d44 624 // in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
pythontech 0:5868e8752d44 625
pythontech 0:5868e8752d44 626 if (comp->have_star) {
pythontech 0:5868e8752d44 627 comp->num_dict_params += 1;
pythontech 0:5868e8752d44 628 // in Micro Python we put the default dict parameters into a dictionary using the bytecode
pythontech 0:5868e8752d44 629 if (comp->num_dict_params == 1) {
pythontech 0:5868e8752d44 630 // in Micro Python we put the default positional parameters into a tuple using the bytecode
pythontech 0:5868e8752d44 631 // we need to do this here before we start building the map for the default keywords
pythontech 0:5868e8752d44 632 if (comp->num_default_params > 0) {
pythontech 0:5868e8752d44 633 EMIT_ARG(build_tuple, comp->num_default_params);
pythontech 0:5868e8752d44 634 } else {
pythontech 0:5868e8752d44 635 EMIT(load_null); // sentinel indicating empty default positional args
pythontech 0:5868e8752d44 636 }
pythontech 0:5868e8752d44 637 // first default dict param, so make the map
pythontech 0:5868e8752d44 638 EMIT_ARG(build_map, 0);
pythontech 0:5868e8752d44 639 }
pythontech 0:5868e8752d44 640
pythontech 0:5868e8752d44 641 // compile value then key, then store it to the dict
pythontech 0:5868e8752d44 642 compile_node(comp, pn_equal);
pythontech 0:5868e8752d44 643 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pn_id));
pythontech 0:5868e8752d44 644 EMIT(store_map);
pythontech 0:5868e8752d44 645 } else {
pythontech 0:5868e8752d44 646 comp->num_default_params += 1;
pythontech 0:5868e8752d44 647 compile_node(comp, pn_equal);
pythontech 0:5868e8752d44 648 }
pythontech 0:5868e8752d44 649 }
pythontech 0:5868e8752d44 650
pythontech 0:5868e8752d44 651 // TODO pn_colon not implemented
pythontech 0:5868e8752d44 652 (void)pn_colon;
pythontech 0:5868e8752d44 653 }
pythontech 0:5868e8752d44 654 }
pythontech 0:5868e8752d44 655
pythontech 0:5868e8752d44 656 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 657 // When we call compile_funcdef_lambdef_param below it can compile an arbitrary
pythontech 0:5868e8752d44 658 // expression for default arguments, which may contain a lambda. The lambda will
pythontech 0:5868e8752d44 659 // call here in a nested way, so we must save and restore the relevant state.
pythontech 0:5868e8752d44 660 bool orig_have_star = comp->have_star;
pythontech 0:5868e8752d44 661 uint16_t orig_num_dict_params = comp->num_dict_params;
pythontech 0:5868e8752d44 662 uint16_t orig_num_default_params = comp->num_default_params;
pythontech 0:5868e8752d44 663
pythontech 0:5868e8752d44 664 // compile default parameters
pythontech 0:5868e8752d44 665 comp->have_star = false;
pythontech 0:5868e8752d44 666 comp->num_dict_params = 0;
pythontech 0:5868e8752d44 667 comp->num_default_params = 0;
pythontech 0:5868e8752d44 668 apply_to_single_or_list(comp, pn_params, pn_list_kind, compile_funcdef_lambdef_param);
pythontech 0:5868e8752d44 669
pythontech 0:5868e8752d44 670 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 671 return;
pythontech 0:5868e8752d44 672 }
pythontech 0:5868e8752d44 673
pythontech 0:5868e8752d44 674 // in Micro Python we put the default positional parameters into a tuple using the bytecode
pythontech 0:5868e8752d44 675 // the default keywords args may have already made the tuple; if not, do it now
pythontech 0:5868e8752d44 676 if (comp->num_default_params > 0 && comp->num_dict_params == 0) {
pythontech 0:5868e8752d44 677 EMIT_ARG(build_tuple, comp->num_default_params);
pythontech 0:5868e8752d44 678 EMIT(load_null); // sentinel indicating empty default keyword args
pythontech 0:5868e8752d44 679 }
pythontech 0:5868e8752d44 680
pythontech 0:5868e8752d44 681 // make the function
pythontech 0:5868e8752d44 682 close_over_variables_etc(comp, scope, comp->num_default_params, comp->num_dict_params);
pythontech 0:5868e8752d44 683
pythontech 0:5868e8752d44 684 // restore state
pythontech 0:5868e8752d44 685 comp->have_star = orig_have_star;
pythontech 0:5868e8752d44 686 comp->num_dict_params = orig_num_dict_params;
pythontech 0:5868e8752d44 687 comp->num_default_params = orig_num_default_params;
pythontech 0:5868e8752d44 688 }
pythontech 0:5868e8752d44 689
pythontech 0:5868e8752d44 690 // leaves function object on stack
pythontech 0:5868e8752d44 691 // returns function name
pythontech 0:5868e8752d44 692 STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
pythontech 0:5868e8752d44 693 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 694 // create a new scope for this function
pythontech 0:5868e8752d44 695 scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options);
pythontech 0:5868e8752d44 696 // store the function scope so the compiling function can use it at each pass
pythontech 0:5868e8752d44 697 pns->nodes[4] = (mp_parse_node_t)s;
pythontech 0:5868e8752d44 698 }
pythontech 0:5868e8752d44 699
pythontech 0:5868e8752d44 700 // get the scope for this function
pythontech 0:5868e8752d44 701 scope_t *fscope = (scope_t*)pns->nodes[4];
pythontech 0:5868e8752d44 702
pythontech 0:5868e8752d44 703 // compile the function definition
pythontech 0:5868e8752d44 704 compile_funcdef_lambdef(comp, fscope, pns->nodes[1], PN_typedargslist);
pythontech 0:5868e8752d44 705
pythontech 0:5868e8752d44 706 // return its name (the 'f' in "def f(...):")
pythontech 0:5868e8752d44 707 return fscope->simple_name;
pythontech 0:5868e8752d44 708 }
pythontech 0:5868e8752d44 709
pythontech 0:5868e8752d44 710 // leaves class object on stack
pythontech 0:5868e8752d44 711 // returns class name
pythontech 0:5868e8752d44 712 STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) {
pythontech 0:5868e8752d44 713 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 714 // create a new scope for this class
pythontech 0:5868e8752d44 715 scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options);
pythontech 0:5868e8752d44 716 // store the class scope so the compiling function can use it at each pass
pythontech 0:5868e8752d44 717 pns->nodes[3] = (mp_parse_node_t)s;
pythontech 0:5868e8752d44 718 }
pythontech 0:5868e8752d44 719
pythontech 0:5868e8752d44 720 EMIT(load_build_class);
pythontech 0:5868e8752d44 721
pythontech 0:5868e8752d44 722 // scope for this class
pythontech 0:5868e8752d44 723 scope_t *cscope = (scope_t*)pns->nodes[3];
pythontech 0:5868e8752d44 724
pythontech 0:5868e8752d44 725 // compile the class
pythontech 0:5868e8752d44 726 close_over_variables_etc(comp, cscope, 0, 0);
pythontech 0:5868e8752d44 727
pythontech 0:5868e8752d44 728 // get its name
pythontech 0:5868e8752d44 729 EMIT_ARG(load_const_str, cscope->simple_name);
pythontech 0:5868e8752d44 730
pythontech 0:5868e8752d44 731 // nodes[1] has parent classes, if any
pythontech 0:5868e8752d44 732 // empty parenthesis (eg class C():) gets here as an empty PN_classdef_2 and needs special handling
pythontech 0:5868e8752d44 733 mp_parse_node_t parents = pns->nodes[1];
pythontech 0:5868e8752d44 734 if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
pythontech 0:5868e8752d44 735 parents = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 736 }
pythontech 0:5868e8752d44 737 comp->func_arg_is_super = false;
pythontech 0:5868e8752d44 738 compile_trailer_paren_helper(comp, parents, false, 2);
pythontech 0:5868e8752d44 739
pythontech 0:5868e8752d44 740 // return its name (the 'C' in class C(...):")
pythontech 0:5868e8752d44 741 return cscope->simple_name;
pythontech 0:5868e8752d44 742 }
pythontech 0:5868e8752d44 743
pythontech 0:5868e8752d44 744 // returns true if it was a built-in decorator (even if the built-in had an error)
pythontech 0:5868e8752d44 745 STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_node_t *name_nodes, uint *emit_options) {
pythontech 0:5868e8752d44 746 if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) {
pythontech 0:5868e8752d44 747 return false;
pythontech 0:5868e8752d44 748 }
pythontech 0:5868e8752d44 749
pythontech 0:5868e8752d44 750 if (name_len != 2) {
pythontech 0:5868e8752d44 751 compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator");
pythontech 0:5868e8752d44 752 return true;
pythontech 0:5868e8752d44 753 }
pythontech 0:5868e8752d44 754
pythontech 0:5868e8752d44 755 qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]);
pythontech 0:5868e8752d44 756 if (attr == MP_QSTR_bytecode) {
pythontech 0:5868e8752d44 757 *emit_options = MP_EMIT_OPT_BYTECODE;
pythontech 0:5868e8752d44 758 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 759 } else if (attr == MP_QSTR_native) {
pythontech 0:5868e8752d44 760 *emit_options = MP_EMIT_OPT_NATIVE_PYTHON;
pythontech 0:5868e8752d44 761 } else if (attr == MP_QSTR_viper) {
pythontech 0:5868e8752d44 762 *emit_options = MP_EMIT_OPT_VIPER;
pythontech 0:5868e8752d44 763 #endif
pythontech 0:5868e8752d44 764 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 765 } else if (attr == MP_QSTR_asm_thumb) {
pythontech 0:5868e8752d44 766 *emit_options = MP_EMIT_OPT_ASM_THUMB;
pythontech 0:5868e8752d44 767 #endif
pythontech 0:5868e8752d44 768 } else {
pythontech 0:5868e8752d44 769 compile_syntax_error(comp, name_nodes[1], "invalid micropython decorator");
pythontech 0:5868e8752d44 770 }
pythontech 0:5868e8752d44 771
pythontech 0:5868e8752d44 772 return true;
pythontech 0:5868e8752d44 773 }
pythontech 0:5868e8752d44 774
pythontech 0:5868e8752d44 775 STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 776 // get the list of decorators
pythontech 0:5868e8752d44 777 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 778 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_decorators, &nodes);
pythontech 0:5868e8752d44 779
pythontech 0:5868e8752d44 780 // inherit emit options for this function/class definition
pythontech 0:5868e8752d44 781 uint emit_options = comp->scope_cur->emit_options;
pythontech 0:5868e8752d44 782
pythontech 0:5868e8752d44 783 // compile each decorator
pythontech 0:5868e8752d44 784 int num_built_in_decorators = 0;
pythontech 0:5868e8752d44 785 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 786 assert(MP_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be
pythontech 0:5868e8752d44 787 mp_parse_node_struct_t *pns_decorator = (mp_parse_node_struct_t*)nodes[i];
pythontech 0:5868e8752d44 788
pythontech 0:5868e8752d44 789 // nodes[0] contains the decorator function, which is a dotted name
pythontech 0:5868e8752d44 790 mp_parse_node_t *name_nodes;
pythontech 0:5868e8752d44 791 int name_len = mp_parse_node_extract_list(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes);
pythontech 0:5868e8752d44 792
pythontech 0:5868e8752d44 793 // check for built-in decorators
pythontech 0:5868e8752d44 794 if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) {
pythontech 0:5868e8752d44 795 // this was a built-in
pythontech 0:5868e8752d44 796 num_built_in_decorators += 1;
pythontech 0:5868e8752d44 797
pythontech 0:5868e8752d44 798 } else {
pythontech 0:5868e8752d44 799 // not a built-in, compile normally
pythontech 0:5868e8752d44 800
pythontech 0:5868e8752d44 801 // compile the decorator function
pythontech 0:5868e8752d44 802 compile_node(comp, name_nodes[0]);
pythontech 0:5868e8752d44 803 for (int j = 1; j < name_len; j++) {
pythontech 0:5868e8752d44 804 assert(MP_PARSE_NODE_IS_ID(name_nodes[j])); // should be
pythontech 0:5868e8752d44 805 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(name_nodes[j]));
pythontech 0:5868e8752d44 806 }
pythontech 0:5868e8752d44 807
pythontech 0:5868e8752d44 808 // nodes[1] contains arguments to the decorator function, if any
pythontech 0:5868e8752d44 809 if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
pythontech 0:5868e8752d44 810 // call the decorator function with the arguments in nodes[1]
pythontech 0:5868e8752d44 811 comp->func_arg_is_super = false;
pythontech 0:5868e8752d44 812 compile_node(comp, pns_decorator->nodes[1]);
pythontech 0:5868e8752d44 813 }
pythontech 0:5868e8752d44 814 }
pythontech 0:5868e8752d44 815 }
pythontech 0:5868e8752d44 816
Colin Hogben 2:c89e95946844 817 // compile the body (funcdef, async funcdef or classdef) and get its name
pythontech 0:5868e8752d44 818 mp_parse_node_struct_t *pns_body = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 819 qstr body_name = 0;
pythontech 0:5868e8752d44 820 if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) {
pythontech 0:5868e8752d44 821 body_name = compile_funcdef_helper(comp, pns_body, emit_options);
Colin Hogben 2:c89e95946844 822 #if MICROPY_PY_ASYNC_AWAIT
Colin Hogben 2:c89e95946844 823 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_async_funcdef) {
Colin Hogben 2:c89e95946844 824 assert(MP_PARSE_NODE_IS_STRUCT(pns_body->nodes[0]));
Colin Hogben 2:c89e95946844 825 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns_body->nodes[0];
Colin Hogben 2:c89e95946844 826 body_name = compile_funcdef_helper(comp, pns0, emit_options);
Colin Hogben 2:c89e95946844 827 scope_t *fscope = (scope_t*)pns0->nodes[4];
Colin Hogben 2:c89e95946844 828 fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Colin Hogben 2:c89e95946844 829 #endif
pythontech 0:5868e8752d44 830 } else {
pythontech 0:5868e8752d44 831 assert(MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef); // should be
pythontech 0:5868e8752d44 832 body_name = compile_classdef_helper(comp, pns_body, emit_options);
pythontech 0:5868e8752d44 833 }
pythontech 0:5868e8752d44 834
pythontech 0:5868e8752d44 835 // call each decorator
pythontech 0:5868e8752d44 836 for (int i = 0; i < n - num_built_in_decorators; i++) {
pythontech 0:5868e8752d44 837 EMIT_ARG(call_function, 1, 0, 0);
pythontech 0:5868e8752d44 838 }
pythontech 0:5868e8752d44 839
pythontech 0:5868e8752d44 840 // store func/class object into name
pythontech 0:5868e8752d44 841 compile_store_id(comp, body_name);
pythontech 0:5868e8752d44 842 }
pythontech 0:5868e8752d44 843
pythontech 0:5868e8752d44 844 STATIC void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 845 qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options);
pythontech 0:5868e8752d44 846 // store function object into function name
pythontech 0:5868e8752d44 847 compile_store_id(comp, fname);
pythontech 0:5868e8752d44 848 }
pythontech 0:5868e8752d44 849
pythontech 0:5868e8752d44 850 STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 851 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 852 compile_delete_id(comp, MP_PARSE_NODE_LEAF_ARG(pn));
Colin Hogben 2:c89e95946844 853 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_expr_normal)) {
pythontech 0:5868e8752d44 854 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 855
Colin Hogben 2:c89e95946844 856 compile_node(comp, pns->nodes[0]); // base of the atom_expr_normal node
pythontech 0:5868e8752d44 857
pythontech 0:5868e8752d44 858 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 859 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
Colin Hogben 2:c89e95946844 860 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_atom_expr_trailers) {
pythontech 0:5868e8752d44 861 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
pythontech 0:5868e8752d44 862 for (int i = 0; i < n - 1; i++) {
pythontech 0:5868e8752d44 863 compile_node(comp, pns1->nodes[i]);
pythontech 0:5868e8752d44 864 }
pythontech 0:5868e8752d44 865 assert(MP_PARSE_NODE_IS_STRUCT(pns1->nodes[n - 1]));
pythontech 0:5868e8752d44 866 pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
pythontech 0:5868e8752d44 867 }
pythontech 0:5868e8752d44 868 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
pythontech 0:5868e8752d44 869 compile_node(comp, pns1->nodes[0]);
pythontech 0:5868e8752d44 870 EMIT(delete_subscr);
pythontech 0:5868e8752d44 871 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
pythontech 0:5868e8752d44 872 assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
pythontech 0:5868e8752d44 873 EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
pythontech 0:5868e8752d44 874 } else {
pythontech 0:5868e8752d44 875 goto cannot_delete;
pythontech 0:5868e8752d44 876 }
pythontech 0:5868e8752d44 877 } else {
pythontech 0:5868e8752d44 878 goto cannot_delete;
pythontech 0:5868e8752d44 879 }
pythontech 0:5868e8752d44 880
pythontech 0:5868e8752d44 881 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
pythontech 0:5868e8752d44 882 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
pythontech 0:5868e8752d44 883 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 884 goto cannot_delete;
pythontech 0:5868e8752d44 885 } else {
pythontech 0:5868e8752d44 886 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_testlist_comp));
pythontech 0:5868e8752d44 887 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 888 // TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
pythontech 0:5868e8752d44 889
pythontech 0:5868e8752d44 890 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 891 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 892 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3b) {
pythontech 0:5868e8752d44 893 // sequence of one item, with trailing comma
pythontech 0:5868e8752d44 894 assert(MP_PARSE_NODE_IS_NULL(pns1->nodes[0]));
pythontech 0:5868e8752d44 895 c_del_stmt(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 896 } else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_testlist_comp_3c) {
pythontech 0:5868e8752d44 897 // sequence of many items
pythontech 0:5868e8752d44 898 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1);
pythontech 0:5868e8752d44 899 c_del_stmt(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 900 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 901 c_del_stmt(comp, pns1->nodes[i]);
pythontech 0:5868e8752d44 902 }
pythontech 0:5868e8752d44 903 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
pythontech 0:5868e8752d44 904 // TODO not implemented; can't del comprehension? can we get here?
pythontech 0:5868e8752d44 905 goto cannot_delete;
pythontech 0:5868e8752d44 906 } else {
pythontech 0:5868e8752d44 907 // sequence with 2 items
pythontech 0:5868e8752d44 908 goto sequence_with_2_items;
pythontech 0:5868e8752d44 909 }
pythontech 0:5868e8752d44 910 } else {
pythontech 0:5868e8752d44 911 // sequence with 2 items
pythontech 0:5868e8752d44 912 sequence_with_2_items:
pythontech 0:5868e8752d44 913 c_del_stmt(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 914 c_del_stmt(comp, pns->nodes[1]);
pythontech 0:5868e8752d44 915 }
pythontech 0:5868e8752d44 916 }
pythontech 0:5868e8752d44 917 } else {
pythontech 0:5868e8752d44 918 // some arbitrary statment that we can't delete (eg del 1)
pythontech 0:5868e8752d44 919 goto cannot_delete;
pythontech 0:5868e8752d44 920 }
pythontech 0:5868e8752d44 921
pythontech 0:5868e8752d44 922 return;
pythontech 0:5868e8752d44 923
pythontech 0:5868e8752d44 924 cannot_delete:
pythontech 0:5868e8752d44 925 compile_syntax_error(comp, (mp_parse_node_t)pn, "can't delete expression");
pythontech 0:5868e8752d44 926 }
pythontech 0:5868e8752d44 927
pythontech 0:5868e8752d44 928 STATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 929 apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt);
pythontech 0:5868e8752d44 930 }
pythontech 0:5868e8752d44 931
pythontech 0:5868e8752d44 932 STATIC void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 933 if (comp->break_label == 0) {
pythontech 0:5868e8752d44 934 compile_syntax_error(comp, (mp_parse_node_t)pns, "'break' outside loop");
pythontech 0:5868e8752d44 935 }
pythontech 0:5868e8752d44 936 assert(comp->cur_except_level >= comp->break_continue_except_level);
pythontech 0:5868e8752d44 937 EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
pythontech 0:5868e8752d44 938 }
pythontech 0:5868e8752d44 939
pythontech 0:5868e8752d44 940 STATIC void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 941 if (comp->continue_label == 0) {
pythontech 0:5868e8752d44 942 compile_syntax_error(comp, (mp_parse_node_t)pns, "'continue' outside loop");
pythontech 0:5868e8752d44 943 }
pythontech 0:5868e8752d44 944 assert(comp->cur_except_level >= comp->break_continue_except_level);
pythontech 0:5868e8752d44 945 EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
pythontech 0:5868e8752d44 946 }
pythontech 0:5868e8752d44 947
pythontech 0:5868e8752d44 948 STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 949 if (comp->scope_cur->kind != SCOPE_FUNCTION) {
pythontech 0:5868e8752d44 950 compile_syntax_error(comp, (mp_parse_node_t)pns, "'return' outside function");
pythontech 0:5868e8752d44 951 return;
pythontech 0:5868e8752d44 952 }
pythontech 0:5868e8752d44 953 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 954 // no argument to 'return', so return None
pythontech 0:5868e8752d44 955 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 956 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
pythontech 0:5868e8752d44 957 // special case when returning an if-expression; to match CPython optimisation
pythontech 0:5868e8752d44 958 mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 959 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];
pythontech 0:5868e8752d44 960
pythontech 0:5868e8752d44 961 uint l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 962 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
pythontech 0:5868e8752d44 963 compile_node(comp, pns_test_if_expr->nodes[0]); // success value
pythontech 0:5868e8752d44 964 EMIT(return_value);
pythontech 0:5868e8752d44 965 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 966 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
pythontech 0:5868e8752d44 967 } else {
pythontech 0:5868e8752d44 968 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 969 }
pythontech 0:5868e8752d44 970 EMIT(return_value);
pythontech 0:5868e8752d44 971 }
pythontech 0:5868e8752d44 972
pythontech 0:5868e8752d44 973 STATIC void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 974 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 975 EMIT(pop_top);
pythontech 0:5868e8752d44 976 }
pythontech 0:5868e8752d44 977
pythontech 0:5868e8752d44 978 STATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 979 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 980 // raise
pythontech 0:5868e8752d44 981 EMIT_ARG(raise_varargs, 0);
pythontech 0:5868e8752d44 982 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_raise_stmt_arg)) {
pythontech 0:5868e8752d44 983 // raise x from y
pythontech 0:5868e8752d44 984 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 985 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 986 compile_node(comp, pns->nodes[1]);
pythontech 0:5868e8752d44 987 EMIT_ARG(raise_varargs, 2);
pythontech 0:5868e8752d44 988 } else {
pythontech 0:5868e8752d44 989 // raise x
pythontech 0:5868e8752d44 990 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 991 EMIT_ARG(raise_varargs, 1);
pythontech 0:5868e8752d44 992 }
pythontech 0:5868e8752d44 993 }
pythontech 0:5868e8752d44 994
pythontech 0:5868e8752d44 995 // q_base holds the base of the name
pythontech 0:5868e8752d44 996 // eg a -> q_base=a
pythontech 0:5868e8752d44 997 // a.b.c -> q_base=a
pythontech 0:5868e8752d44 998 STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) {
pythontech 0:5868e8752d44 999 bool is_as = false;
pythontech 0:5868e8752d44 1000 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) {
pythontech 0:5868e8752d44 1001 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 1002 // a name of the form x as y; unwrap it
pythontech 0:5868e8752d44 1003 *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
pythontech 0:5868e8752d44 1004 pn = pns->nodes[0];
pythontech 0:5868e8752d44 1005 is_as = true;
pythontech 0:5868e8752d44 1006 }
pythontech 0:5868e8752d44 1007 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 1008 // empty name (eg, from . import x)
pythontech 0:5868e8752d44 1009 *q_base = MP_QSTR_;
pythontech 0:5868e8752d44 1010 EMIT_ARG(import_name, MP_QSTR_); // import the empty string
pythontech 0:5868e8752d44 1011 } else if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 1012 // just a simple name
pythontech 0:5868e8752d44 1013 qstr q_full = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 1014 if (!is_as) {
pythontech 0:5868e8752d44 1015 *q_base = q_full;
pythontech 0:5868e8752d44 1016 }
pythontech 0:5868e8752d44 1017 EMIT_ARG(import_name, q_full);
pythontech 0:5868e8752d44 1018 } else {
pythontech 0:5868e8752d44 1019 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_name)); // should be
pythontech 0:5868e8752d44 1020 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 1021 {
pythontech 0:5868e8752d44 1022 // a name of the form a.b.c
pythontech 0:5868e8752d44 1023 if (!is_as) {
pythontech 0:5868e8752d44 1024 *q_base = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 1025 }
pythontech 0:5868e8752d44 1026 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1027 int len = n - 1;
pythontech 0:5868e8752d44 1028 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1029 len += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
pythontech 0:5868e8752d44 1030 }
pythontech 0:5868e8752d44 1031 byte *q_ptr;
pythontech 0:5868e8752d44 1032 byte *str_dest = qstr_build_start(len, &q_ptr);
pythontech 0:5868e8752d44 1033 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1034 if (i > 0) {
pythontech 0:5868e8752d44 1035 *str_dest++ = '.';
pythontech 0:5868e8752d44 1036 }
pythontech 0:5868e8752d44 1037 size_t str_src_len;
pythontech 0:5868e8752d44 1038 const byte *str_src = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &str_src_len);
pythontech 0:5868e8752d44 1039 memcpy(str_dest, str_src, str_src_len);
pythontech 0:5868e8752d44 1040 str_dest += str_src_len;
pythontech 0:5868e8752d44 1041 }
pythontech 0:5868e8752d44 1042 qstr q_full = qstr_build_end(q_ptr);
pythontech 0:5868e8752d44 1043 EMIT_ARG(import_name, q_full);
pythontech 0:5868e8752d44 1044 if (is_as) {
pythontech 0:5868e8752d44 1045 for (int i = 1; i < n; i++) {
pythontech 0:5868e8752d44 1046 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
pythontech 0:5868e8752d44 1047 }
pythontech 0:5868e8752d44 1048 }
pythontech 0:5868e8752d44 1049 }
pythontech 0:5868e8752d44 1050 }
pythontech 0:5868e8752d44 1051 }
pythontech 0:5868e8752d44 1052
pythontech 0:5868e8752d44 1053 STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 1054 EMIT_ARG(load_const_small_int, 0); // level 0 import
pythontech 0:5868e8752d44 1055 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything
pythontech 0:5868e8752d44 1056 qstr q_base;
pythontech 0:5868e8752d44 1057 do_import_name(comp, pn, &q_base);
pythontech 0:5868e8752d44 1058 compile_store_id(comp, q_base);
pythontech 0:5868e8752d44 1059 }
pythontech 0:5868e8752d44 1060
pythontech 0:5868e8752d44 1061 STATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1062 apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name);
pythontech 0:5868e8752d44 1063 }
pythontech 0:5868e8752d44 1064
pythontech 0:5868e8752d44 1065 STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1066 mp_parse_node_t pn_import_source = pns->nodes[0];
pythontech 0:5868e8752d44 1067
pythontech 0:5868e8752d44 1068 // extract the preceeding .'s (if any) for a relative import, to compute the import level
pythontech 0:5868e8752d44 1069 uint import_level = 0;
pythontech 0:5868e8752d44 1070 do {
pythontech 0:5868e8752d44 1071 mp_parse_node_t pn_rel;
pythontech 0:5868e8752d44 1072 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 1073 // This covers relative imports with dots only like "from .. import"
pythontech 0:5868e8752d44 1074 pn_rel = pn_import_source;
pythontech 0:5868e8752d44 1075 pn_import_source = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 1076 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_import_source, PN_import_from_2b)) {
pythontech 0:5868e8752d44 1077 // This covers relative imports starting with dot(s) like "from .foo import"
pythontech 0:5868e8752d44 1078 mp_parse_node_struct_t *pns_2b = (mp_parse_node_struct_t*)pn_import_source;
pythontech 0:5868e8752d44 1079 pn_rel = pns_2b->nodes[0];
pythontech 0:5868e8752d44 1080 pn_import_source = pns_2b->nodes[1];
pythontech 0:5868e8752d44 1081 assert(!MP_PARSE_NODE_IS_NULL(pn_import_source)); // should not be
pythontech 0:5868e8752d44 1082 } else {
pythontech 0:5868e8752d44 1083 // Not a relative import
pythontech 0:5868e8752d44 1084 break;
pythontech 0:5868e8752d44 1085 }
pythontech 0:5868e8752d44 1086
pythontech 0:5868e8752d44 1087 // get the list of . and/or ...'s
pythontech 0:5868e8752d44 1088 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 1089 int n = mp_parse_node_extract_list(&pn_rel, PN_one_or_more_period_or_ellipsis, &nodes);
pythontech 0:5868e8752d44 1090
pythontech 0:5868e8752d44 1091 // count the total number of .'s
pythontech 0:5868e8752d44 1092 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1093 if (MP_PARSE_NODE_IS_TOKEN_KIND(nodes[i], MP_TOKEN_DEL_PERIOD)) {
pythontech 0:5868e8752d44 1094 import_level++;
pythontech 0:5868e8752d44 1095 } else {
pythontech 0:5868e8752d44 1096 // should be an MP_TOKEN_ELLIPSIS
pythontech 0:5868e8752d44 1097 import_level += 3;
pythontech 0:5868e8752d44 1098 }
pythontech 0:5868e8752d44 1099 }
pythontech 0:5868e8752d44 1100 } while (0);
pythontech 0:5868e8752d44 1101
pythontech 0:5868e8752d44 1102 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
pythontech 0:5868e8752d44 1103 EMIT_ARG(load_const_small_int, import_level);
pythontech 0:5868e8752d44 1104
pythontech 0:5868e8752d44 1105 // build the "fromlist" tuple
pythontech 0:5868e8752d44 1106 EMIT_ARG(load_const_str, MP_QSTR__star_);
pythontech 0:5868e8752d44 1107 EMIT_ARG(build_tuple, 1);
pythontech 0:5868e8752d44 1108
pythontech 0:5868e8752d44 1109 // do the import
pythontech 0:5868e8752d44 1110 qstr dummy_q;
pythontech 0:5868e8752d44 1111 do_import_name(comp, pn_import_source, &dummy_q);
pythontech 0:5868e8752d44 1112 EMIT(import_star);
pythontech 0:5868e8752d44 1113
pythontech 0:5868e8752d44 1114 } else {
pythontech 0:5868e8752d44 1115 EMIT_ARG(load_const_small_int, import_level);
pythontech 0:5868e8752d44 1116
pythontech 0:5868e8752d44 1117 // build the "fromlist" tuple
pythontech 0:5868e8752d44 1118 mp_parse_node_t *pn_nodes;
pythontech 0:5868e8752d44 1119 int n = mp_parse_node_extract_list(&pns->nodes[1], PN_import_as_names, &pn_nodes);
pythontech 0:5868e8752d44 1120 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1121 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
pythontech 0:5868e8752d44 1122 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
pythontech 0:5868e8752d44 1123 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
pythontech 0:5868e8752d44 1124 EMIT_ARG(load_const_str, id2);
pythontech 0:5868e8752d44 1125 }
pythontech 0:5868e8752d44 1126 EMIT_ARG(build_tuple, n);
pythontech 0:5868e8752d44 1127
pythontech 0:5868e8752d44 1128 // do the import
pythontech 0:5868e8752d44 1129 qstr dummy_q;
pythontech 0:5868e8752d44 1130 do_import_name(comp, pn_import_source, &dummy_q);
pythontech 0:5868e8752d44 1131 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1132 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_nodes[i], PN_import_as_name));
pythontech 0:5868e8752d44 1133 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pn_nodes[i];
pythontech 0:5868e8752d44 1134 qstr id2 = MP_PARSE_NODE_LEAF_ARG(pns3->nodes[0]); // should be id
pythontech 0:5868e8752d44 1135 EMIT_ARG(import_from, id2);
pythontech 0:5868e8752d44 1136 if (MP_PARSE_NODE_IS_NULL(pns3->nodes[1])) {
pythontech 0:5868e8752d44 1137 compile_store_id(comp, id2);
pythontech 0:5868e8752d44 1138 } else {
pythontech 0:5868e8752d44 1139 compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pns3->nodes[1]));
pythontech 0:5868e8752d44 1140 }
pythontech 0:5868e8752d44 1141 }
pythontech 0:5868e8752d44 1142 EMIT(pop_top);
pythontech 0:5868e8752d44 1143 }
pythontech 0:5868e8752d44 1144 }
pythontech 0:5868e8752d44 1145
pythontech 0:5868e8752d44 1146 STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
pythontech 0:5868e8752d44 1147 bool added;
pythontech 0:5868e8752d44 1148 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
pythontech 0:5868e8752d44 1149 if (!added && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) {
pythontech 0:5868e8752d44 1150 compile_syntax_error(comp, pn, "identifier redefined as global");
pythontech 0:5868e8752d44 1151 return;
pythontech 0:5868e8752d44 1152 }
pythontech 0:5868e8752d44 1153 id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
pythontech 0:5868e8752d44 1154
pythontech 0:5868e8752d44 1155 // if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL
pythontech 0:5868e8752d44 1156 id_info = scope_find_global(comp->scope_cur, qst);
pythontech 0:5868e8752d44 1157 if (id_info != NULL) {
pythontech 0:5868e8752d44 1158 id_info->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
pythontech 0:5868e8752d44 1159 }
pythontech 0:5868e8752d44 1160 }
pythontech 0:5868e8752d44 1161
pythontech 0:5868e8752d44 1162 STATIC void compile_global_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1163 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 1164 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 1165 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
pythontech 0:5868e8752d44 1166 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1167 compile_declare_global(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));
pythontech 0:5868e8752d44 1168 }
pythontech 0:5868e8752d44 1169 }
pythontech 0:5868e8752d44 1170 }
pythontech 0:5868e8752d44 1171
pythontech 0:5868e8752d44 1172 STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, qstr qst) {
pythontech 0:5868e8752d44 1173 bool added;
pythontech 0:5868e8752d44 1174 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qst, &added);
pythontech 0:5868e8752d44 1175 if (!added && id_info->kind != ID_INFO_KIND_FREE) {
pythontech 0:5868e8752d44 1176 compile_syntax_error(comp, pn, "identifier redefined as nonlocal");
pythontech 0:5868e8752d44 1177 return;
pythontech 0:5868e8752d44 1178 }
pythontech 0:5868e8752d44 1179 id_info_t *id_info2 = scope_find_local_in_parent(comp->scope_cur, qst);
pythontech 0:5868e8752d44 1180 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 1181 compile_syntax_error(comp, pn, "no binding for nonlocal found");
pythontech 0:5868e8752d44 1182 return;
pythontech 0:5868e8752d44 1183 }
pythontech 0:5868e8752d44 1184 id_info->kind = ID_INFO_KIND_FREE;
pythontech 0:5868e8752d44 1185 scope_close_over_in_parents(comp->scope_cur, qst);
pythontech 0:5868e8752d44 1186 }
pythontech 0:5868e8752d44 1187
pythontech 0:5868e8752d44 1188 STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1189 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 1190 if (comp->scope_cur->kind == SCOPE_MODULE) {
pythontech 0:5868e8752d44 1191 compile_syntax_error(comp, (mp_parse_node_t)pns, "can't declare nonlocal in outer code");
pythontech 0:5868e8752d44 1192 return;
pythontech 0:5868e8752d44 1193 }
pythontech 0:5868e8752d44 1194 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 1195 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_name_list, &nodes);
pythontech 0:5868e8752d44 1196 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 1197 compile_declare_nonlocal(comp, (mp_parse_node_t)pns, MP_PARSE_NODE_LEAF_ARG(nodes[i]));
pythontech 0:5868e8752d44 1198 }
pythontech 0:5868e8752d44 1199 }
pythontech 0:5868e8752d44 1200 }
pythontech 0:5868e8752d44 1201
pythontech 0:5868e8752d44 1202 STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1203 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1204 c_if_cond(comp, pns->nodes[0], true, l_end);
pythontech 0:5868e8752d44 1205 EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
pythontech 0:5868e8752d44 1206 if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
pythontech 0:5868e8752d44 1207 // assertion message
pythontech 0:5868e8752d44 1208 compile_node(comp, pns->nodes[1]);
pythontech 0:5868e8752d44 1209 EMIT_ARG(call_function, 1, 0, 0);
pythontech 0:5868e8752d44 1210 }
pythontech 0:5868e8752d44 1211 EMIT_ARG(raise_varargs, 1);
pythontech 0:5868e8752d44 1212 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1213 }
pythontech 0:5868e8752d44 1214
pythontech 0:5868e8752d44 1215 STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1216 // TODO proper and/or short circuiting
pythontech 0:5868e8752d44 1217
pythontech 0:5868e8752d44 1218 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1219
pythontech 0:5868e8752d44 1220 // optimisation: don't emit anything when "if False"
pythontech 0:5868e8752d44 1221 if (!node_is_const_false(pns->nodes[0])) {
pythontech 0:5868e8752d44 1222 uint l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 1223 c_if_cond(comp, pns->nodes[0], false, l_fail); // if condition
pythontech 0:5868e8752d44 1224
pythontech 0:5868e8752d44 1225 compile_node(comp, pns->nodes[1]); // if block
pythontech 0:5868e8752d44 1226
pythontech 0:5868e8752d44 1227 // optimisation: skip everything else when "if True"
pythontech 0:5868e8752d44 1228 if (node_is_const_true(pns->nodes[0])) {
pythontech 0:5868e8752d44 1229 goto done;
pythontech 0:5868e8752d44 1230 }
pythontech 0:5868e8752d44 1231
pythontech 0:5868e8752d44 1232 if (
pythontech 0:5868e8752d44 1233 // optimisation: don't jump over non-existent elif/else blocks
pythontech 0:5868e8752d44 1234 !(MP_PARSE_NODE_IS_NULL(pns->nodes[2]) && MP_PARSE_NODE_IS_NULL(pns->nodes[3]))
pythontech 0:5868e8752d44 1235 // optimisation: don't jump if last instruction was return
pythontech 0:5868e8752d44 1236 && !EMIT(last_emit_was_return_value)
pythontech 0:5868e8752d44 1237 ) {
pythontech 0:5868e8752d44 1238 // jump over elif/else blocks
pythontech 0:5868e8752d44 1239 EMIT_ARG(jump, l_end);
pythontech 0:5868e8752d44 1240 }
pythontech 0:5868e8752d44 1241
pythontech 0:5868e8752d44 1242 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 1243 }
pythontech 0:5868e8752d44 1244
pythontech 0:5868e8752d44 1245 // compile elif blocks (if any)
pythontech 0:5868e8752d44 1246 mp_parse_node_t *pn_elif;
pythontech 0:5868e8752d44 1247 int n_elif = mp_parse_node_extract_list(&pns->nodes[2], PN_if_stmt_elif_list, &pn_elif);
pythontech 0:5868e8752d44 1248 for (int i = 0; i < n_elif; i++) {
pythontech 0:5868e8752d44 1249 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_elif[i], PN_if_stmt_elif)); // should be
pythontech 0:5868e8752d44 1250 mp_parse_node_struct_t *pns_elif = (mp_parse_node_struct_t*)pn_elif[i];
pythontech 0:5868e8752d44 1251
pythontech 0:5868e8752d44 1252 // optimisation: don't emit anything when "if False"
pythontech 0:5868e8752d44 1253 if (!node_is_const_false(pns_elif->nodes[0])) {
pythontech 0:5868e8752d44 1254 uint l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 1255 c_if_cond(comp, pns_elif->nodes[0], false, l_fail); // elif condition
pythontech 0:5868e8752d44 1256
pythontech 0:5868e8752d44 1257 compile_node(comp, pns_elif->nodes[1]); // elif block
pythontech 0:5868e8752d44 1258
pythontech 0:5868e8752d44 1259 // optimisation: skip everything else when "elif True"
pythontech 0:5868e8752d44 1260 if (node_is_const_true(pns_elif->nodes[0])) {
pythontech 0:5868e8752d44 1261 goto done;
pythontech 0:5868e8752d44 1262 }
pythontech 0:5868e8752d44 1263
pythontech 0:5868e8752d44 1264 // optimisation: don't jump if last instruction was return
pythontech 0:5868e8752d44 1265 if (!EMIT(last_emit_was_return_value)) {
pythontech 0:5868e8752d44 1266 EMIT_ARG(jump, l_end);
pythontech 0:5868e8752d44 1267 }
pythontech 0:5868e8752d44 1268 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 1269 }
pythontech 0:5868e8752d44 1270 }
pythontech 0:5868e8752d44 1271
pythontech 0:5868e8752d44 1272 // compile else block
pythontech 0:5868e8752d44 1273 compile_node(comp, pns->nodes[3]); // can be null
pythontech 0:5868e8752d44 1274
pythontech 0:5868e8752d44 1275 done:
pythontech 0:5868e8752d44 1276 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1277 }
pythontech 0:5868e8752d44 1278
pythontech 0:5868e8752d44 1279 #define START_BREAK_CONTINUE_BLOCK \
pythontech 0:5868e8752d44 1280 uint16_t old_break_label = comp->break_label; \
pythontech 0:5868e8752d44 1281 uint16_t old_continue_label = comp->continue_label; \
pythontech 0:5868e8752d44 1282 uint16_t old_break_continue_except_level = comp->break_continue_except_level; \
pythontech 0:5868e8752d44 1283 uint break_label = comp_next_label(comp); \
pythontech 0:5868e8752d44 1284 uint continue_label = comp_next_label(comp); \
pythontech 0:5868e8752d44 1285 comp->break_label = break_label; \
pythontech 0:5868e8752d44 1286 comp->continue_label = continue_label; \
pythontech 0:5868e8752d44 1287 comp->break_continue_except_level = comp->cur_except_level;
pythontech 0:5868e8752d44 1288
pythontech 0:5868e8752d44 1289 #define END_BREAK_CONTINUE_BLOCK \
pythontech 0:5868e8752d44 1290 comp->break_label = old_break_label; \
pythontech 0:5868e8752d44 1291 comp->continue_label = old_continue_label; \
pythontech 0:5868e8752d44 1292 comp->break_continue_except_level = old_break_continue_except_level;
pythontech 0:5868e8752d44 1293
pythontech 0:5868e8752d44 1294 STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1295 START_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1296
pythontech 0:5868e8752d44 1297 if (!node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False"
pythontech 0:5868e8752d44 1298 uint top_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1299 if (!node_is_const_true(pns->nodes[0])) { // optimisation: don't jump to cond for "while True"
pythontech 0:5868e8752d44 1300 EMIT_ARG(jump, continue_label);
pythontech 0:5868e8752d44 1301 }
pythontech 0:5868e8752d44 1302 EMIT_ARG(label_assign, top_label);
pythontech 0:5868e8752d44 1303 compile_node(comp, pns->nodes[1]); // body
pythontech 0:5868e8752d44 1304 EMIT_ARG(label_assign, continue_label);
pythontech 0:5868e8752d44 1305 c_if_cond(comp, pns->nodes[0], true, top_label); // condition
pythontech 0:5868e8752d44 1306 }
pythontech 0:5868e8752d44 1307
pythontech 0:5868e8752d44 1308 // break/continue apply to outer loop (if any) in the else block
pythontech 0:5868e8752d44 1309 END_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1310
pythontech 0:5868e8752d44 1311 compile_node(comp, pns->nodes[2]); // else
pythontech 0:5868e8752d44 1312
pythontech 0:5868e8752d44 1313 EMIT_ARG(label_assign, break_label);
pythontech 0:5868e8752d44 1314 }
pythontech 0:5868e8752d44 1315
pythontech 0:5868e8752d44 1316 // This function compiles an optimised for-loop of the form:
pythontech 0:5868e8752d44 1317 // for <var> in range(<start>, <end>, <step>):
pythontech 0:5868e8752d44 1318 // <body>
pythontech 0:5868e8752d44 1319 // else:
pythontech 0:5868e8752d44 1320 // <else>
pythontech 0:5868e8752d44 1321 // <var> must be an identifier and <step> must be a small-int.
pythontech 0:5868e8752d44 1322 //
pythontech 0:5868e8752d44 1323 // Semantics of for-loop require:
pythontech 0:5868e8752d44 1324 // - final failing value should not be stored in the loop variable
pythontech 0:5868e8752d44 1325 // - if the loop never runs, the loop variable should never be assigned
pythontech 0:5868e8752d44 1326 // - assignments to <var>, <end> or <step> in the body do not alter the loop
pythontech 0:5868e8752d44 1327 // (<step> is a constant for us, so no need to worry about it changing)
pythontech 0:5868e8752d44 1328 //
pythontech 0:5868e8752d44 1329 // If <end> is a small-int, then the stack during the for-loop contains just
pythontech 0:5868e8752d44 1330 // the current value of <var>. Otherwise, the stack contains <end> then the
pythontech 0:5868e8752d44 1331 // current value of <var>.
pythontech 0:5868e8752d44 1332 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 1333 START_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1334
pythontech 0:5868e8752d44 1335 uint top_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1336 uint entry_label = comp_next_label(comp);
pythontech 0:5868e8752d44 1337
pythontech 0:5868e8752d44 1338 // put the end value on the stack if it's not a small-int constant
pythontech 0:5868e8752d44 1339 bool end_on_stack = !MP_PARSE_NODE_IS_SMALL_INT(pn_end);
pythontech 0:5868e8752d44 1340 if (end_on_stack) {
pythontech 0:5868e8752d44 1341 compile_node(comp, pn_end);
pythontech 0:5868e8752d44 1342 }
pythontech 0:5868e8752d44 1343
pythontech 0:5868e8752d44 1344 // compile: start
pythontech 0:5868e8752d44 1345 compile_node(comp, pn_start);
pythontech 0:5868e8752d44 1346
pythontech 0:5868e8752d44 1347 EMIT_ARG(jump, entry_label);
pythontech 0:5868e8752d44 1348 EMIT_ARG(label_assign, top_label);
pythontech 0:5868e8752d44 1349
pythontech 0:5868e8752d44 1350 // duplicate next value and store it to var
pythontech 0:5868e8752d44 1351 EMIT(dup_top);
pythontech 0:5868e8752d44 1352 c_assign(comp, pn_var, ASSIGN_STORE);
pythontech 0:5868e8752d44 1353
pythontech 0:5868e8752d44 1354 // compile body
pythontech 0:5868e8752d44 1355 compile_node(comp, pn_body);
pythontech 0:5868e8752d44 1356
pythontech 0:5868e8752d44 1357 EMIT_ARG(label_assign, continue_label);
pythontech 0:5868e8752d44 1358
pythontech 0:5868e8752d44 1359 // compile: var + step
pythontech 0:5868e8752d44 1360 compile_node(comp, pn_step);
pythontech 0:5868e8752d44 1361 EMIT_ARG(binary_op, MP_BINARY_OP_INPLACE_ADD);
pythontech 0:5868e8752d44 1362
pythontech 0:5868e8752d44 1363 EMIT_ARG(label_assign, entry_label);
pythontech 0:5868e8752d44 1364
pythontech 0:5868e8752d44 1365 // compile: if var <cond> end: goto top
pythontech 0:5868e8752d44 1366 if (end_on_stack) {
pythontech 0:5868e8752d44 1367 EMIT(dup_top_two);
pythontech 0:5868e8752d44 1368 EMIT(rot_two);
pythontech 0:5868e8752d44 1369 } else {
pythontech 0:5868e8752d44 1370 EMIT(dup_top);
pythontech 0:5868e8752d44 1371 compile_node(comp, pn_end);
pythontech 0:5868e8752d44 1372 }
pythontech 0:5868e8752d44 1373 assert(MP_PARSE_NODE_IS_SMALL_INT(pn_step));
pythontech 0:5868e8752d44 1374 if (MP_PARSE_NODE_LEAF_SMALL_INT(pn_step) >= 0) {
pythontech 0:5868e8752d44 1375 EMIT_ARG(binary_op, MP_BINARY_OP_LESS);
pythontech 0:5868e8752d44 1376 } else {
pythontech 0:5868e8752d44 1377 EMIT_ARG(binary_op, MP_BINARY_OP_MORE);
pythontech 0:5868e8752d44 1378 }
pythontech 0:5868e8752d44 1379 EMIT_ARG(pop_jump_if, true, top_label);
pythontech 0:5868e8752d44 1380
pythontech 0:5868e8752d44 1381 // break/continue apply to outer loop (if any) in the else block
pythontech 0:5868e8752d44 1382 END_BREAK_CONTINUE_BLOCK
pythontech 0:5868e8752d44 1383
pythontech 0:5868e8752d44 1384 compile_node(comp, pn_else);
pythontech 0:5868e8752d44 1385
pythontech 0:5868e8752d44 1386 EMIT_ARG(label_assign, break_label);
pythontech 0:5868e8752d44 1387
pythontech 0:5868e8752d44 1388 // discard final value of var that failed the loop condition
pythontech 0:5868e8752d44 1389 EMIT(pop_top);
pythontech 0:5868e8752d44 1390
pythontech 0:5868e8752d44 1391 // discard <end> value if it's on the stack
pythontech 0:5868e8752d44 1392 if (end_on_stack) {
pythontech 0:5868e8752d44 1393 EMIT(pop_top);
pythontech 0:5868e8752d44 1394 }
pythontech 0:5868e8752d44 1395 }
pythontech 0:5868e8752d44 1396
pythontech 0:5868e8752d44 1397 STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1398 // this bit optimises: for <x> in range(...), turning it into an explicitly incremented variable
pythontech 0:5868e8752d44 1399 // this is actually slower, but uses no heap memory
pythontech 0:5868e8752d44 1400 // for viper it will be much, much faster
Colin Hogben 2:c89e95946844 1401 if (/*comp->scope_cur->emit_options == MP_EMIT_OPT_VIPER &&*/ MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_atom_expr_normal)) {
pythontech 0:5868e8752d44 1402 mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
Colin Hogben 2:c89e95946844 1403 if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
pythontech 0:5868e8752d44 1404 && MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
Colin Hogben 2:c89e95946844 1405 && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)) {
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
Colin Hogben 2:c89e95946844 1664 STATIC void compile_yield_from(compiler_t *comp) {
Colin Hogben 2:c89e95946844 1665 EMIT(get_iter);
Colin Hogben 2:c89e95946844 1666 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Colin Hogben 2:c89e95946844 1667 EMIT(yield_from);
Colin Hogben 2:c89e95946844 1668 }
Colin Hogben 2:c89e95946844 1669
Colin Hogben 2:c89e95946844 1670 #if MICROPY_PY_ASYNC_AWAIT
Colin Hogben 2:c89e95946844 1671 STATIC void compile_await_object_method(compiler_t *comp, qstr method) {
Colin Hogben 2:c89e95946844 1672 EMIT_ARG(load_method, method);
Colin Hogben 2:c89e95946844 1673 EMIT_ARG(call_method, 0, 0, 0);
Colin Hogben 2:c89e95946844 1674 compile_yield_from(comp);
Colin Hogben 2:c89e95946844 1675 }
Colin Hogben 2:c89e95946844 1676
Colin Hogben 2:c89e95946844 1677 STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Colin Hogben 2:c89e95946844 1678 // comp->break_label |= MP_EMIT_BREAK_FROM_FOR;
Colin Hogben 2:c89e95946844 1679
Colin Hogben 2:c89e95946844 1680 qstr context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[1]);
Colin Hogben 2:c89e95946844 1681 uint while_else_label = comp_next_label(comp);
Colin Hogben 2:c89e95946844 1682 uint try_exception_label = comp_next_label(comp);
Colin Hogben 2:c89e95946844 1683 uint try_else_label = comp_next_label(comp);
Colin Hogben 2:c89e95946844 1684 uint try_finally_label = comp_next_label(comp);
Colin Hogben 2:c89e95946844 1685
Colin Hogben 2:c89e95946844 1686 compile_node(comp, pns->nodes[1]); // iterator
Colin Hogben 2:c89e95946844 1687 compile_await_object_method(comp, MP_QSTR___aiter__);
Colin Hogben 2:c89e95946844 1688 compile_store_id(comp, context);
Colin Hogben 2:c89e95946844 1689
Colin Hogben 2:c89e95946844 1690 START_BREAK_CONTINUE_BLOCK
Colin Hogben 2:c89e95946844 1691
Colin Hogben 2:c89e95946844 1692 EMIT_ARG(label_assign, continue_label);
Colin Hogben 2:c89e95946844 1693
Colin Hogben 2:c89e95946844 1694 EMIT_ARG(setup_except, try_exception_label);
Colin Hogben 2:c89e95946844 1695 compile_increase_except_level(comp);
Colin Hogben 2:c89e95946844 1696
Colin Hogben 2:c89e95946844 1697 compile_load_id(comp, context);
Colin Hogben 2:c89e95946844 1698 compile_await_object_method(comp, MP_QSTR___anext__);
Colin Hogben 2:c89e95946844 1699 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
Colin Hogben 2:c89e95946844 1700 EMIT(pop_block);
Colin Hogben 2:c89e95946844 1701 EMIT_ARG(jump, try_else_label);
Colin Hogben 2:c89e95946844 1702
Colin Hogben 2:c89e95946844 1703 EMIT_ARG(label_assign, try_exception_label);
Colin Hogben 2:c89e95946844 1704 EMIT(start_except_handler);
Colin Hogben 2:c89e95946844 1705 EMIT(dup_top);
Colin Hogben 2:c89e95946844 1706 EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration);
Colin Hogben 2:c89e95946844 1707 EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
Colin Hogben 2:c89e95946844 1708 EMIT_ARG(pop_jump_if, false, try_finally_label);
Colin Hogben 2:c89e95946844 1709 EMIT(pop_top);
Colin Hogben 2:c89e95946844 1710 EMIT(pop_top);
Colin Hogben 2:c89e95946844 1711 EMIT(pop_top);
Colin Hogben 2:c89e95946844 1712 EMIT(pop_except);
Colin Hogben 2:c89e95946844 1713 EMIT_ARG(jump, while_else_label);
Colin Hogben 2:c89e95946844 1714
Colin Hogben 2:c89e95946844 1715 EMIT_ARG(label_assign, try_finally_label);
Colin Hogben 2:c89e95946844 1716 EMIT_ARG(adjust_stack_size, 3);
Colin Hogben 2:c89e95946844 1717 compile_decrease_except_level(comp);
Colin Hogben 2:c89e95946844 1718 EMIT(end_finally);
Colin Hogben 2:c89e95946844 1719 EMIT(end_except_handler);
Colin Hogben 2:c89e95946844 1720
Colin Hogben 2:c89e95946844 1721 EMIT_ARG(label_assign, try_else_label);
Colin Hogben 2:c89e95946844 1722 compile_node(comp, pns->nodes[2]); // body
Colin Hogben 2:c89e95946844 1723
Colin Hogben 2:c89e95946844 1724 EMIT_ARG(jump, continue_label);
Colin Hogben 2:c89e95946844 1725 // break/continue apply to outer loop (if any) in the else block
Colin Hogben 2:c89e95946844 1726 END_BREAK_CONTINUE_BLOCK
Colin Hogben 2:c89e95946844 1727
Colin Hogben 2:c89e95946844 1728 EMIT_ARG(label_assign, while_else_label);
Colin Hogben 2:c89e95946844 1729 compile_node(comp, pns->nodes[3]); // else
Colin Hogben 2:c89e95946844 1730
Colin Hogben 2:c89e95946844 1731 EMIT_ARG(label_assign, break_label);
Colin Hogben 2:c89e95946844 1732 }
Colin Hogben 2:c89e95946844 1733
Colin Hogben 2:c89e95946844 1734 STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, mp_parse_node_t body) {
Colin Hogben 2:c89e95946844 1735 if (n == 0) {
Colin Hogben 2:c89e95946844 1736 // no more pre-bits, compile the body of the with
Colin Hogben 2:c89e95946844 1737 compile_node(comp, body);
Colin Hogben 2:c89e95946844 1738 } else {
Colin Hogben 2:c89e95946844 1739 uint try_exception_label = comp_next_label(comp);
Colin Hogben 2:c89e95946844 1740 uint no_reraise_label = comp_next_label(comp);
Colin Hogben 2:c89e95946844 1741 uint try_else_label = comp_next_label(comp);
Colin Hogben 2:c89e95946844 1742 uint end_label = comp_next_label(comp);
Colin Hogben 2:c89e95946844 1743 qstr context;
Colin Hogben 2:c89e95946844 1744
Colin Hogben 2:c89e95946844 1745 if (MP_PARSE_NODE_IS_STRUCT_KIND(nodes[0], PN_with_item)) {
Colin Hogben 2:c89e95946844 1746 // this pre-bit is of the form "a as b"
Colin Hogben 2:c89e95946844 1747 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)nodes[0];
Colin Hogben 2:c89e95946844 1748 compile_node(comp, pns->nodes[0]);
Colin Hogben 2:c89e95946844 1749 context = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
Colin Hogben 2:c89e95946844 1750 compile_store_id(comp, context);
Colin Hogben 2:c89e95946844 1751 compile_load_id(comp, context);
Colin Hogben 2:c89e95946844 1752 compile_await_object_method(comp, MP_QSTR___aenter__);
Colin Hogben 2:c89e95946844 1753 c_assign(comp, pns->nodes[1], ASSIGN_STORE);
Colin Hogben 2:c89e95946844 1754 } else {
Colin Hogben 2:c89e95946844 1755 // this pre-bit is just an expression
Colin Hogben 2:c89e95946844 1756 compile_node(comp, nodes[0]);
Colin Hogben 2:c89e95946844 1757 context = MP_PARSE_NODE_LEAF_ARG(nodes[0]);
Colin Hogben 2:c89e95946844 1758 compile_store_id(comp, context);
Colin Hogben 2:c89e95946844 1759 compile_load_id(comp, context);
Colin Hogben 2:c89e95946844 1760 compile_await_object_method(comp, MP_QSTR___aenter__);
Colin Hogben 2:c89e95946844 1761 EMIT(pop_top);
Colin Hogben 2:c89e95946844 1762 }
Colin Hogben 2:c89e95946844 1763
Colin Hogben 2:c89e95946844 1764 compile_load_id(comp, context);
Colin Hogben 2:c89e95946844 1765 EMIT_ARG(load_method, MP_QSTR___aexit__);
Colin Hogben 2:c89e95946844 1766
Colin Hogben 2:c89e95946844 1767 EMIT_ARG(setup_except, try_exception_label);
Colin Hogben 2:c89e95946844 1768 compile_increase_except_level(comp);
Colin Hogben 2:c89e95946844 1769 // compile additional pre-bits and the body
Colin Hogben 2:c89e95946844 1770 compile_async_with_stmt_helper(comp, n - 1, nodes + 1, body);
Colin Hogben 2:c89e95946844 1771 // finish this with block
Colin Hogben 2:c89e95946844 1772 EMIT(pop_block);
Colin Hogben 2:c89e95946844 1773 EMIT_ARG(jump, try_else_label); // jump over exception handler
Colin Hogben 2:c89e95946844 1774
Colin Hogben 2:c89e95946844 1775 EMIT_ARG(label_assign, try_exception_label); // start of exception handler
Colin Hogben 2:c89e95946844 1776 EMIT(start_except_handler);
Colin Hogben 2:c89e95946844 1777 EMIT(rot_three);
Colin Hogben 2:c89e95946844 1778 EMIT(rot_two);
Colin Hogben 2:c89e95946844 1779 EMIT_ARG(call_method, 3, 0, 0);
Colin Hogben 2:c89e95946844 1780 compile_yield_from(comp);
Colin Hogben 2:c89e95946844 1781 EMIT_ARG(pop_jump_if, true, no_reraise_label);
Colin Hogben 2:c89e95946844 1782 EMIT_ARG(raise_varargs, 0);
Colin Hogben 2:c89e95946844 1783
Colin Hogben 2:c89e95946844 1784 EMIT_ARG(label_assign, no_reraise_label);
Colin Hogben 2:c89e95946844 1785 EMIT(pop_except);
Colin Hogben 2:c89e95946844 1786 EMIT_ARG(jump, end_label);
Colin Hogben 2:c89e95946844 1787
Colin Hogben 2:c89e95946844 1788 EMIT_ARG(adjust_stack_size, 5);
Colin Hogben 2:c89e95946844 1789 compile_decrease_except_level(comp);
Colin Hogben 2:c89e95946844 1790 EMIT(end_finally);
Colin Hogben 2:c89e95946844 1791 EMIT(end_except_handler);
Colin Hogben 2:c89e95946844 1792
Colin Hogben 2:c89e95946844 1793 EMIT_ARG(label_assign, try_else_label); // start of try-else handler
Colin Hogben 2:c89e95946844 1794 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
Colin Hogben 2:c89e95946844 1795 EMIT(dup_top);
Colin Hogben 2:c89e95946844 1796 EMIT(dup_top);
Colin Hogben 2:c89e95946844 1797 EMIT_ARG(call_method, 3, 0, 0);
Colin Hogben 2:c89e95946844 1798 compile_yield_from(comp);
Colin Hogben 2:c89e95946844 1799 EMIT(pop_top);
Colin Hogben 2:c89e95946844 1800
Colin Hogben 2:c89e95946844 1801 EMIT_ARG(label_assign, end_label);
Colin Hogben 2:c89e95946844 1802
Colin Hogben 2:c89e95946844 1803 }
Colin Hogben 2:c89e95946844 1804 }
Colin Hogben 2:c89e95946844 1805
Colin Hogben 2:c89e95946844 1806 STATIC void compile_async_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Colin Hogben 2:c89e95946844 1807 // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit)
Colin Hogben 2:c89e95946844 1808 mp_parse_node_t *nodes;
Colin Hogben 2:c89e95946844 1809 int n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes);
Colin Hogben 2:c89e95946844 1810 assert(n > 0);
Colin Hogben 2:c89e95946844 1811
Colin Hogben 2:c89e95946844 1812 // compile in a nested fashion
Colin Hogben 2:c89e95946844 1813 compile_async_with_stmt_helper(comp, n, nodes, pns->nodes[1]);
Colin Hogben 2:c89e95946844 1814 }
Colin Hogben 2:c89e95946844 1815
Colin Hogben 2:c89e95946844 1816 STATIC void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
Colin Hogben 2:c89e95946844 1817 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[0]));
Colin Hogben 2:c89e95946844 1818 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
Colin Hogben 2:c89e95946844 1819 if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_funcdef) {
Colin Hogben 2:c89e95946844 1820 // async def
Colin Hogben 2:c89e95946844 1821 compile_funcdef(comp, pns0);
Colin Hogben 2:c89e95946844 1822 scope_t *fscope = (scope_t*)pns0->nodes[4];
Colin Hogben 2:c89e95946844 1823 fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR;
Colin Hogben 2:c89e95946844 1824 } else if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_for_stmt) {
Colin Hogben 2:c89e95946844 1825 // async for
Colin Hogben 2:c89e95946844 1826 compile_async_for_stmt(comp, pns0);
Colin Hogben 2:c89e95946844 1827 } else {
Colin Hogben 2:c89e95946844 1828 // async with
Colin Hogben 2:c89e95946844 1829 assert(MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_with_stmt);
Colin Hogben 2:c89e95946844 1830 compile_async_with_stmt(comp, pns0);
Colin Hogben 2:c89e95946844 1831 }
Colin Hogben 2:c89e95946844 1832 }
Colin Hogben 2:c89e95946844 1833 #endif
Colin Hogben 2:c89e95946844 1834
pythontech 0:5868e8752d44 1835 STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1836 if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
pythontech 0:5868e8752d44 1837 if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) {
pythontech 0:5868e8752d44 1838 // for REPL, evaluate then print the expression
pythontech 0:5868e8752d44 1839 compile_load_id(comp, MP_QSTR___repl_print__);
pythontech 0:5868e8752d44 1840 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1841 EMIT_ARG(call_function, 1, 0, 0);
pythontech 0:5868e8752d44 1842 EMIT(pop_top);
pythontech 0:5868e8752d44 1843
pythontech 0:5868e8752d44 1844 } else {
pythontech 0:5868e8752d44 1845 // for non-REPL, evaluate then discard the expression
pythontech 0:5868e8752d44 1846 if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
pythontech 0:5868e8752d44 1847 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)
pythontech 0:5868e8752d44 1848 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_bytes)
pythontech 0:5868e8752d44 1849 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
pythontech 0:5868e8752d44 1850 // do nothing with a lonely constant
pythontech 0:5868e8752d44 1851 } else {
pythontech 0:5868e8752d44 1852 compile_node(comp, pns->nodes[0]); // just an expression
pythontech 0:5868e8752d44 1853 EMIT(pop_top); // discard last result since this is a statement and leaves nothing on the stack
pythontech 0:5868e8752d44 1854 }
pythontech 0:5868e8752d44 1855 }
pythontech 0:5868e8752d44 1856 } else if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 1857 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1858 int kind = MP_PARSE_NODE_STRUCT_KIND(pns1);
pythontech 0:5868e8752d44 1859 if (kind == PN_expr_stmt_augassign) {
pythontech 0:5868e8752d44 1860 c_assign(comp, pns->nodes[0], ASSIGN_AUG_LOAD); // lhs load for aug assign
pythontech 0:5868e8752d44 1861 compile_node(comp, pns1->nodes[1]); // rhs
pythontech 0:5868e8752d44 1862 assert(MP_PARSE_NODE_IS_TOKEN(pns1->nodes[0]));
pythontech 0:5868e8752d44 1863 mp_binary_op_t op;
pythontech 0:5868e8752d44 1864 switch (MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0])) {
pythontech 0:5868e8752d44 1865 case MP_TOKEN_DEL_PIPE_EQUAL: op = MP_BINARY_OP_INPLACE_OR; break;
pythontech 0:5868e8752d44 1866 case MP_TOKEN_DEL_CARET_EQUAL: op = MP_BINARY_OP_INPLACE_XOR; break;
pythontech 0:5868e8752d44 1867 case MP_TOKEN_DEL_AMPERSAND_EQUAL: op = MP_BINARY_OP_INPLACE_AND; break;
pythontech 0:5868e8752d44 1868 case MP_TOKEN_DEL_DBL_LESS_EQUAL: op = MP_BINARY_OP_INPLACE_LSHIFT; break;
pythontech 0:5868e8752d44 1869 case MP_TOKEN_DEL_DBL_MORE_EQUAL: op = MP_BINARY_OP_INPLACE_RSHIFT; break;
pythontech 0:5868e8752d44 1870 case MP_TOKEN_DEL_PLUS_EQUAL: op = MP_BINARY_OP_INPLACE_ADD; break;
pythontech 0:5868e8752d44 1871 case MP_TOKEN_DEL_MINUS_EQUAL: op = MP_BINARY_OP_INPLACE_SUBTRACT; break;
pythontech 0:5868e8752d44 1872 case MP_TOKEN_DEL_STAR_EQUAL: op = MP_BINARY_OP_INPLACE_MULTIPLY; break;
pythontech 0:5868e8752d44 1873 case MP_TOKEN_DEL_DBL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_FLOOR_DIVIDE; break;
pythontech 0:5868e8752d44 1874 case MP_TOKEN_DEL_SLASH_EQUAL: op = MP_BINARY_OP_INPLACE_TRUE_DIVIDE; break;
pythontech 0:5868e8752d44 1875 case MP_TOKEN_DEL_PERCENT_EQUAL: op = MP_BINARY_OP_INPLACE_MODULO; break;
pythontech 0:5868e8752d44 1876 case MP_TOKEN_DEL_DBL_STAR_EQUAL: default: op = MP_BINARY_OP_INPLACE_POWER; break;
pythontech 0:5868e8752d44 1877 }
pythontech 0:5868e8752d44 1878 EMIT_ARG(binary_op, op);
pythontech 0:5868e8752d44 1879 c_assign(comp, pns->nodes[0], ASSIGN_AUG_STORE); // lhs store for aug assign
pythontech 0:5868e8752d44 1880 } else if (kind == PN_expr_stmt_assign_list) {
pythontech 0:5868e8752d44 1881 int rhs = MP_PARSE_NODE_STRUCT_NUM_NODES(pns1) - 1;
pythontech 0:5868e8752d44 1882 compile_node(comp, pns1->nodes[rhs]); // rhs
pythontech 0:5868e8752d44 1883 // following CPython, we store left-most first
pythontech 0:5868e8752d44 1884 if (rhs > 0) {
pythontech 0:5868e8752d44 1885 EMIT(dup_top);
pythontech 0:5868e8752d44 1886 }
pythontech 0:5868e8752d44 1887 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1888 for (int i = 0; i < rhs; i++) {
pythontech 0:5868e8752d44 1889 if (i + 1 < rhs) {
pythontech 0:5868e8752d44 1890 EMIT(dup_top);
pythontech 0:5868e8752d44 1891 }
pythontech 0:5868e8752d44 1892 c_assign(comp, pns1->nodes[i], ASSIGN_STORE); // middle store
pythontech 0:5868e8752d44 1893 }
pythontech 0:5868e8752d44 1894 } else {
pythontech 0:5868e8752d44 1895 plain_assign:
pythontech 0:5868e8752d44 1896 if (MICROPY_COMP_DOUBLE_TUPLE_ASSIGN
pythontech 0:5868e8752d44 1897 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
pythontech 0:5868e8752d44 1898 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
pythontech 0:5868e8752d44 1899 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 2
pythontech 0:5868e8752d44 1900 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 2) {
pythontech 0:5868e8752d44 1901 // optimisation for a, b = c, d
pythontech 0:5868e8752d44 1902 mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1903 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 1904 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
pythontech 0:5868e8752d44 1905 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) {
pythontech 0:5868e8752d44 1906 // can't optimise when it's a star expression on the lhs
pythontech 0:5868e8752d44 1907 goto no_optimisation;
pythontech 0:5868e8752d44 1908 }
pythontech 0:5868e8752d44 1909 compile_node(comp, pns10->nodes[0]); // rhs
pythontech 0:5868e8752d44 1910 compile_node(comp, pns10->nodes[1]); // rhs
pythontech 0:5868e8752d44 1911 EMIT(rot_two);
pythontech 0:5868e8752d44 1912 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1913 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1914 } else if (MICROPY_COMP_TRIPLE_TUPLE_ASSIGN
pythontech 0:5868e8752d44 1915 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_testlist_star_expr)
pythontech 0:5868e8752d44 1916 && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_star_expr)
pythontech 0:5868e8752d44 1917 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[1]) == 3
pythontech 0:5868e8752d44 1918 && MP_PARSE_NODE_STRUCT_NUM_NODES((mp_parse_node_struct_t*)pns->nodes[0]) == 3) {
pythontech 0:5868e8752d44 1919 // optimisation for a, b, c = d, e, f
pythontech 0:5868e8752d44 1920 mp_parse_node_struct_t *pns10 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1921 mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 1922 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
pythontech 0:5868e8752d44 1923 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)
pythontech 0:5868e8752d44 1924 || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) {
pythontech 0:5868e8752d44 1925 // can't optimise when it's a star expression on the lhs
pythontech 0:5868e8752d44 1926 goto no_optimisation;
pythontech 0:5868e8752d44 1927 }
pythontech 0:5868e8752d44 1928 compile_node(comp, pns10->nodes[0]); // rhs
pythontech 0:5868e8752d44 1929 compile_node(comp, pns10->nodes[1]); // rhs
pythontech 0:5868e8752d44 1930 compile_node(comp, pns10->nodes[2]); // rhs
pythontech 0:5868e8752d44 1931 EMIT(rot_three);
pythontech 0:5868e8752d44 1932 EMIT(rot_two);
pythontech 0:5868e8752d44 1933 c_assign(comp, pns0->nodes[0], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1934 c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1935 c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1936 } else {
pythontech 0:5868e8752d44 1937 no_optimisation:
pythontech 0:5868e8752d44 1938 compile_node(comp, pns->nodes[1]); // rhs
pythontech 0:5868e8752d44 1939 c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
pythontech 0:5868e8752d44 1940 }
pythontech 0:5868e8752d44 1941 }
pythontech 0:5868e8752d44 1942 } else {
pythontech 0:5868e8752d44 1943 goto plain_assign;
pythontech 0:5868e8752d44 1944 }
pythontech 0:5868e8752d44 1945 }
pythontech 0:5868e8752d44 1946
pythontech 0:5868e8752d44 1947 STATIC void c_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns, mp_binary_op_t binary_op) {
pythontech 0:5868e8752d44 1948 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1949 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 1950 for (int i = 1; i < num_nodes; i += 1) {
pythontech 0:5868e8752d44 1951 compile_node(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 1952 EMIT_ARG(binary_op, binary_op);
pythontech 0:5868e8752d44 1953 }
pythontech 0:5868e8752d44 1954 }
pythontech 0:5868e8752d44 1955
pythontech 0:5868e8752d44 1956 STATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1957 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else));
pythontech 0:5868e8752d44 1958 mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 1959
pythontech 0:5868e8752d44 1960 uint l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 1961 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1962 c_if_cond(comp, pns_test_if_else->nodes[0], false, l_fail); // condition
pythontech 0:5868e8752d44 1963 compile_node(comp, pns->nodes[0]); // success value
pythontech 0:5868e8752d44 1964 EMIT_ARG(jump, l_end);
pythontech 0:5868e8752d44 1965 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 1966 EMIT_ARG(adjust_stack_size, -1); // adjust stack size
pythontech 0:5868e8752d44 1967 compile_node(comp, pns_test_if_else->nodes[1]); // failure value
pythontech 0:5868e8752d44 1968 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1969 }
pythontech 0:5868e8752d44 1970
pythontech 0:5868e8752d44 1971 STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1972 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 1973 // create a new scope for this lambda
pythontech 0:5868e8752d44 1974 scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
pythontech 0:5868e8752d44 1975 // store the lambda scope so the compiling function (this one) can use it at each pass
pythontech 0:5868e8752d44 1976 pns->nodes[2] = (mp_parse_node_t)s;
pythontech 0:5868e8752d44 1977 }
pythontech 0:5868e8752d44 1978
pythontech 0:5868e8752d44 1979 // get the scope for this lambda
pythontech 0:5868e8752d44 1980 scope_t *this_scope = (scope_t*)pns->nodes[2];
pythontech 0:5868e8752d44 1981
pythontech 0:5868e8752d44 1982 // compile the lambda definition
pythontech 0:5868e8752d44 1983 compile_funcdef_lambdef(comp, this_scope, pns->nodes[0], PN_varargslist);
pythontech 0:5868e8752d44 1984 }
pythontech 0:5868e8752d44 1985
pythontech 0:5868e8752d44 1986 STATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns, bool cond) {
pythontech 0:5868e8752d44 1987 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 1988 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 1989 for (int i = 0; i < n; i += 1) {
pythontech 0:5868e8752d44 1990 compile_node(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 1991 if (i + 1 < n) {
pythontech 0:5868e8752d44 1992 EMIT_ARG(jump_if_or_pop, cond, l_end);
pythontech 0:5868e8752d44 1993 }
pythontech 0:5868e8752d44 1994 }
pythontech 0:5868e8752d44 1995 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 1996 }
pythontech 0:5868e8752d44 1997
pythontech 0:5868e8752d44 1998 STATIC void compile_or_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 1999 compile_or_and_test(comp, pns, true);
pythontech 0:5868e8752d44 2000 }
pythontech 0:5868e8752d44 2001
pythontech 0:5868e8752d44 2002 STATIC void compile_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2003 compile_or_and_test(comp, pns, false);
pythontech 0:5868e8752d44 2004 }
pythontech 0:5868e8752d44 2005
pythontech 0:5868e8752d44 2006 STATIC void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2007 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2008 EMIT_ARG(unary_op, MP_UNARY_OP_NOT);
pythontech 0:5868e8752d44 2009 }
pythontech 0:5868e8752d44 2010
pythontech 0:5868e8752d44 2011 STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2012 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2013 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2014 bool multi = (num_nodes > 3);
pythontech 0:5868e8752d44 2015 uint l_fail = 0;
pythontech 0:5868e8752d44 2016 if (multi) {
pythontech 0:5868e8752d44 2017 l_fail = comp_next_label(comp);
pythontech 0:5868e8752d44 2018 }
pythontech 0:5868e8752d44 2019 for (int i = 1; i + 1 < num_nodes; i += 2) {
pythontech 0:5868e8752d44 2020 compile_node(comp, pns->nodes[i + 1]);
pythontech 0:5868e8752d44 2021 if (i + 2 < num_nodes) {
pythontech 0:5868e8752d44 2022 EMIT(dup_top);
pythontech 0:5868e8752d44 2023 EMIT(rot_three);
pythontech 0:5868e8752d44 2024 }
pythontech 0:5868e8752d44 2025 if (MP_PARSE_NODE_IS_TOKEN(pns->nodes[i])) {
pythontech 0:5868e8752d44 2026 mp_binary_op_t op;
pythontech 0:5868e8752d44 2027 switch (MP_PARSE_NODE_LEAF_ARG(pns->nodes[i])) {
pythontech 0:5868e8752d44 2028 case MP_TOKEN_OP_LESS: op = MP_BINARY_OP_LESS; break;
pythontech 0:5868e8752d44 2029 case MP_TOKEN_OP_MORE: op = MP_BINARY_OP_MORE; break;
pythontech 0:5868e8752d44 2030 case MP_TOKEN_OP_DBL_EQUAL: op = MP_BINARY_OP_EQUAL; break;
pythontech 0:5868e8752d44 2031 case MP_TOKEN_OP_LESS_EQUAL: op = MP_BINARY_OP_LESS_EQUAL; break;
pythontech 0:5868e8752d44 2032 case MP_TOKEN_OP_MORE_EQUAL: op = MP_BINARY_OP_MORE_EQUAL; break;
pythontech 0:5868e8752d44 2033 case MP_TOKEN_OP_NOT_EQUAL: op = MP_BINARY_OP_NOT_EQUAL; break;
pythontech 0:5868e8752d44 2034 case MP_TOKEN_KW_IN: default: op = MP_BINARY_OP_IN; break;
pythontech 0:5868e8752d44 2035 }
pythontech 0:5868e8752d44 2036 EMIT_ARG(binary_op, op);
pythontech 0:5868e8752d44 2037 } else {
pythontech 0:5868e8752d44 2038 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i])); // should be
pythontech 0:5868e8752d44 2039 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[i];
pythontech 0:5868e8752d44 2040 int kind = MP_PARSE_NODE_STRUCT_KIND(pns2);
pythontech 0:5868e8752d44 2041 if (kind == PN_comp_op_not_in) {
pythontech 0:5868e8752d44 2042 EMIT_ARG(binary_op, MP_BINARY_OP_NOT_IN);
pythontech 0:5868e8752d44 2043 } else {
pythontech 0:5868e8752d44 2044 assert(kind == PN_comp_op_is); // should be
pythontech 0:5868e8752d44 2045 if (MP_PARSE_NODE_IS_NULL(pns2->nodes[0])) {
pythontech 0:5868e8752d44 2046 EMIT_ARG(binary_op, MP_BINARY_OP_IS);
pythontech 0:5868e8752d44 2047 } else {
pythontech 0:5868e8752d44 2048 EMIT_ARG(binary_op, MP_BINARY_OP_IS_NOT);
pythontech 0:5868e8752d44 2049 }
pythontech 0:5868e8752d44 2050 }
pythontech 0:5868e8752d44 2051 }
pythontech 0:5868e8752d44 2052 if (i + 2 < num_nodes) {
pythontech 0:5868e8752d44 2053 EMIT_ARG(jump_if_or_pop, false, l_fail);
pythontech 0:5868e8752d44 2054 }
pythontech 0:5868e8752d44 2055 }
pythontech 0:5868e8752d44 2056 if (multi) {
pythontech 0:5868e8752d44 2057 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 2058 EMIT_ARG(jump, l_end);
pythontech 0:5868e8752d44 2059 EMIT_ARG(label_assign, l_fail);
pythontech 0:5868e8752d44 2060 EMIT_ARG(adjust_stack_size, 1);
pythontech 0:5868e8752d44 2061 EMIT(rot_two);
pythontech 0:5868e8752d44 2062 EMIT(pop_top);
pythontech 0:5868e8752d44 2063 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 2064 }
pythontech 0:5868e8752d44 2065 }
pythontech 0:5868e8752d44 2066
pythontech 0:5868e8752d44 2067 STATIC void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2068 compile_syntax_error(comp, (mp_parse_node_t)pns, "*x must be assignment target");
pythontech 0:5868e8752d44 2069 }
pythontech 0:5868e8752d44 2070
pythontech 0:5868e8752d44 2071 STATIC void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2072 c_binary_op(comp, pns, MP_BINARY_OP_OR);
pythontech 0:5868e8752d44 2073 }
pythontech 0:5868e8752d44 2074
pythontech 0:5868e8752d44 2075 STATIC void compile_xor_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2076 c_binary_op(comp, pns, MP_BINARY_OP_XOR);
pythontech 0:5868e8752d44 2077 }
pythontech 0:5868e8752d44 2078
pythontech 0:5868e8752d44 2079 STATIC void compile_and_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2080 c_binary_op(comp, pns, MP_BINARY_OP_AND);
pythontech 0:5868e8752d44 2081 }
pythontech 0:5868e8752d44 2082
pythontech 0:5868e8752d44 2083 STATIC void compile_shift_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2084 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2085 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2086 for (int i = 1; i + 1 < num_nodes; i += 2) {
pythontech 0:5868e8752d44 2087 compile_node(comp, pns->nodes[i + 1]);
pythontech 0:5868e8752d44 2088 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_LESS)) {
pythontech 0:5868e8752d44 2089 EMIT_ARG(binary_op, MP_BINARY_OP_LSHIFT);
pythontech 0:5868e8752d44 2090 } else {
pythontech 0:5868e8752d44 2091 assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_MORE)); // should be
pythontech 0:5868e8752d44 2092 EMIT_ARG(binary_op, MP_BINARY_OP_RSHIFT);
pythontech 0:5868e8752d44 2093 }
pythontech 0:5868e8752d44 2094 }
pythontech 0:5868e8752d44 2095 }
pythontech 0:5868e8752d44 2096
pythontech 0:5868e8752d44 2097 STATIC void compile_arith_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2098 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2099 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2100 for (int i = 1; i + 1 < num_nodes; i += 2) {
pythontech 0:5868e8752d44 2101 compile_node(comp, pns->nodes[i + 1]);
pythontech 0:5868e8752d44 2102 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PLUS)) {
pythontech 0:5868e8752d44 2103 EMIT_ARG(binary_op, MP_BINARY_OP_ADD);
pythontech 0:5868e8752d44 2104 } else {
pythontech 0:5868e8752d44 2105 assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_MINUS)); // should be
pythontech 0:5868e8752d44 2106 EMIT_ARG(binary_op, MP_BINARY_OP_SUBTRACT);
pythontech 0:5868e8752d44 2107 }
pythontech 0:5868e8752d44 2108 }
pythontech 0:5868e8752d44 2109 }
pythontech 0:5868e8752d44 2110
pythontech 0:5868e8752d44 2111 STATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2112 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2113 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2114 for (int i = 1; i + 1 < num_nodes; i += 2) {
pythontech 0:5868e8752d44 2115 compile_node(comp, pns->nodes[i + 1]);
pythontech 0:5868e8752d44 2116 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_STAR)) {
pythontech 0:5868e8752d44 2117 EMIT_ARG(binary_op, MP_BINARY_OP_MULTIPLY);
pythontech 0:5868e8752d44 2118 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_DBL_SLASH)) {
pythontech 0:5868e8752d44 2119 EMIT_ARG(binary_op, MP_BINARY_OP_FLOOR_DIVIDE);
pythontech 0:5868e8752d44 2120 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_SLASH)) {
pythontech 0:5868e8752d44 2121 EMIT_ARG(binary_op, MP_BINARY_OP_TRUE_DIVIDE);
pythontech 0:5868e8752d44 2122 } else {
pythontech 0:5868e8752d44 2123 assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[i], MP_TOKEN_OP_PERCENT)); // should be
pythontech 0:5868e8752d44 2124 EMIT_ARG(binary_op, MP_BINARY_OP_MODULO);
pythontech 0:5868e8752d44 2125 }
pythontech 0:5868e8752d44 2126 }
pythontech 0:5868e8752d44 2127 }
pythontech 0:5868e8752d44 2128
pythontech 0:5868e8752d44 2129 STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2130 compile_node(comp, pns->nodes[1]);
pythontech 0:5868e8752d44 2131 if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
pythontech 0:5868e8752d44 2132 EMIT_ARG(unary_op, MP_UNARY_OP_POSITIVE);
pythontech 0:5868e8752d44 2133 } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_MINUS)) {
pythontech 0:5868e8752d44 2134 EMIT_ARG(unary_op, MP_UNARY_OP_NEGATIVE);
pythontech 0:5868e8752d44 2135 } else {
pythontech 0:5868e8752d44 2136 assert(MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_TILDE)); // should be
pythontech 0:5868e8752d44 2137 EMIT_ARG(unary_op, MP_UNARY_OP_INVERT);
pythontech 0:5868e8752d44 2138 }
pythontech 0:5868e8752d44 2139 }
pythontech 0:5868e8752d44 2140
Colin Hogben 2:c89e95946844 2141 STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2142 // this is to handle special super() call
pythontech 0:5868e8752d44 2143 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 2144
pythontech 0:5868e8752d44 2145 compile_generic_all_nodes(comp, pns);
Colin Hogben 2:c89e95946844 2146 }
Colin Hogben 2:c89e95946844 2147
Colin Hogben 2:c89e95946844 2148 STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
Colin Hogben 2:c89e95946844 2149 compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power
Colin Hogben 2:c89e95946844 2150 EMIT_ARG(binary_op, MP_BINARY_OP_POWER);
pythontech 0:5868e8752d44 2151 }
pythontech 0:5868e8752d44 2152
pythontech 0:5868e8752d44 2153 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 2154 // function to call is on top of stack
pythontech 0:5868e8752d44 2155
pythontech 0:5868e8752d44 2156 // this is to handle special super() call
pythontech 0:5868e8752d44 2157 if (MP_PARSE_NODE_IS_NULL(pn_arglist) && comp->func_arg_is_super && comp->scope_cur->kind == SCOPE_FUNCTION) {
pythontech 0:5868e8752d44 2158 compile_load_id(comp, MP_QSTR___class__);
pythontech 0:5868e8752d44 2159 // look for first argument to function (assumes it's "self")
pythontech 0:5868e8752d44 2160 for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
pythontech 0:5868e8752d44 2161 if (comp->scope_cur->id_info[i].flags & ID_FLAG_IS_PARAM) {
pythontech 0:5868e8752d44 2162 // first argument found; load it and call super
pythontech 0:5868e8752d44 2163 EMIT_LOAD_FAST(MP_QSTR_, comp->scope_cur->id_info[i].local_num);
pythontech 0:5868e8752d44 2164 EMIT_ARG(call_function, 2, 0, 0);
pythontech 0:5868e8752d44 2165 return;
pythontech 0:5868e8752d44 2166 }
pythontech 0:5868e8752d44 2167 }
pythontech 0:5868e8752d44 2168 compile_syntax_error(comp, MP_PARSE_NODE_NULL, "super() call cannot find self"); // really a TypeError
pythontech 0:5868e8752d44 2169 return;
pythontech 0:5868e8752d44 2170 }
pythontech 0:5868e8752d44 2171
pythontech 0:5868e8752d44 2172 // get the list of arguments
pythontech 0:5868e8752d44 2173 mp_parse_node_t *args;
pythontech 0:5868e8752d44 2174 int n_args = mp_parse_node_extract_list(&pn_arglist, PN_arglist, &args);
pythontech 0:5868e8752d44 2175
pythontech 0:5868e8752d44 2176 // compile the arguments
pythontech 0:5868e8752d44 2177 // Rather than calling compile_node on the list, we go through the list of args
pythontech 0:5868e8752d44 2178 // explicitly here so that we can count the number of arguments and give sensible
pythontech 0:5868e8752d44 2179 // error messages.
pythontech 0:5868e8752d44 2180 int n_positional = n_positional_extra;
pythontech 0:5868e8752d44 2181 uint n_keyword = 0;
pythontech 0:5868e8752d44 2182 uint star_flags = 0;
pythontech 0:5868e8752d44 2183 mp_parse_node_struct_t *star_args_node = NULL, *dblstar_args_node = NULL;
pythontech 0:5868e8752d44 2184 for (int i = 0; i < n_args; i++) {
pythontech 0:5868e8752d44 2185 if (MP_PARSE_NODE_IS_STRUCT(args[i])) {
pythontech 0:5868e8752d44 2186 mp_parse_node_struct_t *pns_arg = (mp_parse_node_struct_t*)args[i];
pythontech 0:5868e8752d44 2187 if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_star) {
pythontech 0:5868e8752d44 2188 if (star_flags & MP_EMIT_STAR_FLAG_SINGLE) {
pythontech 0:5868e8752d44 2189 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple *x");
pythontech 0:5868e8752d44 2190 return;
pythontech 0:5868e8752d44 2191 }
pythontech 0:5868e8752d44 2192 star_flags |= MP_EMIT_STAR_FLAG_SINGLE;
pythontech 0:5868e8752d44 2193 star_args_node = pns_arg;
pythontech 0:5868e8752d44 2194 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_arglist_dbl_star) {
pythontech 0:5868e8752d44 2195 if (star_flags & MP_EMIT_STAR_FLAG_DOUBLE) {
pythontech 0:5868e8752d44 2196 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "can't have multiple **x");
pythontech 0:5868e8752d44 2197 return;
pythontech 0:5868e8752d44 2198 }
pythontech 0:5868e8752d44 2199 star_flags |= MP_EMIT_STAR_FLAG_DOUBLE;
pythontech 0:5868e8752d44 2200 dblstar_args_node = pns_arg;
pythontech 0:5868e8752d44 2201 } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) {
pythontech 0:5868e8752d44 2202 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_comp_for)) {
pythontech 0:5868e8752d44 2203 if (!MP_PARSE_NODE_IS_ID(pns_arg->nodes[0])) {
pythontech 0:5868e8752d44 2204 compile_syntax_error(comp, (mp_parse_node_t)pns_arg, "LHS of keyword arg must be an id");
pythontech 0:5868e8752d44 2205 return;
pythontech 0:5868e8752d44 2206 }
pythontech 0:5868e8752d44 2207 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns_arg->nodes[0]));
pythontech 0:5868e8752d44 2208 compile_node(comp, pns_arg->nodes[1]);
pythontech 0:5868e8752d44 2209 n_keyword += 1;
pythontech 0:5868e8752d44 2210 } else {
pythontech 0:5868e8752d44 2211 compile_comprehension(comp, pns_arg, SCOPE_GEN_EXPR);
pythontech 0:5868e8752d44 2212 n_positional++;
pythontech 0:5868e8752d44 2213 }
pythontech 0:5868e8752d44 2214 } else {
pythontech 0:5868e8752d44 2215 goto normal_argument;
pythontech 0:5868e8752d44 2216 }
pythontech 0:5868e8752d44 2217 } else {
pythontech 0:5868e8752d44 2218 normal_argument:
pythontech 0:5868e8752d44 2219 if (n_keyword > 0) {
pythontech 0:5868e8752d44 2220 compile_syntax_error(comp, args[i], "non-keyword arg after keyword arg");
pythontech 0:5868e8752d44 2221 return;
pythontech 0:5868e8752d44 2222 }
pythontech 0:5868e8752d44 2223 compile_node(comp, args[i]);
pythontech 0:5868e8752d44 2224 n_positional++;
pythontech 0:5868e8752d44 2225 }
pythontech 0:5868e8752d44 2226 }
pythontech 0:5868e8752d44 2227
pythontech 0:5868e8752d44 2228 // compile the star/double-star arguments if we had them
pythontech 0:5868e8752d44 2229 // if we had one but not the other then we load "null" as a place holder
pythontech 0:5868e8752d44 2230 if (star_flags != 0) {
pythontech 0:5868e8752d44 2231 if (star_args_node == NULL) {
pythontech 0:5868e8752d44 2232 EMIT(load_null);
pythontech 0:5868e8752d44 2233 } else {
pythontech 0:5868e8752d44 2234 compile_node(comp, star_args_node->nodes[0]);
pythontech 0:5868e8752d44 2235 }
pythontech 0:5868e8752d44 2236 if (dblstar_args_node == NULL) {
pythontech 0:5868e8752d44 2237 EMIT(load_null);
pythontech 0:5868e8752d44 2238 } else {
pythontech 0:5868e8752d44 2239 compile_node(comp, dblstar_args_node->nodes[0]);
pythontech 0:5868e8752d44 2240 }
pythontech 0:5868e8752d44 2241 }
pythontech 0:5868e8752d44 2242
pythontech 0:5868e8752d44 2243 // emit the function/method call
pythontech 0:5868e8752d44 2244 if (is_method_call) {
pythontech 0:5868e8752d44 2245 EMIT_ARG(call_method, n_positional, n_keyword, star_flags);
pythontech 0:5868e8752d44 2246 } else {
pythontech 0:5868e8752d44 2247 EMIT_ARG(call_function, n_positional, n_keyword, star_flags);
pythontech 0:5868e8752d44 2248 }
pythontech 0:5868e8752d44 2249 }
pythontech 0:5868e8752d44 2250
Colin Hogben 2:c89e95946844 2251 STATIC void compile_atom_expr_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2252 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2253 for (int i = 0; i < num_nodes; i++) {
pythontech 0:5868e8752d44 2254 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 2255 // optimisation for method calls a.f(...), following PyPy
pythontech 0:5868e8752d44 2256 mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
pythontech 0:5868e8752d44 2257 mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
pythontech 0:5868e8752d44 2258 EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
pythontech 0:5868e8752d44 2259 compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
pythontech 0:5868e8752d44 2260 i += 1;
pythontech 0:5868e8752d44 2261 } else {
pythontech 0:5868e8752d44 2262 compile_node(comp, pns->nodes[i]);
pythontech 0:5868e8752d44 2263 }
pythontech 0:5868e8752d44 2264 comp->func_arg_is_super = false;
pythontech 0:5868e8752d44 2265 }
pythontech 0:5868e8752d44 2266 }
pythontech 0:5868e8752d44 2267
pythontech 0:5868e8752d44 2268 STATIC void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2269 // a list of strings
pythontech 0:5868e8752d44 2270
pythontech 0:5868e8752d44 2271 // check type of list (string or bytes) and count total number of bytes
pythontech 0:5868e8752d44 2272 int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2273 size_t n_bytes = 0;
pythontech 0:5868e8752d44 2274 int string_kind = MP_PARSE_NODE_NULL;
pythontech 0:5868e8752d44 2275 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 2276 int pn_kind;
pythontech 0:5868e8752d44 2277 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[i])) {
pythontech 0:5868e8752d44 2278 pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
pythontech 0:5868e8752d44 2279 assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
pythontech 0:5868e8752d44 2280 n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
pythontech 0:5868e8752d44 2281 } else {
pythontech 0:5868e8752d44 2282 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i]));
pythontech 0:5868e8752d44 2283 mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
pythontech 0:5868e8752d44 2284 if (MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_string) {
pythontech 0:5868e8752d44 2285 pn_kind = MP_PARSE_NODE_STRING;
pythontech 0:5868e8752d44 2286 } else {
pythontech 0:5868e8752d44 2287 assert(MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_bytes);
pythontech 0:5868e8752d44 2288 pn_kind = MP_PARSE_NODE_BYTES;
pythontech 0:5868e8752d44 2289 }
pythontech 0:5868e8752d44 2290 n_bytes += pns_string->nodes[1];
pythontech 0:5868e8752d44 2291 }
pythontech 0:5868e8752d44 2292 if (i == 0) {
pythontech 0:5868e8752d44 2293 string_kind = pn_kind;
pythontech 0:5868e8752d44 2294 } else if (pn_kind != string_kind) {
pythontech 0:5868e8752d44 2295 compile_syntax_error(comp, (mp_parse_node_t)pns, "cannot mix bytes and nonbytes literals");
pythontech 0:5868e8752d44 2296 return;
pythontech 0:5868e8752d44 2297 }
pythontech 0:5868e8752d44 2298 }
pythontech 0:5868e8752d44 2299
pythontech 0:5868e8752d44 2300 // if we are not in the last pass, just load a dummy object
pythontech 0:5868e8752d44 2301 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2302 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2303 return;
pythontech 0:5868e8752d44 2304 }
pythontech 0:5868e8752d44 2305
pythontech 0:5868e8752d44 2306 // concatenate string/bytes
pythontech 0:5868e8752d44 2307 vstr_t vstr;
pythontech 0:5868e8752d44 2308 vstr_init_len(&vstr, n_bytes);
pythontech 0:5868e8752d44 2309 byte *s_dest = (byte*)vstr.buf;
pythontech 0:5868e8752d44 2310 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 2311 if (MP_PARSE_NODE_IS_LEAF(pns->nodes[i])) {
pythontech 0:5868e8752d44 2312 size_t s_len;
pythontech 0:5868e8752d44 2313 const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
pythontech 0:5868e8752d44 2314 memcpy(s_dest, s, s_len);
pythontech 0:5868e8752d44 2315 s_dest += s_len;
pythontech 0:5868e8752d44 2316 } else {
pythontech 0:5868e8752d44 2317 mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
pythontech 0:5868e8752d44 2318 memcpy(s_dest, (const char*)pns_string->nodes[0], pns_string->nodes[1]);
pythontech 0:5868e8752d44 2319 s_dest += pns_string->nodes[1];
pythontech 0:5868e8752d44 2320 }
pythontech 0:5868e8752d44 2321 }
pythontech 0:5868e8752d44 2322
pythontech 0:5868e8752d44 2323 // load the object
pythontech 0:5868e8752d44 2324 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 2325 }
pythontech 0:5868e8752d44 2326
pythontech 0:5868e8752d44 2327 // pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
pythontech 0:5868e8752d44 2328 STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
pythontech 0:5868e8752d44 2329 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
pythontech 0:5868e8752d44 2330 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
pythontech 0:5868e8752d44 2331 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2332
pythontech 0:5868e8752d44 2333 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2334 // create a new scope for this comprehension
pythontech 0:5868e8752d44 2335 scope_t *s = scope_new_and_link(comp, kind, (mp_parse_node_t)pns, comp->scope_cur->emit_options);
pythontech 0:5868e8752d44 2336 // store the comprehension scope so the compiling function (this one) can use it at each pass
pythontech 0:5868e8752d44 2337 pns_comp_for->nodes[3] = (mp_parse_node_t)s;
pythontech 0:5868e8752d44 2338 }
pythontech 0:5868e8752d44 2339
pythontech 0:5868e8752d44 2340 // get the scope for this comprehension
pythontech 0:5868e8752d44 2341 scope_t *this_scope = (scope_t*)pns_comp_for->nodes[3];
pythontech 0:5868e8752d44 2342
pythontech 0:5868e8752d44 2343 // compile the comprehension
pythontech 0:5868e8752d44 2344 close_over_variables_etc(comp, this_scope, 0, 0);
pythontech 0:5868e8752d44 2345
pythontech 0:5868e8752d44 2346 compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
pythontech 0:5868e8752d44 2347 EMIT(get_iter);
pythontech 0:5868e8752d44 2348 EMIT_ARG(call_function, 1, 0, 0);
pythontech 0:5868e8752d44 2349 }
pythontech 0:5868e8752d44 2350
pythontech 0:5868e8752d44 2351 STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2352 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2353 // an empty tuple
pythontech 0:5868e8752d44 2354 c_tuple(comp, MP_PARSE_NODE_NULL, NULL);
pythontech 0:5868e8752d44 2355 } else {
pythontech 0:5868e8752d44 2356 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
pythontech 0:5868e8752d44 2357 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2358 assert(!MP_PARSE_NODE_IS_NULL(pns->nodes[1]));
pythontech 0:5868e8752d44 2359 if (MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])) {
pythontech 0:5868e8752d44 2360 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2361 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3b) {
pythontech 0:5868e8752d44 2362 // tuple of one item, with trailing comma
pythontech 0:5868e8752d44 2363 assert(MP_PARSE_NODE_IS_NULL(pns2->nodes[0]));
pythontech 0:5868e8752d44 2364 c_tuple(comp, pns->nodes[0], NULL);
pythontech 0:5868e8752d44 2365 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_testlist_comp_3c) {
pythontech 0:5868e8752d44 2366 // tuple of many items
pythontech 0:5868e8752d44 2367 c_tuple(comp, pns->nodes[0], pns2);
pythontech 0:5868e8752d44 2368 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_comp_for) {
pythontech 0:5868e8752d44 2369 // generator expression
pythontech 0:5868e8752d44 2370 compile_comprehension(comp, pns, SCOPE_GEN_EXPR);
pythontech 0:5868e8752d44 2371 } else {
pythontech 0:5868e8752d44 2372 // tuple with 2 items
pythontech 0:5868e8752d44 2373 goto tuple_with_2_items;
pythontech 0:5868e8752d44 2374 }
pythontech 0:5868e8752d44 2375 } else {
pythontech 0:5868e8752d44 2376 // tuple with 2 items
pythontech 0:5868e8752d44 2377 tuple_with_2_items:
pythontech 0:5868e8752d44 2378 c_tuple(comp, MP_PARSE_NODE_NULL, pns);
pythontech 0:5868e8752d44 2379 }
pythontech 0:5868e8752d44 2380 }
pythontech 0:5868e8752d44 2381 }
pythontech 0:5868e8752d44 2382
pythontech 0:5868e8752d44 2383 STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2384 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2385 // empty list
pythontech 0:5868e8752d44 2386 EMIT_ARG(build_list, 0);
pythontech 0:5868e8752d44 2387 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
pythontech 0:5868e8752d44 2388 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2389 if (MP_PARSE_NODE_IS_STRUCT(pns2->nodes[1])) {
pythontech 0:5868e8752d44 2390 mp_parse_node_struct_t *pns3 = (mp_parse_node_struct_t*)pns2->nodes[1];
pythontech 0:5868e8752d44 2391 if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3b) {
pythontech 0:5868e8752d44 2392 // list of one item, with trailing comma
pythontech 0:5868e8752d44 2393 assert(MP_PARSE_NODE_IS_NULL(pns3->nodes[0]));
pythontech 0:5868e8752d44 2394 compile_node(comp, pns2->nodes[0]);
pythontech 0:5868e8752d44 2395 EMIT_ARG(build_list, 1);
pythontech 0:5868e8752d44 2396 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_testlist_comp_3c) {
pythontech 0:5868e8752d44 2397 // list of many items
pythontech 0:5868e8752d44 2398 compile_node(comp, pns2->nodes[0]);
pythontech 0:5868e8752d44 2399 compile_generic_all_nodes(comp, pns3);
pythontech 0:5868e8752d44 2400 EMIT_ARG(build_list, 1 + MP_PARSE_NODE_STRUCT_NUM_NODES(pns3));
pythontech 0:5868e8752d44 2401 } else if (MP_PARSE_NODE_STRUCT_KIND(pns3) == PN_comp_for) {
pythontech 0:5868e8752d44 2402 // list comprehension
pythontech 0:5868e8752d44 2403 compile_comprehension(comp, pns2, SCOPE_LIST_COMP);
pythontech 0:5868e8752d44 2404 } else {
pythontech 0:5868e8752d44 2405 // list with 2 items
pythontech 0:5868e8752d44 2406 goto list_with_2_items;
pythontech 0:5868e8752d44 2407 }
pythontech 0:5868e8752d44 2408 } else {
pythontech 0:5868e8752d44 2409 // list with 2 items
pythontech 0:5868e8752d44 2410 list_with_2_items:
pythontech 0:5868e8752d44 2411 compile_node(comp, pns2->nodes[0]);
pythontech 0:5868e8752d44 2412 compile_node(comp, pns2->nodes[1]);
pythontech 0:5868e8752d44 2413 EMIT_ARG(build_list, 2);
pythontech 0:5868e8752d44 2414 }
pythontech 0:5868e8752d44 2415 } else {
pythontech 0:5868e8752d44 2416 // list with 1 item
pythontech 0:5868e8752d44 2417 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2418 EMIT_ARG(build_list, 1);
pythontech 0:5868e8752d44 2419 }
pythontech 0:5868e8752d44 2420 }
pythontech 0:5868e8752d44 2421
pythontech 0:5868e8752d44 2422 STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2423 mp_parse_node_t pn = pns->nodes[0];
pythontech 0:5868e8752d44 2424 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 2425 // empty dict
pythontech 0:5868e8752d44 2426 EMIT_ARG(build_map, 0);
pythontech 0:5868e8752d44 2427 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 2428 pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2429 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker_item) {
pythontech 0:5868e8752d44 2430 // dict with one element
pythontech 0:5868e8752d44 2431 EMIT_ARG(build_map, 1);
pythontech 0:5868e8752d44 2432 compile_node(comp, pn);
pythontech 0:5868e8752d44 2433 EMIT(store_map);
pythontech 0:5868e8752d44 2434 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_dictorsetmaker) {
pythontech 0:5868e8752d44 2435 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should succeed
pythontech 0:5868e8752d44 2436 mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2437 if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_dictorsetmaker_list) {
pythontech 0:5868e8752d44 2438 // dict/set with multiple elements
pythontech 0:5868e8752d44 2439
pythontech 0:5868e8752d44 2440 // get tail elements (2nd, 3rd, ...)
pythontech 0:5868e8752d44 2441 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 2442 int n = mp_parse_node_extract_list(&pns1->nodes[0], PN_dictorsetmaker_list2, &nodes);
pythontech 0:5868e8752d44 2443
pythontech 0:5868e8752d44 2444 // first element sets whether it's a dict or set
pythontech 0:5868e8752d44 2445 bool is_dict;
pythontech 0:5868e8752d44 2446 if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
pythontech 0:5868e8752d44 2447 // a dictionary
pythontech 0:5868e8752d44 2448 EMIT_ARG(build_map, 1 + n);
pythontech 0:5868e8752d44 2449 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2450 EMIT(store_map);
pythontech 0:5868e8752d44 2451 is_dict = true;
pythontech 0:5868e8752d44 2452 } else {
pythontech 0:5868e8752d44 2453 // a set
pythontech 0:5868e8752d44 2454 compile_node(comp, pns->nodes[0]); // 1st value of set
pythontech 0:5868e8752d44 2455 is_dict = false;
pythontech 0:5868e8752d44 2456 }
pythontech 0:5868e8752d44 2457
pythontech 0:5868e8752d44 2458 // process rest of elements
pythontech 0:5868e8752d44 2459 for (int i = 0; i < n; i++) {
pythontech 0:5868e8752d44 2460 mp_parse_node_t pn_i = nodes[i];
pythontech 0:5868e8752d44 2461 bool is_key_value = MP_PARSE_NODE_IS_STRUCT_KIND(pn_i, PN_dictorsetmaker_item);
pythontech 0:5868e8752d44 2462 compile_node(comp, pn_i);
pythontech 0:5868e8752d44 2463 if (is_dict) {
pythontech 0:5868e8752d44 2464 if (!is_key_value) {
pythontech 0:5868e8752d44 2465 compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dictionary");
pythontech 0:5868e8752d44 2466 return;
pythontech 0:5868e8752d44 2467 }
pythontech 0:5868e8752d44 2468 EMIT(store_map);
pythontech 0:5868e8752d44 2469 } else {
pythontech 0:5868e8752d44 2470 if (is_key_value) {
pythontech 0:5868e8752d44 2471 compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
pythontech 0:5868e8752d44 2472 return;
pythontech 0:5868e8752d44 2473 }
pythontech 0:5868e8752d44 2474 }
pythontech 0:5868e8752d44 2475 }
pythontech 0:5868e8752d44 2476
pythontech 0:5868e8752d44 2477 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 2478 // if it's a set, build it
pythontech 0:5868e8752d44 2479 if (!is_dict) {
pythontech 0:5868e8752d44 2480 EMIT_ARG(build_set, 1 + n);
pythontech 0:5868e8752d44 2481 }
pythontech 0:5868e8752d44 2482 #endif
pythontech 0:5868e8752d44 2483 } else {
pythontech 0:5868e8752d44 2484 assert(MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_comp_for); // should be
pythontech 0:5868e8752d44 2485 // dict/set comprehension
pythontech 0:5868e8752d44 2486 if (!MICROPY_PY_BUILTINS_SET || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_dictorsetmaker_item)) {
pythontech 0:5868e8752d44 2487 // a dictionary comprehension
pythontech 0:5868e8752d44 2488 compile_comprehension(comp, pns, SCOPE_DICT_COMP);
pythontech 0:5868e8752d44 2489 } else {
pythontech 0:5868e8752d44 2490 // a set comprehension
pythontech 0:5868e8752d44 2491 compile_comprehension(comp, pns, SCOPE_SET_COMP);
pythontech 0:5868e8752d44 2492 }
pythontech 0:5868e8752d44 2493 }
pythontech 0:5868e8752d44 2494 } else {
pythontech 0:5868e8752d44 2495 // set with one element
pythontech 0:5868e8752d44 2496 goto set_with_one_element;
pythontech 0:5868e8752d44 2497 }
pythontech 0:5868e8752d44 2498 } else {
pythontech 0:5868e8752d44 2499 // set with one element
pythontech 0:5868e8752d44 2500 set_with_one_element:
pythontech 0:5868e8752d44 2501 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 2502 compile_node(comp, pn);
pythontech 0:5868e8752d44 2503 EMIT_ARG(build_set, 1);
pythontech 0:5868e8752d44 2504 #else
pythontech 0:5868e8752d44 2505 assert(0);
pythontech 0:5868e8752d44 2506 #endif
pythontech 0:5868e8752d44 2507 }
pythontech 0:5868e8752d44 2508 }
pythontech 0:5868e8752d44 2509
pythontech 0:5868e8752d44 2510 STATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2511 compile_trailer_paren_helper(comp, pns->nodes[0], false, 0);
pythontech 0:5868e8752d44 2512 }
pythontech 0:5868e8752d44 2513
pythontech 0:5868e8752d44 2514 STATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2515 // object who's index we want is on top of stack
pythontech 0:5868e8752d44 2516 compile_node(comp, pns->nodes[0]); // the index
pythontech 0:5868e8752d44 2517 EMIT(load_subscr);
pythontech 0:5868e8752d44 2518 }
pythontech 0:5868e8752d44 2519
pythontech 0:5868e8752d44 2520 STATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2521 // object who's attribute we want is on top of stack
pythontech 0:5868e8752d44 2522 EMIT_ARG(load_attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // attribute to get
pythontech 0:5868e8752d44 2523 }
pythontech 0:5868e8752d44 2524
pythontech 0:5868e8752d44 2525 #if MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 2526 STATIC void compile_subscript_3_helper(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2527 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3); // should always be
pythontech 0:5868e8752d44 2528 mp_parse_node_t pn = pns->nodes[0];
pythontech 0:5868e8752d44 2529 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 2530 // [?:]
pythontech 0:5868e8752d44 2531 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2532 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2533 } else if (MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 2534 pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2535 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3c) {
pythontech 0:5868e8752d44 2536 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2537 pn = pns->nodes[0];
pythontech 0:5868e8752d44 2538 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 2539 // [?::]
pythontech 0:5868e8752d44 2540 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2541 } else {
pythontech 0:5868e8752d44 2542 // [?::x]
pythontech 0:5868e8752d44 2543 compile_node(comp, pn);
pythontech 0:5868e8752d44 2544 EMIT_ARG(build_slice, 3);
pythontech 0:5868e8752d44 2545 }
pythontech 0:5868e8752d44 2546 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_3d) {
pythontech 0:5868e8752d44 2547 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2548 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
pythontech 0:5868e8752d44 2549 pns = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 2550 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_sliceop); // should always be
pythontech 0:5868e8752d44 2551 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2552 // [?:x:]
pythontech 0:5868e8752d44 2553 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2554 } else {
pythontech 0:5868e8752d44 2555 // [?:x:x]
pythontech 0:5868e8752d44 2556 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2557 EMIT_ARG(build_slice, 3);
pythontech 0:5868e8752d44 2558 }
pythontech 0:5868e8752d44 2559 } else {
pythontech 0:5868e8752d44 2560 // [?:x]
pythontech 0:5868e8752d44 2561 compile_node(comp, pn);
pythontech 0:5868e8752d44 2562 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2563 }
pythontech 0:5868e8752d44 2564 } else {
pythontech 0:5868e8752d44 2565 // [?:x]
pythontech 0:5868e8752d44 2566 compile_node(comp, pn);
pythontech 0:5868e8752d44 2567 EMIT_ARG(build_slice, 2);
pythontech 0:5868e8752d44 2568 }
pythontech 0:5868e8752d44 2569 }
pythontech 0:5868e8752d44 2570
pythontech 0:5868e8752d44 2571 STATIC void compile_subscript_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2572 compile_node(comp, pns->nodes[0]); // start of slice
pythontech 0:5868e8752d44 2573 assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be
pythontech 0:5868e8752d44 2574 compile_subscript_3_helper(comp, (mp_parse_node_struct_t*)pns->nodes[1]);
pythontech 0:5868e8752d44 2575 }
pythontech 0:5868e8752d44 2576
pythontech 0:5868e8752d44 2577 STATIC void compile_subscript_3(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2578 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2579 compile_subscript_3_helper(comp, pns);
pythontech 0:5868e8752d44 2580 }
pythontech 0:5868e8752d44 2581 #endif // MICROPY_PY_BUILTINS_SLICE
pythontech 0:5868e8752d44 2582
pythontech 0:5868e8752d44 2583 STATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2584 // if this is called then we are compiling a dict key:value pair
pythontech 0:5868e8752d44 2585 compile_node(comp, pns->nodes[1]); // value
pythontech 0:5868e8752d44 2586 compile_node(comp, pns->nodes[0]); // key
pythontech 0:5868e8752d44 2587 }
pythontech 0:5868e8752d44 2588
pythontech 0:5868e8752d44 2589 STATIC void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2590 qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options);
pythontech 0:5868e8752d44 2591 // store class object into class name
pythontech 0:5868e8752d44 2592 compile_store_id(comp, cname);
pythontech 0:5868e8752d44 2593 }
pythontech 0:5868e8752d44 2594
pythontech 0:5868e8752d44 2595 STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2596 if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {
pythontech 0:5868e8752d44 2597 compile_syntax_error(comp, (mp_parse_node_t)pns, "'yield' outside function");
pythontech 0:5868e8752d44 2598 return;
pythontech 0:5868e8752d44 2599 }
pythontech 0:5868e8752d44 2600 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2601 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2602 EMIT(yield_value);
pythontech 0:5868e8752d44 2603 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) {
pythontech 0:5868e8752d44 2604 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2605 compile_node(comp, pns->nodes[0]);
Colin Hogben 2:c89e95946844 2606 compile_yield_from(comp);
pythontech 0:5868e8752d44 2607 } else {
pythontech 0:5868e8752d44 2608 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2609 EMIT(yield_value);
pythontech 0:5868e8752d44 2610 }
pythontech 0:5868e8752d44 2611 }
pythontech 0:5868e8752d44 2612
Colin Hogben 2:c89e95946844 2613 #if MICROPY_PY_ASYNC_AWAIT
Colin Hogben 2:c89e95946844 2614 STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pns) {
Colin Hogben 2:c89e95946844 2615 if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) {
Colin Hogben 2:c89e95946844 2616 compile_syntax_error(comp, (mp_parse_node_t)pns, "'await' outside function");
Colin Hogben 2:c89e95946844 2617 return;
Colin Hogben 2:c89e95946844 2618 }
Colin Hogben 2:c89e95946844 2619 compile_atom_expr_normal(comp, pns);
Colin Hogben 2:c89e95946844 2620 compile_yield_from(comp);
Colin Hogben 2:c89e95946844 2621 }
Colin Hogben 2:c89e95946844 2622 #endif
Colin Hogben 2:c89e95946844 2623
pythontech 0:5868e8752d44 2624 STATIC void compile_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2625 // only create and load the actual str object on the last pass
pythontech 0:5868e8752d44 2626 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2627 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2628 } else {
pythontech 0:5868e8752d44 2629 EMIT_ARG(load_const_obj, mp_obj_new_str((const char*)pns->nodes[0], pns->nodes[1], false));
pythontech 0:5868e8752d44 2630 }
pythontech 0:5868e8752d44 2631 }
pythontech 0:5868e8752d44 2632
pythontech 0:5868e8752d44 2633 STATIC void compile_bytes(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2634 // only create and load the actual bytes object on the last pass
pythontech 0:5868e8752d44 2635 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2636 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2637 } else {
pythontech 0:5868e8752d44 2638 EMIT_ARG(load_const_obj, mp_obj_new_bytes((const byte*)pns->nodes[0], pns->nodes[1]));
pythontech 0:5868e8752d44 2639 }
pythontech 0:5868e8752d44 2640 }
pythontech 0:5868e8752d44 2641
pythontech 0:5868e8752d44 2642 STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
pythontech 0:5868e8752d44 2643 #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
pythontech 0:5868e8752d44 2644 // nodes are 32-bit pointers, but need to extract 64-bit object
pythontech 0:5868e8752d44 2645 EMIT_ARG(load_const_obj, (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
pythontech 0:5868e8752d44 2646 #else
pythontech 0:5868e8752d44 2647 EMIT_ARG(load_const_obj, (mp_obj_t)pns->nodes[0]);
pythontech 0:5868e8752d44 2648 #endif
pythontech 0:5868e8752d44 2649 }
pythontech 0:5868e8752d44 2650
pythontech 0:5868e8752d44 2651 typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
pythontech 0:5868e8752d44 2652 STATIC compile_function_t compile_function[] = {
pythontech 0:5868e8752d44 2653 #define nc NULL
pythontech 0:5868e8752d44 2654 #define c(f) compile_##f
pythontech 0:5868e8752d44 2655 #define DEF_RULE(rule, comp, kind, ...) comp,
pythontech 0:5868e8752d44 2656 #include "py/grammar.h"
pythontech 0:5868e8752d44 2657 #undef nc
pythontech 0:5868e8752d44 2658 #undef c
pythontech 0:5868e8752d44 2659 #undef DEF_RULE
pythontech 0:5868e8752d44 2660 NULL,
pythontech 0:5868e8752d44 2661 compile_string,
pythontech 0:5868e8752d44 2662 compile_bytes,
pythontech 0:5868e8752d44 2663 compile_const_object,
pythontech 0:5868e8752d44 2664 };
pythontech 0:5868e8752d44 2665
pythontech 0:5868e8752d44 2666 STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2667 if (MP_PARSE_NODE_IS_NULL(pn)) {
pythontech 0:5868e8752d44 2668 // pass
pythontech 0:5868e8752d44 2669 } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
pythontech 0:5868e8752d44 2670 mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
pythontech 0:5868e8752d44 2671 #if MICROPY_DYNAMIC_COMPILER
pythontech 0:5868e8752d44 2672 mp_uint_t sign_mask = -(1 << (mp_dynamic_compiler.small_int_bits - 1));
pythontech 0:5868e8752d44 2673 if ((arg & sign_mask) == 0 || (arg & sign_mask) == sign_mask) {
pythontech 0:5868e8752d44 2674 // integer fits in target runtime's small-int
pythontech 0:5868e8752d44 2675 EMIT_ARG(load_const_small_int, arg);
pythontech 0:5868e8752d44 2676 } else {
pythontech 0:5868e8752d44 2677 // integer doesn't fit, so create a multi-precision int object
pythontech 0:5868e8752d44 2678 // (but only create the actual object on the last pass)
pythontech 0:5868e8752d44 2679 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2680 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2681 } else {
pythontech 0:5868e8752d44 2682 EMIT_ARG(load_const_obj, mp_obj_new_int_from_ll(arg));
pythontech 0:5868e8752d44 2683 }
pythontech 0:5868e8752d44 2684 }
pythontech 0:5868e8752d44 2685 #else
pythontech 0:5868e8752d44 2686 EMIT_ARG(load_const_small_int, arg);
pythontech 0:5868e8752d44 2687 #endif
pythontech 0:5868e8752d44 2688 } else if (MP_PARSE_NODE_IS_LEAF(pn)) {
pythontech 0:5868e8752d44 2689 uintptr_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 2690 switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
pythontech 0:5868e8752d44 2691 case MP_PARSE_NODE_ID: compile_load_id(comp, arg); break;
pythontech 0:5868e8752d44 2692 case MP_PARSE_NODE_STRING: EMIT_ARG(load_const_str, arg); break;
pythontech 0:5868e8752d44 2693 case MP_PARSE_NODE_BYTES:
pythontech 0:5868e8752d44 2694 // only create and load the actual bytes object on the last pass
pythontech 0:5868e8752d44 2695 if (comp->pass != MP_PASS_EMIT) {
pythontech 0:5868e8752d44 2696 EMIT_ARG(load_const_obj, mp_const_none);
pythontech 0:5868e8752d44 2697 } else {
pythontech 0:5868e8752d44 2698 size_t len;
pythontech 0:5868e8752d44 2699 const byte *data = qstr_data(arg, &len);
pythontech 0:5868e8752d44 2700 EMIT_ARG(load_const_obj, mp_obj_new_bytes(data, len));
pythontech 0:5868e8752d44 2701 }
pythontech 0:5868e8752d44 2702 break;
pythontech 0:5868e8752d44 2703 case MP_PARSE_NODE_TOKEN: default:
pythontech 0:5868e8752d44 2704 if (arg == MP_TOKEN_NEWLINE) {
pythontech 0:5868e8752d44 2705 // this can occur when file_input lets through a NEWLINE (eg if file starts with a newline)
pythontech 0:5868e8752d44 2706 // or when single_input lets through a NEWLINE (user enters a blank line)
pythontech 0:5868e8752d44 2707 // do nothing
pythontech 0:5868e8752d44 2708 } else {
pythontech 0:5868e8752d44 2709 EMIT_ARG(load_const_tok, arg);
pythontech 0:5868e8752d44 2710 }
pythontech 0:5868e8752d44 2711 break;
pythontech 0:5868e8752d44 2712 }
pythontech 0:5868e8752d44 2713 } else {
pythontech 0:5868e8752d44 2714 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2715 EMIT_ARG(set_source_line, pns->source_line);
pythontech 0:5868e8752d44 2716 compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
pythontech 0:5868e8752d44 2717 if (f == NULL) {
pythontech 0:5868e8752d44 2718 #if MICROPY_DEBUG_PRINTERS
pythontech 0:5868e8752d44 2719 printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
pythontech 0:5868e8752d44 2720 mp_parse_node_print(pn, 0);
pythontech 0:5868e8752d44 2721 #endif
pythontech 0:5868e8752d44 2722 compile_syntax_error(comp, pn, "internal compiler error");
pythontech 0:5868e8752d44 2723 } else {
pythontech 0:5868e8752d44 2724 f(comp, pns);
pythontech 0:5868e8752d44 2725 }
pythontech 0:5868e8752d44 2726 }
pythontech 0:5868e8752d44 2727 }
pythontech 0:5868e8752d44 2728
pythontech 0:5868e8752d44 2729 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 2730 // check that **kw is last
pythontech 0:5868e8752d44 2731 if ((comp->scope_cur->scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
pythontech 0:5868e8752d44 2732 compile_syntax_error(comp, pn, "invalid syntax");
pythontech 0:5868e8752d44 2733 return;
pythontech 0:5868e8752d44 2734 }
pythontech 0:5868e8752d44 2735
pythontech 0:5868e8752d44 2736 qstr param_name = MP_QSTR_NULL;
pythontech 0:5868e8752d44 2737 uint param_flag = ID_FLAG_IS_PARAM;
pythontech 0:5868e8752d44 2738 if (MP_PARSE_NODE_IS_ID(pn)) {
pythontech 0:5868e8752d44 2739 param_name = MP_PARSE_NODE_LEAF_ARG(pn);
pythontech 0:5868e8752d44 2740 if (comp->have_star) {
pythontech 0:5868e8752d44 2741 // comes after a star, so counts as a keyword-only parameter
pythontech 0:5868e8752d44 2742 comp->scope_cur->num_kwonly_args += 1;
pythontech 0:5868e8752d44 2743 } else {
pythontech 0:5868e8752d44 2744 // comes before a star, so counts as a positional parameter
pythontech 0:5868e8752d44 2745 comp->scope_cur->num_pos_args += 1;
pythontech 0:5868e8752d44 2746 }
pythontech 0:5868e8752d44 2747 } else {
pythontech 0:5868e8752d44 2748 assert(MP_PARSE_NODE_IS_STRUCT(pn));
pythontech 0:5868e8752d44 2749 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2750 if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_name) {
pythontech 0:5868e8752d44 2751 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2752 if (comp->have_star) {
pythontech 0:5868e8752d44 2753 // comes after a star, so counts as a keyword-only parameter
pythontech 0:5868e8752d44 2754 comp->scope_cur->num_kwonly_args += 1;
pythontech 0:5868e8752d44 2755 } else {
pythontech 0:5868e8752d44 2756 // comes before a star, so counts as a positional parameter
pythontech 0:5868e8752d44 2757 comp->scope_cur->num_pos_args += 1;
pythontech 0:5868e8752d44 2758 }
pythontech 0:5868e8752d44 2759 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == pn_star) {
pythontech 0:5868e8752d44 2760 if (comp->have_star) {
pythontech 0:5868e8752d44 2761 // more than one star
pythontech 0:5868e8752d44 2762 compile_syntax_error(comp, pn, "invalid syntax");
pythontech 0:5868e8752d44 2763 return;
pythontech 0:5868e8752d44 2764 }
pythontech 0:5868e8752d44 2765 comp->have_star = true;
pythontech 0:5868e8752d44 2766 param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM;
pythontech 0:5868e8752d44 2767 if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
pythontech 0:5868e8752d44 2768 // bare star
pythontech 0:5868e8752d44 2769 // TODO see http://www.python.org/dev/peps/pep-3102/
pythontech 0:5868e8752d44 2770 //assert(comp->scope_cur->num_dict_params == 0);
pythontech 0:5868e8752d44 2771 } else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
pythontech 0:5868e8752d44 2772 // named star
pythontech 0:5868e8752d44 2773 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
pythontech 0:5868e8752d44 2774 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2775 } else {
pythontech 0:5868e8752d44 2776 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)); // should be
pythontech 0:5868e8752d44 2777 // named star with possible annotation
pythontech 0:5868e8752d44 2778 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARARGS;
pythontech 0:5868e8752d44 2779 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2780 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2781 }
pythontech 0:5868e8752d44 2782 } else {
pythontech 0:5868e8752d44 2783 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == pn_dbl_star); // should be
pythontech 0:5868e8752d44 2784 param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2785 param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_DBL_STAR_PARAM;
pythontech 0:5868e8752d44 2786 comp->scope_cur->scope_flags |= MP_SCOPE_FLAG_VARKEYWORDS;
pythontech 0:5868e8752d44 2787 }
pythontech 0:5868e8752d44 2788 }
pythontech 0:5868e8752d44 2789
pythontech 0:5868e8752d44 2790 if (param_name != MP_QSTR_NULL) {
pythontech 0:5868e8752d44 2791 bool added;
pythontech 0:5868e8752d44 2792 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
pythontech 0:5868e8752d44 2793 if (!added) {
pythontech 0:5868e8752d44 2794 compile_syntax_error(comp, pn, "name reused for argument");
pythontech 0:5868e8752d44 2795 return;
pythontech 0:5868e8752d44 2796 }
pythontech 0:5868e8752d44 2797 id_info->kind = ID_INFO_KIND_LOCAL;
pythontech 0:5868e8752d44 2798 id_info->flags = param_flag;
pythontech 0:5868e8752d44 2799 }
pythontech 0:5868e8752d44 2800 }
pythontech 0:5868e8752d44 2801
pythontech 0:5868e8752d44 2802 STATIC void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2803 compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star);
pythontech 0:5868e8752d44 2804 }
pythontech 0:5868e8752d44 2805
pythontech 0:5868e8752d44 2806 STATIC void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2807 compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star);
pythontech 0:5868e8752d44 2808 }
pythontech 0:5868e8752d44 2809
pythontech 0:5868e8752d44 2810 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 2811 STATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2812 if (!MP_PARSE_NODE_IS_STRUCT(pn)) {
pythontech 0:5868e8752d44 2813 // no annotation
pythontech 0:5868e8752d44 2814 return;
pythontech 0:5868e8752d44 2815 }
pythontech 0:5868e8752d44 2816
pythontech 0:5868e8752d44 2817 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2818 if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_name) {
pythontech 0:5868e8752d44 2819 // named parameter with possible annotation
pythontech 0:5868e8752d44 2820 // fallthrough
pythontech 0:5868e8752d44 2821 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_star) {
pythontech 0:5868e8752d44 2822 if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_tfpdef)) {
pythontech 0:5868e8752d44 2823 // named star with possible annotation
pythontech 0:5868e8752d44 2824 pns = (mp_parse_node_struct_t*)pns->nodes[0];
pythontech 0:5868e8752d44 2825 // fallthrough
pythontech 0:5868e8752d44 2826 } else {
pythontech 0:5868e8752d44 2827 // no annotation
pythontech 0:5868e8752d44 2828 return;
pythontech 0:5868e8752d44 2829 }
pythontech 0:5868e8752d44 2830 } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star) {
pythontech 0:5868e8752d44 2831 // double star with possible annotation
pythontech 0:5868e8752d44 2832 // fallthrough
pythontech 0:5868e8752d44 2833 } else {
pythontech 0:5868e8752d44 2834 // no annotation
pythontech 0:5868e8752d44 2835 return;
pythontech 0:5868e8752d44 2836 }
pythontech 0:5868e8752d44 2837
pythontech 0:5868e8752d44 2838 mp_parse_node_t pn_annotation = pns->nodes[1];
pythontech 0:5868e8752d44 2839
pythontech 0:5868e8752d44 2840 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
pythontech 0:5868e8752d44 2841 qstr param_name = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]);
pythontech 0:5868e8752d44 2842 id_info_t *id_info = scope_find(comp->scope_cur, param_name);
pythontech 0:5868e8752d44 2843 assert(id_info != NULL);
pythontech 0:5868e8752d44 2844
pythontech 0:5868e8752d44 2845 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
pythontech 0:5868e8752d44 2846 qstr arg_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
pythontech 0:5868e8752d44 2847 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ARG, id_info->local_num, arg_type);
pythontech 0:5868e8752d44 2848 } else {
pythontech 0:5868e8752d44 2849 compile_syntax_error(comp, pn_annotation, "parameter annotation must be an identifier");
pythontech 0:5868e8752d44 2850 }
pythontech 0:5868e8752d44 2851 }
pythontech 0:5868e8752d44 2852 }
pythontech 0:5868e8752d44 2853 #endif // MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 2854
pythontech 0:5868e8752d44 2855 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 2856 uint l_top = comp_next_label(comp);
pythontech 0:5868e8752d44 2857 uint l_end = comp_next_label(comp);
pythontech 0:5868e8752d44 2858 EMIT_ARG(label_assign, l_top);
pythontech 0:5868e8752d44 2859 EMIT_ARG(for_iter, l_end);
pythontech 0:5868e8752d44 2860 c_assign(comp, pns_comp_for->nodes[0], ASSIGN_STORE);
pythontech 0:5868e8752d44 2861 mp_parse_node_t pn_iter = pns_comp_for->nodes[2];
pythontech 0:5868e8752d44 2862
pythontech 0:5868e8752d44 2863 tail_recursion:
pythontech 0:5868e8752d44 2864 if (MP_PARSE_NODE_IS_NULL(pn_iter)) {
pythontech 0:5868e8752d44 2865 // no more nested if/for; compile inner expression
pythontech 0:5868e8752d44 2866 compile_node(comp, pn_inner_expr);
pythontech 0:5868e8752d44 2867 if (comp->scope_cur->kind == SCOPE_LIST_COMP) {
pythontech 0:5868e8752d44 2868 EMIT_ARG(list_append, for_depth + 2);
pythontech 0:5868e8752d44 2869 } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) {
pythontech 0:5868e8752d44 2870 EMIT_ARG(map_add, for_depth + 2);
pythontech 0:5868e8752d44 2871 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 2872 } else if (comp->scope_cur->kind == SCOPE_SET_COMP) {
pythontech 0:5868e8752d44 2873 EMIT_ARG(set_add, for_depth + 2);
pythontech 0:5868e8752d44 2874 #endif
pythontech 0:5868e8752d44 2875 } else {
pythontech 0:5868e8752d44 2876 EMIT(yield_value);
pythontech 0:5868e8752d44 2877 EMIT(pop_top);
pythontech 0:5868e8752d44 2878 }
pythontech 0:5868e8752d44 2879 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
pythontech 0:5868e8752d44 2880 // if condition
pythontech 0:5868e8752d44 2881 mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
pythontech 0:5868e8752d44 2882 c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
pythontech 0:5868e8752d44 2883 pn_iter = pns_comp_if->nodes[1];
pythontech 0:5868e8752d44 2884 goto tail_recursion;
pythontech 0:5868e8752d44 2885 } else {
pythontech 0:5868e8752d44 2886 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)); // should be
pythontech 0:5868e8752d44 2887 // for loop
pythontech 0:5868e8752d44 2888 mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
pythontech 0:5868e8752d44 2889 compile_node(comp, pns_comp_for2->nodes[1]);
pythontech 0:5868e8752d44 2890 EMIT(get_iter);
pythontech 0:5868e8752d44 2891 compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1);
pythontech 0:5868e8752d44 2892 }
pythontech 0:5868e8752d44 2893
pythontech 0:5868e8752d44 2894 EMIT_ARG(jump, l_top);
pythontech 0:5868e8752d44 2895 EMIT_ARG(label_assign, l_end);
pythontech 0:5868e8752d44 2896 EMIT(for_iter_end);
pythontech 0:5868e8752d44 2897 }
pythontech 0:5868e8752d44 2898
pythontech 0:5868e8752d44 2899 STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
pythontech 0:5868e8752d44 2900 #if MICROPY_ENABLE_DOC_STRING
pythontech 0:5868e8752d44 2901 // see http://www.python.org/dev/peps/pep-0257/
pythontech 0:5868e8752d44 2902
pythontech 0:5868e8752d44 2903 // look for the first statement
pythontech 0:5868e8752d44 2904 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
pythontech 0:5868e8752d44 2905 // a statement; fall through
pythontech 0:5868e8752d44 2906 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_file_input_2)) {
pythontech 0:5868e8752d44 2907 // file input; find the first non-newline node
pythontech 0:5868e8752d44 2908 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2909 int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
pythontech 0:5868e8752d44 2910 for (int i = 0; i < num_nodes; i++) {
pythontech 0:5868e8752d44 2911 pn = pns->nodes[i];
pythontech 0:5868e8752d44 2912 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 2913 // not a newline, so this is the first statement; finish search
pythontech 0:5868e8752d44 2914 break;
pythontech 0:5868e8752d44 2915 }
pythontech 0:5868e8752d44 2916 }
pythontech 0:5868e8752d44 2917 // 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 2918 } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_suite_block_stmts)) {
pythontech 0:5868e8752d44 2919 // a list of statements; get the first one
pythontech 0:5868e8752d44 2920 pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
pythontech 0:5868e8752d44 2921 } else {
pythontech 0:5868e8752d44 2922 return;
pythontech 0:5868e8752d44 2923 }
pythontech 0:5868e8752d44 2924
pythontech 0:5868e8752d44 2925 // check the first statement for a doc string
pythontech 0:5868e8752d44 2926 if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_expr_stmt)) {
pythontech 0:5868e8752d44 2927 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pythontech 0:5868e8752d44 2928 if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])
pythontech 0:5868e8752d44 2929 && MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)
pythontech 0:5868e8752d44 2930 || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)) {
pythontech 0:5868e8752d44 2931 // compile the doc string
pythontech 0:5868e8752d44 2932 compile_node(comp, pns->nodes[0]);
pythontech 0:5868e8752d44 2933 // store the doc string
pythontech 0:5868e8752d44 2934 compile_store_id(comp, MP_QSTR___doc__);
pythontech 0:5868e8752d44 2935 }
pythontech 0:5868e8752d44 2936 }
pythontech 0:5868e8752d44 2937 #else
pythontech 0:5868e8752d44 2938 (void)comp;
pythontech 0:5868e8752d44 2939 (void)pn;
pythontech 0:5868e8752d44 2940 #endif
pythontech 0:5868e8752d44 2941 }
pythontech 0:5868e8752d44 2942
pythontech 0:5868e8752d44 2943 STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
pythontech 0:5868e8752d44 2944 comp->pass = pass;
pythontech 0:5868e8752d44 2945 comp->scope_cur = scope;
pythontech 0:5868e8752d44 2946 comp->next_label = 1;
pythontech 0:5868e8752d44 2947 EMIT_ARG(start_pass, pass, scope);
pythontech 0:5868e8752d44 2948
pythontech 0:5868e8752d44 2949 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2950 // reset maximum stack sizes in scope
pythontech 0:5868e8752d44 2951 // they will be computed in this first pass
pythontech 0:5868e8752d44 2952 scope->stack_size = 0;
pythontech 0:5868e8752d44 2953 scope->exc_stack_size = 0;
pythontech 0:5868e8752d44 2954 }
pythontech 0:5868e8752d44 2955
pythontech 0:5868e8752d44 2956 // compile
pythontech 0:5868e8752d44 2957 if (MP_PARSE_NODE_IS_STRUCT_KIND(scope->pn, PN_eval_input)) {
pythontech 0:5868e8752d44 2958 assert(scope->kind == SCOPE_MODULE);
pythontech 0:5868e8752d44 2959 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 2960 compile_node(comp, pns->nodes[0]); // compile the expression
pythontech 0:5868e8752d44 2961 EMIT(return_value);
pythontech 0:5868e8752d44 2962 } else if (scope->kind == SCOPE_MODULE) {
pythontech 0:5868e8752d44 2963 if (!comp->is_repl) {
pythontech 0:5868e8752d44 2964 check_for_doc_string(comp, scope->pn);
pythontech 0:5868e8752d44 2965 }
pythontech 0:5868e8752d44 2966 compile_node(comp, scope->pn);
pythontech 0:5868e8752d44 2967 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 2968 EMIT(return_value);
pythontech 0:5868e8752d44 2969 } else if (scope->kind == SCOPE_FUNCTION) {
pythontech 0:5868e8752d44 2970 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 2971 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 2972 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
pythontech 0:5868e8752d44 2973
pythontech 0:5868e8752d44 2974 // work out number of parameters, keywords and default parameters, and add them to the id_info array
pythontech 0:5868e8752d44 2975 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
pythontech 0:5868e8752d44 2976 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 2977 comp->have_star = false;
pythontech 0:5868e8752d44 2978 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_param);
pythontech 0:5868e8752d44 2979 }
pythontech 0:5868e8752d44 2980 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 2981 else if (scope->emit_options == MP_EMIT_OPT_VIPER) {
pythontech 0:5868e8752d44 2982 // compile annotations; only needed on latter compiler passes
pythontech 0:5868e8752d44 2983 // only needed for viper emitter
pythontech 0:5868e8752d44 2984
pythontech 0:5868e8752d44 2985 // argument annotations
pythontech 0:5868e8752d44 2986 apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_scope_func_annotations);
pythontech 0:5868e8752d44 2987
pythontech 0:5868e8752d44 2988 // pns->nodes[2] is return/whole function annotation
pythontech 0:5868e8752d44 2989 mp_parse_node_t pn_annotation = pns->nodes[2];
pythontech 0:5868e8752d44 2990 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
pythontech 0:5868e8752d44 2991 // nodes[2] can be null or a test-expr
pythontech 0:5868e8752d44 2992 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
pythontech 0:5868e8752d44 2993 qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
pythontech 0:5868e8752d44 2994 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_RETURN, 0, ret_type);
pythontech 0:5868e8752d44 2995 } else {
pythontech 0:5868e8752d44 2996 compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier");
pythontech 0:5868e8752d44 2997 }
pythontech 0:5868e8752d44 2998 }
pythontech 0:5868e8752d44 2999 }
pythontech 0:5868e8752d44 3000 #endif // MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3001
pythontech 0:5868e8752d44 3002 compile_node(comp, pns->nodes[3]); // 3 is function body
pythontech 0:5868e8752d44 3003 // emit return if it wasn't the last opcode
pythontech 0:5868e8752d44 3004 if (!EMIT(last_emit_was_return_value)) {
pythontech 0:5868e8752d44 3005 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 3006 EMIT(return_value);
pythontech 0:5868e8752d44 3007 }
pythontech 0:5868e8752d44 3008 } else if (scope->kind == SCOPE_LAMBDA) {
pythontech 0:5868e8752d44 3009 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 3010 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 3011 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3);
pythontech 0:5868e8752d44 3012
pythontech 0:5868e8752d44 3013 // work out number of parameters, keywords and default parameters, and add them to the id_info array
pythontech 0:5868e8752d44 3014 // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
pythontech 0:5868e8752d44 3015 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3016 comp->have_star = false;
pythontech 0:5868e8752d44 3017 apply_to_single_or_list(comp, pns->nodes[0], PN_varargslist, compile_scope_lambda_param);
pythontech 0:5868e8752d44 3018 }
pythontech 0:5868e8752d44 3019
pythontech 0:5868e8752d44 3020 compile_node(comp, pns->nodes[1]); // 1 is lambda body
pythontech 0:5868e8752d44 3021
pythontech 0:5868e8752d44 3022 // if the lambda is a generator, then we return None, not the result of the expression of the lambda
pythontech 0:5868e8752d44 3023 if (scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) {
pythontech 0:5868e8752d44 3024 EMIT(pop_top);
pythontech 0:5868e8752d44 3025 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 3026 }
pythontech 0:5868e8752d44 3027 EMIT(return_value);
pythontech 0:5868e8752d44 3028 } 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 3029 // a bit of a hack at the moment
pythontech 0:5868e8752d44 3030
pythontech 0:5868e8752d44 3031 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 3032 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 3033 assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
pythontech 0:5868e8752d44 3034 assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for));
pythontech 0:5868e8752d44 3035 mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t*)pns->nodes[1];
pythontech 0:5868e8752d44 3036
pythontech 0:5868e8752d44 3037 // We need a unique name for the comprehension argument (the iterator).
pythontech 0:5868e8752d44 3038 // CPython uses .0, but we should be able to use anything that won't
pythontech 0:5868e8752d44 3039 // clash with a user defined variable. Best to use an existing qstr,
pythontech 0:5868e8752d44 3040 // so we use the blank qstr.
pythontech 0:5868e8752d44 3041 qstr qstr_arg = MP_QSTR_;
pythontech 0:5868e8752d44 3042 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3043 bool added;
pythontech 0:5868e8752d44 3044 id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, qstr_arg, &added);
pythontech 0:5868e8752d44 3045 assert(added);
pythontech 0:5868e8752d44 3046 id_info->kind = ID_INFO_KIND_LOCAL;
pythontech 0:5868e8752d44 3047 scope->num_pos_args = 1;
pythontech 0:5868e8752d44 3048 }
pythontech 0:5868e8752d44 3049
pythontech 0:5868e8752d44 3050 if (scope->kind == SCOPE_LIST_COMP) {
pythontech 0:5868e8752d44 3051 EMIT_ARG(build_list, 0);
pythontech 0:5868e8752d44 3052 } else if (scope->kind == SCOPE_DICT_COMP) {
pythontech 0:5868e8752d44 3053 EMIT_ARG(build_map, 0);
pythontech 0:5868e8752d44 3054 #if MICROPY_PY_BUILTINS_SET
pythontech 0:5868e8752d44 3055 } else if (scope->kind == SCOPE_SET_COMP) {
pythontech 0:5868e8752d44 3056 EMIT_ARG(build_set, 0);
pythontech 0:5868e8752d44 3057 #endif
pythontech 0:5868e8752d44 3058 }
pythontech 0:5868e8752d44 3059
pythontech 0:5868e8752d44 3060 compile_load_id(comp, qstr_arg);
pythontech 0:5868e8752d44 3061 compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0);
pythontech 0:5868e8752d44 3062
pythontech 0:5868e8752d44 3063 if (scope->kind == SCOPE_GEN_EXPR) {
pythontech 0:5868e8752d44 3064 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 3065 }
pythontech 0:5868e8752d44 3066 EMIT(return_value);
pythontech 0:5868e8752d44 3067 } else {
pythontech 0:5868e8752d44 3068 assert(scope->kind == SCOPE_CLASS);
pythontech 0:5868e8752d44 3069 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 3070 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 3071 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_classdef);
pythontech 0:5868e8752d44 3072
pythontech 0:5868e8752d44 3073 if (comp->pass == MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3074 bool added;
pythontech 0:5868e8752d44 3075 id_info_t *id_info = scope_find_or_add_id(scope, MP_QSTR___class__, &added);
pythontech 0:5868e8752d44 3076 assert(added);
pythontech 0:5868e8752d44 3077 id_info->kind = ID_INFO_KIND_LOCAL;
pythontech 0:5868e8752d44 3078 }
pythontech 0:5868e8752d44 3079
pythontech 0:5868e8752d44 3080 compile_load_id(comp, MP_QSTR___name__);
pythontech 0:5868e8752d44 3081 compile_store_id(comp, MP_QSTR___module__);
pythontech 0:5868e8752d44 3082 EMIT_ARG(load_const_str, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0])); // 0 is class name
pythontech 0:5868e8752d44 3083 compile_store_id(comp, MP_QSTR___qualname__);
pythontech 0:5868e8752d44 3084
pythontech 0:5868e8752d44 3085 check_for_doc_string(comp, pns->nodes[2]);
pythontech 0:5868e8752d44 3086 compile_node(comp, pns->nodes[2]); // 2 is class body
pythontech 0:5868e8752d44 3087
pythontech 0:5868e8752d44 3088 id_info_t *id = scope_find(scope, MP_QSTR___class__);
pythontech 0:5868e8752d44 3089 assert(id != NULL);
pythontech 0:5868e8752d44 3090 if (id->kind == ID_INFO_KIND_LOCAL) {
pythontech 0:5868e8752d44 3091 EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
pythontech 0:5868e8752d44 3092 } else {
pythontech 0:5868e8752d44 3093 EMIT_LOAD_FAST(MP_QSTR___class__, id->local_num);
pythontech 0:5868e8752d44 3094 }
pythontech 0:5868e8752d44 3095 EMIT(return_value);
pythontech 0:5868e8752d44 3096 }
pythontech 0:5868e8752d44 3097
pythontech 0:5868e8752d44 3098 EMIT(end_pass);
pythontech 0:5868e8752d44 3099
pythontech 0:5868e8752d44 3100 // make sure we match all the exception levels
pythontech 0:5868e8752d44 3101 assert(comp->cur_except_level == 0);
pythontech 0:5868e8752d44 3102 }
pythontech 0:5868e8752d44 3103
pythontech 0:5868e8752d44 3104 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3105 // requires 3 passes: SCOPE, CODE_SIZE, EMIT
pythontech 0:5868e8752d44 3106 STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
pythontech 0:5868e8752d44 3107 comp->pass = pass;
pythontech 0:5868e8752d44 3108 comp->scope_cur = scope;
pythontech 0:5868e8752d44 3109 comp->next_label = 1;
pythontech 0:5868e8752d44 3110
pythontech 0:5868e8752d44 3111 if (scope->kind != SCOPE_FUNCTION) {
pythontech 0:5868e8752d44 3112 compile_syntax_error(comp, MP_PARSE_NODE_NULL, "inline assembler must be a function");
pythontech 0:5868e8752d44 3113 return;
pythontech 0:5868e8752d44 3114 }
pythontech 0:5868e8752d44 3115
pythontech 0:5868e8752d44 3116 if (comp->pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3117 EMIT_INLINE_ASM_ARG(start_pass, comp->pass, comp->scope_cur, &comp->compile_error);
pythontech 0:5868e8752d44 3118 }
pythontech 0:5868e8752d44 3119
pythontech 0:5868e8752d44 3120 // get the function definition parse node
pythontech 0:5868e8752d44 3121 assert(MP_PARSE_NODE_IS_STRUCT(scope->pn));
pythontech 0:5868e8752d44 3122 mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)scope->pn;
pythontech 0:5868e8752d44 3123 assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef);
pythontech 0:5868e8752d44 3124
pythontech 0:5868e8752d44 3125 //qstr f_id = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); // function name
pythontech 0:5868e8752d44 3126
pythontech 0:5868e8752d44 3127 // parameters are in pns->nodes[1]
pythontech 0:5868e8752d44 3128 if (comp->pass == MP_PASS_CODE_SIZE) {
pythontech 0:5868e8752d44 3129 mp_parse_node_t *pn_params;
pythontech 0:5868e8752d44 3130 int n_params = mp_parse_node_extract_list(&pns->nodes[1], PN_typedargslist, &pn_params);
pythontech 0:5868e8752d44 3131 scope->num_pos_args = EMIT_INLINE_ASM_ARG(count_params, n_params, pn_params);
pythontech 0:5868e8752d44 3132 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3133 goto inline_asm_error;
pythontech 0:5868e8752d44 3134 }
pythontech 0:5868e8752d44 3135 }
pythontech 0:5868e8752d44 3136
pythontech 0:5868e8752d44 3137 // pns->nodes[2] is function return annotation
pythontech 0:5868e8752d44 3138 mp_uint_t type_sig = MP_NATIVE_TYPE_INT;
pythontech 0:5868e8752d44 3139 mp_parse_node_t pn_annotation = pns->nodes[2];
pythontech 0:5868e8752d44 3140 if (!MP_PARSE_NODE_IS_NULL(pn_annotation)) {
pythontech 0:5868e8752d44 3141 // nodes[2] can be null or a test-expr
pythontech 0:5868e8752d44 3142 if (MP_PARSE_NODE_IS_ID(pn_annotation)) {
pythontech 0:5868e8752d44 3143 qstr ret_type = MP_PARSE_NODE_LEAF_ARG(pn_annotation);
pythontech 0:5868e8752d44 3144 switch (ret_type) {
pythontech 0:5868e8752d44 3145 case MP_QSTR_object: type_sig = MP_NATIVE_TYPE_OBJ; break;
pythontech 0:5868e8752d44 3146 case MP_QSTR_bool: type_sig = MP_NATIVE_TYPE_BOOL; break;
pythontech 0:5868e8752d44 3147 case MP_QSTR_int: type_sig = MP_NATIVE_TYPE_INT; break;
pythontech 0:5868e8752d44 3148 case MP_QSTR_uint: type_sig = MP_NATIVE_TYPE_UINT; break;
pythontech 0:5868e8752d44 3149 default: compile_syntax_error(comp, pn_annotation, "unknown type"); return;
pythontech 0:5868e8752d44 3150 }
pythontech 0:5868e8752d44 3151 } else {
pythontech 0:5868e8752d44 3152 compile_syntax_error(comp, pn_annotation, "return annotation must be an identifier");
pythontech 0:5868e8752d44 3153 }
pythontech 0:5868e8752d44 3154 }
pythontech 0:5868e8752d44 3155
pythontech 0:5868e8752d44 3156 mp_parse_node_t pn_body = pns->nodes[3]; // body
pythontech 0:5868e8752d44 3157 mp_parse_node_t *nodes;
pythontech 0:5868e8752d44 3158 int num = mp_parse_node_extract_list(&pn_body, PN_suite_block_stmts, &nodes);
pythontech 0:5868e8752d44 3159
pythontech 0:5868e8752d44 3160 for (int i = 0; i < num; i++) {
pythontech 0:5868e8752d44 3161 assert(MP_PARSE_NODE_IS_STRUCT(nodes[i]));
pythontech 0:5868e8752d44 3162 mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)nodes[i];
pythontech 0:5868e8752d44 3163 if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_pass_stmt) {
pythontech 0:5868e8752d44 3164 // no instructions
pythontech 0:5868e8752d44 3165 continue;
pythontech 0:5868e8752d44 3166 } else if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_expr_stmt) {
pythontech 0:5868e8752d44 3167 // not an instruction; error
pythontech 0:5868e8752d44 3168 not_an_instruction:
pythontech 0:5868e8752d44 3169 compile_syntax_error(comp, nodes[i], "expecting an assembler instruction");
pythontech 0:5868e8752d44 3170 return;
pythontech 0:5868e8752d44 3171 }
pythontech 0:5868e8752d44 3172
pythontech 0:5868e8752d44 3173 // check structure of parse node
pythontech 0:5868e8752d44 3174 assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0]));
pythontech 0:5868e8752d44 3175 if (!MP_PARSE_NODE_IS_NULL(pns2->nodes[1])) {
pythontech 0:5868e8752d44 3176 goto not_an_instruction;
pythontech 0:5868e8752d44 3177 }
pythontech 0:5868e8752d44 3178 pns2 = (mp_parse_node_struct_t*)pns2->nodes[0];
Colin Hogben 2:c89e95946844 3179 if (MP_PARSE_NODE_STRUCT_KIND(pns2) != PN_atom_expr_normal) {
pythontech 0:5868e8752d44 3180 goto not_an_instruction;
pythontech 0:5868e8752d44 3181 }
pythontech 0:5868e8752d44 3182 if (!MP_PARSE_NODE_IS_ID(pns2->nodes[0])) {
pythontech 0:5868e8752d44 3183 goto not_an_instruction;
pythontech 0:5868e8752d44 3184 }
pythontech 0:5868e8752d44 3185 if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns2->nodes[1], PN_trailer_paren)) {
pythontech 0:5868e8752d44 3186 goto not_an_instruction;
pythontech 0:5868e8752d44 3187 }
pythontech 0:5868e8752d44 3188
pythontech 0:5868e8752d44 3189 // parse node looks like an instruction
pythontech 0:5868e8752d44 3190 // get instruction name and args
pythontech 0:5868e8752d44 3191 qstr op = MP_PARSE_NODE_LEAF_ARG(pns2->nodes[0]);
pythontech 0:5868e8752d44 3192 pns2 = (mp_parse_node_struct_t*)pns2->nodes[1]; // PN_trailer_paren
pythontech 0:5868e8752d44 3193 mp_parse_node_t *pn_arg;
pythontech 0:5868e8752d44 3194 int n_args = mp_parse_node_extract_list(&pns2->nodes[0], PN_arglist, &pn_arg);
pythontech 0:5868e8752d44 3195
pythontech 0:5868e8752d44 3196 // emit instructions
pythontech 0:5868e8752d44 3197 if (op == MP_QSTR_label) {
pythontech 0:5868e8752d44 3198 if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
pythontech 0:5868e8752d44 3199 compile_syntax_error(comp, nodes[i], "'label' requires 1 argument");
pythontech 0:5868e8752d44 3200 return;
pythontech 0:5868e8752d44 3201 }
pythontech 0:5868e8752d44 3202 uint lab = comp_next_label(comp);
pythontech 0:5868e8752d44 3203 if (pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3204 if (!EMIT_INLINE_ASM_ARG(label, lab, MP_PARSE_NODE_LEAF_ARG(pn_arg[0]))) {
pythontech 0:5868e8752d44 3205 compile_syntax_error(comp, nodes[i], "label redefined");
pythontech 0:5868e8752d44 3206 return;
pythontech 0:5868e8752d44 3207 }
pythontech 0:5868e8752d44 3208 }
pythontech 0:5868e8752d44 3209 } else if (op == MP_QSTR_align) {
pythontech 0:5868e8752d44 3210 if (!(n_args == 1 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
pythontech 0:5868e8752d44 3211 compile_syntax_error(comp, nodes[i], "'align' requires 1 argument");
pythontech 0:5868e8752d44 3212 return;
pythontech 0:5868e8752d44 3213 }
pythontech 0:5868e8752d44 3214 if (pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3215 EMIT_INLINE_ASM_ARG(align, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]));
pythontech 0:5868e8752d44 3216 }
pythontech 0:5868e8752d44 3217 } else if (op == MP_QSTR_data) {
pythontech 0:5868e8752d44 3218 if (!(n_args >= 2 && MP_PARSE_NODE_IS_SMALL_INT(pn_arg[0]))) {
pythontech 0:5868e8752d44 3219 compile_syntax_error(comp, nodes[i], "'data' requires at least 2 arguments");
pythontech 0:5868e8752d44 3220 return;
pythontech 0:5868e8752d44 3221 }
pythontech 0:5868e8752d44 3222 if (pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3223 mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
pythontech 0:5868e8752d44 3224 for (uint j = 1; j < n_args; j++) {
pythontech 0:5868e8752d44 3225 if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[j])) {
pythontech 0:5868e8752d44 3226 compile_syntax_error(comp, nodes[i], "'data' requires integer arguments");
pythontech 0:5868e8752d44 3227 return;
pythontech 0:5868e8752d44 3228 }
pythontech 0:5868e8752d44 3229 EMIT_INLINE_ASM_ARG(data, bytesize, MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[j]));
pythontech 0:5868e8752d44 3230 }
pythontech 0:5868e8752d44 3231 }
pythontech 0:5868e8752d44 3232 } else {
pythontech 0:5868e8752d44 3233 if (pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3234 EMIT_INLINE_ASM_ARG(op, op, n_args, pn_arg);
pythontech 0:5868e8752d44 3235 }
pythontech 0:5868e8752d44 3236 }
pythontech 0:5868e8752d44 3237
pythontech 0:5868e8752d44 3238 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3239 pns = pns2; // this is the parse node that had the error
pythontech 0:5868e8752d44 3240 goto inline_asm_error;
pythontech 0:5868e8752d44 3241 }
pythontech 0:5868e8752d44 3242 }
pythontech 0:5868e8752d44 3243
pythontech 0:5868e8752d44 3244 if (comp->pass > MP_PASS_SCOPE) {
pythontech 0:5868e8752d44 3245 EMIT_INLINE_ASM_ARG(end_pass, type_sig);
pythontech 0:5868e8752d44 3246 }
pythontech 0:5868e8752d44 3247
pythontech 0:5868e8752d44 3248 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3249 // inline assembler had an error; set line for its exception
pythontech 0:5868e8752d44 3250 inline_asm_error:
pythontech 0:5868e8752d44 3251 comp->compile_error_line = pns->source_line;
pythontech 0:5868e8752d44 3252 }
pythontech 0:5868e8752d44 3253 }
pythontech 0:5868e8752d44 3254 #endif
pythontech 0:5868e8752d44 3255
pythontech 0:5868e8752d44 3256 STATIC void scope_compute_things(scope_t *scope) {
pythontech 0:5868e8752d44 3257 // in Micro Python we put the *x parameter after all other parameters (except **y)
pythontech 0:5868e8752d44 3258 if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) {
pythontech 0:5868e8752d44 3259 id_info_t *id_param = NULL;
pythontech 0:5868e8752d44 3260 for (int i = scope->id_info_len - 1; i >= 0; i--) {
pythontech 0:5868e8752d44 3261 id_info_t *id = &scope->id_info[i];
pythontech 0:5868e8752d44 3262 if (id->flags & ID_FLAG_IS_STAR_PARAM) {
pythontech 0:5868e8752d44 3263 if (id_param != NULL) {
pythontech 0:5868e8752d44 3264 // swap star param with last param
pythontech 0:5868e8752d44 3265 id_info_t temp = *id_param; *id_param = *id; *id = temp;
pythontech 0:5868e8752d44 3266 }
pythontech 0:5868e8752d44 3267 break;
pythontech 0:5868e8752d44 3268 } else if (id_param == NULL && id->flags == ID_FLAG_IS_PARAM) {
pythontech 0:5868e8752d44 3269 id_param = id;
pythontech 0:5868e8752d44 3270 }
pythontech 0:5868e8752d44 3271 }
pythontech 0:5868e8752d44 3272 }
pythontech 0:5868e8752d44 3273
pythontech 0:5868e8752d44 3274 // in functions, turn implicit globals into explicit globals
pythontech 0:5868e8752d44 3275 // compute the index of each local
pythontech 0:5868e8752d44 3276 scope->num_locals = 0;
pythontech 0:5868e8752d44 3277 for (int i = 0; i < scope->id_info_len; i++) {
pythontech 0:5868e8752d44 3278 id_info_t *id = &scope->id_info[i];
pythontech 0:5868e8752d44 3279 if (scope->kind == SCOPE_CLASS && id->qst == MP_QSTR___class__) {
pythontech 0:5868e8752d44 3280 // __class__ is not counted as a local; if it's used then it becomes a ID_INFO_KIND_CELL
pythontech 0:5868e8752d44 3281 continue;
pythontech 0:5868e8752d44 3282 }
pythontech 0:5868e8752d44 3283 if (scope->kind >= SCOPE_FUNCTION && scope->kind <= SCOPE_GEN_EXPR && id->kind == ID_INFO_KIND_GLOBAL_IMPLICIT) {
pythontech 0:5868e8752d44 3284 id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
pythontech 0:5868e8752d44 3285 }
pythontech 0:5868e8752d44 3286 // params always count for 1 local, even if they are a cell
pythontech 0:5868e8752d44 3287 if (id->kind == ID_INFO_KIND_LOCAL || (id->flags & ID_FLAG_IS_PARAM)) {
pythontech 0:5868e8752d44 3288 id->local_num = scope->num_locals++;
pythontech 0:5868e8752d44 3289 }
pythontech 0:5868e8752d44 3290 }
pythontech 0:5868e8752d44 3291
pythontech 0:5868e8752d44 3292 // compute the index of cell vars
pythontech 0:5868e8752d44 3293 for (int i = 0; i < scope->id_info_len; i++) {
pythontech 0:5868e8752d44 3294 id_info_t *id = &scope->id_info[i];
pythontech 0:5868e8752d44 3295 // in Micro Python the cells come right after the fast locals
pythontech 0:5868e8752d44 3296 // parameters are not counted here, since they remain at the start
pythontech 0:5868e8752d44 3297 // of the locals, even if they are cell vars
pythontech 0:5868e8752d44 3298 if (id->kind == ID_INFO_KIND_CELL && !(id->flags & ID_FLAG_IS_PARAM)) {
pythontech 0:5868e8752d44 3299 id->local_num = scope->num_locals;
pythontech 0:5868e8752d44 3300 scope->num_locals += 1;
pythontech 0:5868e8752d44 3301 }
pythontech 0:5868e8752d44 3302 }
pythontech 0:5868e8752d44 3303
pythontech 0:5868e8752d44 3304 // compute the index of free vars
pythontech 0:5868e8752d44 3305 // make sure they are in the order of the parent scope
pythontech 0:5868e8752d44 3306 if (scope->parent != NULL) {
pythontech 0:5868e8752d44 3307 int num_free = 0;
pythontech 0:5868e8752d44 3308 for (int i = 0; i < scope->parent->id_info_len; i++) {
pythontech 0:5868e8752d44 3309 id_info_t *id = &scope->parent->id_info[i];
pythontech 0:5868e8752d44 3310 if (id->kind == ID_INFO_KIND_CELL || id->kind == ID_INFO_KIND_FREE) {
pythontech 0:5868e8752d44 3311 for (int j = 0; j < scope->id_info_len; j++) {
pythontech 0:5868e8752d44 3312 id_info_t *id2 = &scope->id_info[j];
pythontech 0:5868e8752d44 3313 if (id2->kind == ID_INFO_KIND_FREE && id->qst == id2->qst) {
pythontech 0:5868e8752d44 3314 assert(!(id2->flags & ID_FLAG_IS_PARAM)); // free vars should not be params
pythontech 0:5868e8752d44 3315 // in Micro Python the frees come first, before the params
pythontech 0:5868e8752d44 3316 id2->local_num = num_free;
pythontech 0:5868e8752d44 3317 num_free += 1;
pythontech 0:5868e8752d44 3318 }
pythontech 0:5868e8752d44 3319 }
pythontech 0:5868e8752d44 3320 }
pythontech 0:5868e8752d44 3321 }
pythontech 0:5868e8752d44 3322 // in Micro Python shift all other locals after the free locals
pythontech 0:5868e8752d44 3323 if (num_free > 0) {
pythontech 0:5868e8752d44 3324 for (int i = 0; i < scope->id_info_len; i++) {
pythontech 0:5868e8752d44 3325 id_info_t *id = &scope->id_info[i];
pythontech 0:5868e8752d44 3326 if (id->kind != ID_INFO_KIND_FREE || (id->flags & ID_FLAG_IS_PARAM)) {
pythontech 0:5868e8752d44 3327 id->local_num += num_free;
pythontech 0:5868e8752d44 3328 }
pythontech 0:5868e8752d44 3329 }
pythontech 0:5868e8752d44 3330 scope->num_pos_args += num_free; // free vars are counted as params for passing them into the function
pythontech 0:5868e8752d44 3331 scope->num_locals += num_free;
pythontech 0:5868e8752d44 3332 }
pythontech 0:5868e8752d44 3333 }
pythontech 0:5868e8752d44 3334 }
pythontech 0:5868e8752d44 3335
pythontech 0:5868e8752d44 3336 #if !MICROPY_PERSISTENT_CODE_SAVE
pythontech 0:5868e8752d44 3337 STATIC
pythontech 0:5868e8752d44 3338 #endif
pythontech 0:5868e8752d44 3339 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 3340 // put compiler state on the stack, it's relatively small
pythontech 0:5868e8752d44 3341 compiler_t comp_state = {0};
pythontech 0:5868e8752d44 3342 compiler_t *comp = &comp_state;
pythontech 0:5868e8752d44 3343
pythontech 0:5868e8752d44 3344 comp->source_file = source_file;
pythontech 0:5868e8752d44 3345 comp->is_repl = is_repl;
pythontech 0:5868e8752d44 3346
pythontech 0:5868e8752d44 3347 // create the module scope
pythontech 0:5868e8752d44 3348 scope_t *module_scope = scope_new_and_link(comp, SCOPE_MODULE, parse_tree->root, emit_opt);
pythontech 0:5868e8752d44 3349
pythontech 0:5868e8752d44 3350 // create standard emitter; it's used at least for MP_PASS_SCOPE
pythontech 0:5868e8752d44 3351 emit_t *emit_bc = emit_bc_new();
pythontech 0:5868e8752d44 3352
pythontech 0:5868e8752d44 3353 // compile pass 1
pythontech 0:5868e8752d44 3354 comp->emit = emit_bc;
pythontech 0:5868e8752d44 3355 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3356 comp->emit_method_table = &emit_bc_method_table;
pythontech 0:5868e8752d44 3357 #endif
pythontech 0:5868e8752d44 3358 uint max_num_labels = 0;
pythontech 0:5868e8752d44 3359 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
pythontech 0:5868e8752d44 3360 if (false) {
pythontech 0:5868e8752d44 3361 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3362 } else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) {
pythontech 0:5868e8752d44 3363 compile_scope_inline_asm(comp, s, MP_PASS_SCOPE);
pythontech 0:5868e8752d44 3364 #endif
pythontech 0:5868e8752d44 3365 } else {
pythontech 0:5868e8752d44 3366 compile_scope(comp, s, MP_PASS_SCOPE);
pythontech 0:5868e8752d44 3367 }
pythontech 0:5868e8752d44 3368
pythontech 0:5868e8752d44 3369 // update maximim number of labels needed
pythontech 0:5868e8752d44 3370 if (comp->next_label > max_num_labels) {
pythontech 0:5868e8752d44 3371 max_num_labels = comp->next_label;
pythontech 0:5868e8752d44 3372 }
pythontech 0:5868e8752d44 3373 }
pythontech 0:5868e8752d44 3374
pythontech 0:5868e8752d44 3375 // compute some things related to scope and identifiers
pythontech 0:5868e8752d44 3376 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
pythontech 0:5868e8752d44 3377 scope_compute_things(s);
pythontech 0:5868e8752d44 3378 }
pythontech 0:5868e8752d44 3379
pythontech 0:5868e8752d44 3380 // set max number of labels now that it's calculated
pythontech 0:5868e8752d44 3381 emit_bc_set_max_num_labels(emit_bc, max_num_labels);
pythontech 0:5868e8752d44 3382
pythontech 0:5868e8752d44 3383 // compile pass 2 and 3
pythontech 0:5868e8752d44 3384 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3385 emit_t *emit_native = NULL;
pythontech 0:5868e8752d44 3386 #endif
pythontech 0:5868e8752d44 3387 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3388 emit_inline_asm_t *emit_inline_thumb = NULL;
pythontech 0:5868e8752d44 3389 #endif
pythontech 0:5868e8752d44 3390 for (scope_t *s = comp->scope_head; s != NULL && comp->compile_error == MP_OBJ_NULL; s = s->next) {
pythontech 0:5868e8752d44 3391 if (false) {
pythontech 0:5868e8752d44 3392 // dummy
pythontech 0:5868e8752d44 3393
pythontech 0:5868e8752d44 3394 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3395 } else if (s->emit_options == MP_EMIT_OPT_ASM_THUMB) {
pythontech 0:5868e8752d44 3396 // inline assembly for thumb
pythontech 0:5868e8752d44 3397 if (emit_inline_thumb == NULL) {
pythontech 0:5868e8752d44 3398 emit_inline_thumb = emit_inline_thumb_new(max_num_labels);
pythontech 0:5868e8752d44 3399 }
pythontech 0:5868e8752d44 3400 comp->emit = NULL;
pythontech 0:5868e8752d44 3401 comp->emit_inline_asm = emit_inline_thumb;
pythontech 0:5868e8752d44 3402 comp->emit_inline_asm_method_table = &emit_inline_thumb_method_table;
pythontech 0:5868e8752d44 3403 compile_scope_inline_asm(comp, s, MP_PASS_CODE_SIZE);
pythontech 0:5868e8752d44 3404 if (comp->compile_error == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3405 compile_scope_inline_asm(comp, s, MP_PASS_EMIT);
pythontech 0:5868e8752d44 3406 }
pythontech 0:5868e8752d44 3407 #endif
pythontech 0:5868e8752d44 3408
pythontech 0:5868e8752d44 3409 } else {
pythontech 0:5868e8752d44 3410
pythontech 0:5868e8752d44 3411 // choose the emit type
pythontech 0:5868e8752d44 3412
pythontech 0:5868e8752d44 3413 switch (s->emit_options) {
pythontech 0:5868e8752d44 3414
pythontech 0:5868e8752d44 3415 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3416 case MP_EMIT_OPT_NATIVE_PYTHON:
pythontech 0:5868e8752d44 3417 case MP_EMIT_OPT_VIPER:
pythontech 0:5868e8752d44 3418 #if MICROPY_EMIT_X64
pythontech 0:5868e8752d44 3419 if (emit_native == NULL) {
pythontech 0:5868e8752d44 3420 emit_native = emit_native_x64_new(&comp->compile_error, max_num_labels);
pythontech 0:5868e8752d44 3421 }
pythontech 0:5868e8752d44 3422 comp->emit_method_table = &emit_native_x64_method_table;
pythontech 0:5868e8752d44 3423 #elif MICROPY_EMIT_X86
pythontech 0:5868e8752d44 3424 if (emit_native == NULL) {
pythontech 0:5868e8752d44 3425 emit_native = emit_native_x86_new(&comp->compile_error, max_num_labels);
pythontech 0:5868e8752d44 3426 }
pythontech 0:5868e8752d44 3427 comp->emit_method_table = &emit_native_x86_method_table;
pythontech 0:5868e8752d44 3428 #elif MICROPY_EMIT_THUMB
pythontech 0:5868e8752d44 3429 if (emit_native == NULL) {
pythontech 0:5868e8752d44 3430 emit_native = emit_native_thumb_new(&comp->compile_error, max_num_labels);
pythontech 0:5868e8752d44 3431 }
pythontech 0:5868e8752d44 3432 comp->emit_method_table = &emit_native_thumb_method_table;
pythontech 0:5868e8752d44 3433 #elif MICROPY_EMIT_ARM
pythontech 0:5868e8752d44 3434 if (emit_native == NULL) {
pythontech 0:5868e8752d44 3435 emit_native = emit_native_arm_new(&comp->compile_error, max_num_labels);
pythontech 0:5868e8752d44 3436 }
pythontech 0:5868e8752d44 3437 comp->emit_method_table = &emit_native_arm_method_table;
pythontech 0:5868e8752d44 3438 #endif
pythontech 0:5868e8752d44 3439 comp->emit = emit_native;
pythontech 0:5868e8752d44 3440 EMIT_ARG(set_native_type, MP_EMIT_NATIVE_TYPE_ENABLE, s->emit_options == MP_EMIT_OPT_VIPER, 0);
pythontech 0:5868e8752d44 3441 break;
pythontech 0:5868e8752d44 3442 #endif // MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3443
pythontech 0:5868e8752d44 3444 default:
pythontech 0:5868e8752d44 3445 comp->emit = emit_bc;
pythontech 0:5868e8752d44 3446 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3447 comp->emit_method_table = &emit_bc_method_table;
pythontech 0:5868e8752d44 3448 #endif
pythontech 0:5868e8752d44 3449 break;
pythontech 0:5868e8752d44 3450 }
pythontech 0:5868e8752d44 3451
pythontech 0:5868e8752d44 3452 // need a pass to compute stack size
pythontech 0:5868e8752d44 3453 compile_scope(comp, s, MP_PASS_STACK_SIZE);
pythontech 0:5868e8752d44 3454
pythontech 0:5868e8752d44 3455 // second last pass: compute code size
pythontech 0:5868e8752d44 3456 if (comp->compile_error == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3457 compile_scope(comp, s, MP_PASS_CODE_SIZE);
pythontech 0:5868e8752d44 3458 }
pythontech 0:5868e8752d44 3459
pythontech 0:5868e8752d44 3460 // final pass: emit code
pythontech 0:5868e8752d44 3461 if (comp->compile_error == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3462 compile_scope(comp, s, MP_PASS_EMIT);
pythontech 0:5868e8752d44 3463 }
pythontech 0:5868e8752d44 3464 }
pythontech 0:5868e8752d44 3465 }
pythontech 0:5868e8752d44 3466
pythontech 0:5868e8752d44 3467 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3468 // if there is no line number for the error then use the line
pythontech 0:5868e8752d44 3469 // number for the start of this scope
pythontech 0:5868e8752d44 3470 compile_error_set_line(comp, comp->scope_cur->pn);
pythontech 0:5868e8752d44 3471 // add a traceback to the exception using relevant source info
pythontech 0:5868e8752d44 3472 mp_obj_exception_add_traceback(comp->compile_error, comp->source_file,
pythontech 0:5868e8752d44 3473 comp->compile_error_line, comp->scope_cur->simple_name);
pythontech 0:5868e8752d44 3474 }
pythontech 0:5868e8752d44 3475
pythontech 0:5868e8752d44 3476 // free the emitters
pythontech 0:5868e8752d44 3477
pythontech 0:5868e8752d44 3478 emit_bc_free(emit_bc);
pythontech 0:5868e8752d44 3479 #if MICROPY_EMIT_NATIVE
pythontech 0:5868e8752d44 3480 if (emit_native != NULL) {
pythontech 0:5868e8752d44 3481 #if MICROPY_EMIT_X64
pythontech 0:5868e8752d44 3482 emit_native_x64_free(emit_native);
pythontech 0:5868e8752d44 3483 #elif MICROPY_EMIT_X86
pythontech 0:5868e8752d44 3484 emit_native_x86_free(emit_native);
pythontech 0:5868e8752d44 3485 #elif MICROPY_EMIT_THUMB
pythontech 0:5868e8752d44 3486 emit_native_thumb_free(emit_native);
pythontech 0:5868e8752d44 3487 #elif MICROPY_EMIT_ARM
pythontech 0:5868e8752d44 3488 emit_native_arm_free(emit_native);
pythontech 0:5868e8752d44 3489 #endif
pythontech 0:5868e8752d44 3490 }
pythontech 0:5868e8752d44 3491 #endif
pythontech 0:5868e8752d44 3492 #if MICROPY_EMIT_INLINE_THUMB
pythontech 0:5868e8752d44 3493 if (emit_inline_thumb != NULL) {
pythontech 0:5868e8752d44 3494 emit_inline_thumb_free(emit_inline_thumb);
pythontech 0:5868e8752d44 3495 }
pythontech 0:5868e8752d44 3496 #endif
pythontech 0:5868e8752d44 3497
pythontech 0:5868e8752d44 3498 // free the parse tree
pythontech 0:5868e8752d44 3499 mp_parse_tree_clear(parse_tree);
pythontech 0:5868e8752d44 3500
pythontech 0:5868e8752d44 3501 // free the scopes
pythontech 0:5868e8752d44 3502 mp_raw_code_t *outer_raw_code = module_scope->raw_code;
pythontech 0:5868e8752d44 3503 for (scope_t *s = module_scope; s;) {
pythontech 0:5868e8752d44 3504 scope_t *next = s->next;
pythontech 0:5868e8752d44 3505 scope_free(s);
pythontech 0:5868e8752d44 3506 s = next;
pythontech 0:5868e8752d44 3507 }
pythontech 0:5868e8752d44 3508
pythontech 0:5868e8752d44 3509 if (comp->compile_error != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 3510 nlr_raise(comp->compile_error);
pythontech 0:5868e8752d44 3511 } else {
pythontech 0:5868e8752d44 3512 return outer_raw_code;
pythontech 0:5868e8752d44 3513 }
pythontech 0:5868e8752d44 3514 }
pythontech 0:5868e8752d44 3515
pythontech 0:5868e8752d44 3516 mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt, bool is_repl) {
pythontech 0:5868e8752d44 3517 mp_raw_code_t *rc = mp_compile_to_raw_code(parse_tree, source_file, emit_opt, is_repl);
pythontech 0:5868e8752d44 3518 // return function that executes the outer module
pythontech 0:5868e8752d44 3519 return mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);
pythontech 0:5868e8752d44 3520 }
pythontech 0:5868e8752d44 3521
pythontech 0:5868e8752d44 3522 #endif // MICROPY_ENABLE_COMPILER