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:
0:5868e8752d44
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, 2014 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 <stdio.h>
pythontech 0:5868e8752d44 28 #include <string.h>
pythontech 0:5868e8752d44 29 #include <assert.h>
pythontech 0:5868e8752d44 30
pythontech 0:5868e8752d44 31 #include "py/mpstate.h"
pythontech 0:5868e8752d44 32 #include "py/nlr.h"
pythontech 0:5868e8752d44 33 #include "py/parsenum.h"
pythontech 0:5868e8752d44 34 #include "py/compile.h"
pythontech 0:5868e8752d44 35 #include "py/objstr.h"
pythontech 0:5868e8752d44 36 #include "py/objtuple.h"
pythontech 0:5868e8752d44 37 #include "py/objlist.h"
pythontech 0:5868e8752d44 38 #include "py/objmodule.h"
pythontech 0:5868e8752d44 39 #include "py/objgenerator.h"
pythontech 0:5868e8752d44 40 #include "py/smallint.h"
pythontech 0:5868e8752d44 41 #include "py/runtime0.h"
pythontech 0:5868e8752d44 42 #include "py/runtime.h"
pythontech 0:5868e8752d44 43 #include "py/builtin.h"
pythontech 0:5868e8752d44 44 #include "py/stackctrl.h"
pythontech 0:5868e8752d44 45 #include "py/gc.h"
pythontech 0:5868e8752d44 46
pythontech 0:5868e8752d44 47 #if 0 // print debugging info
pythontech 0:5868e8752d44 48 #define DEBUG_PRINT (1)
pythontech 0:5868e8752d44 49 #define DEBUG_printf DEBUG_printf
pythontech 0:5868e8752d44 50 #define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
pythontech 0:5868e8752d44 51 #else // don't print debugging info
pythontech 0:5868e8752d44 52 #define DEBUG_printf(...) (void)0
pythontech 0:5868e8752d44 53 #define DEBUG_OP_printf(...) (void)0
pythontech 0:5868e8752d44 54 #endif
pythontech 0:5868e8752d44 55
pythontech 0:5868e8752d44 56 const mp_obj_module_t mp_module___main__ = {
pythontech 0:5868e8752d44 57 .base = { &mp_type_module },
pythontech 0:5868e8752d44 58 .name = MP_QSTR___main__,
pythontech 0:5868e8752d44 59 .globals = (mp_obj_dict_t*)&MP_STATE_VM(dict_main),
pythontech 0:5868e8752d44 60 };
pythontech 0:5868e8752d44 61
pythontech 0:5868e8752d44 62 void mp_init(void) {
pythontech 0:5868e8752d44 63 qstr_init();
pythontech 0:5868e8752d44 64
pythontech 0:5868e8752d44 65 // no pending exceptions to start with
pythontech 0:5868e8752d44 66 MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
pythontech 0:5868e8752d44 67
pythontech 0:5868e8752d44 68 #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
pythontech 0:5868e8752d44 69 mp_init_emergency_exception_buf();
pythontech 0:5868e8752d44 70 #endif
pythontech 0:5868e8752d44 71
pythontech 0:5868e8752d44 72 // call port specific initialization if any
pythontech 0:5868e8752d44 73 #ifdef MICROPY_PORT_INIT_FUNC
pythontech 0:5868e8752d44 74 MICROPY_PORT_INIT_FUNC;
pythontech 0:5868e8752d44 75 #endif
pythontech 0:5868e8752d44 76
pythontech 0:5868e8752d44 77 // optimization disabled by default
pythontech 0:5868e8752d44 78 MP_STATE_VM(mp_optimise_value) = 0;
pythontech 0:5868e8752d44 79
pythontech 0:5868e8752d44 80 // init global module stuff
pythontech 0:5868e8752d44 81 mp_module_init();
pythontech 0:5868e8752d44 82
pythontech 0:5868e8752d44 83 // initialise the __main__ module
pythontech 0:5868e8752d44 84 mp_obj_dict_init(&MP_STATE_VM(dict_main), 1);
pythontech 0:5868e8752d44 85 mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(dict_main)), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
pythontech 0:5868e8752d44 86
pythontech 0:5868e8752d44 87 // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
pythontech 0:5868e8752d44 88 MP_STATE_CTX(dict_locals) = MP_STATE_CTX(dict_globals) = &MP_STATE_VM(dict_main);
pythontech 0:5868e8752d44 89
pythontech 0:5868e8752d44 90 #if MICROPY_CAN_OVERRIDE_BUILTINS
pythontech 0:5868e8752d44 91 // start with no extensions to builtins
pythontech 0:5868e8752d44 92 MP_STATE_VM(mp_module_builtins_override_dict) = NULL;
pythontech 0:5868e8752d44 93 #endif
pythontech 0:5868e8752d44 94 }
pythontech 0:5868e8752d44 95
pythontech 0:5868e8752d44 96 void mp_deinit(void) {
pythontech 0:5868e8752d44 97 //mp_obj_dict_free(&dict_main);
pythontech 0:5868e8752d44 98 mp_module_deinit();
pythontech 0:5868e8752d44 99
pythontech 0:5868e8752d44 100 // call port specific deinitialization if any
pythontech 0:5868e8752d44 101 #ifdef MICROPY_PORT_INIT_FUNC
pythontech 0:5868e8752d44 102 MICROPY_PORT_DEINIT_FUNC;
pythontech 0:5868e8752d44 103 #endif
pythontech 0:5868e8752d44 104 }
pythontech 0:5868e8752d44 105
pythontech 0:5868e8752d44 106 mp_obj_t mp_load_name(qstr qst) {
pythontech 0:5868e8752d44 107 // logic: search locals, globals, builtins
pythontech 0:5868e8752d44 108 DEBUG_OP_printf("load name %s\n", qstr_str(qst));
pythontech 0:5868e8752d44 109 // If we're at the outer scope (locals == globals), dispatch to load_global right away
pythontech 0:5868e8752d44 110 if (MP_STATE_CTX(dict_locals) != MP_STATE_CTX(dict_globals)) {
pythontech 0:5868e8752d44 111 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 112 if (elem != NULL) {
pythontech 0:5868e8752d44 113 return elem->value;
pythontech 0:5868e8752d44 114 }
pythontech 0:5868e8752d44 115 }
pythontech 0:5868e8752d44 116 return mp_load_global(qst);
pythontech 0:5868e8752d44 117 }
pythontech 0:5868e8752d44 118
pythontech 0:5868e8752d44 119 mp_obj_t mp_load_global(qstr qst) {
pythontech 0:5868e8752d44 120 // logic: search globals, builtins
pythontech 0:5868e8752d44 121 DEBUG_OP_printf("load global %s\n", qstr_str(qst));
pythontech 0:5868e8752d44 122 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 123 if (elem == NULL) {
pythontech 0:5868e8752d44 124 #if MICROPY_CAN_OVERRIDE_BUILTINS
pythontech 0:5868e8752d44 125 if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {
pythontech 0:5868e8752d44 126 // lookup in additional dynamic table of builtins first
pythontech 0:5868e8752d44 127 elem = mp_map_lookup(&MP_STATE_VM(mp_module_builtins_override_dict)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 128 if (elem != NULL) {
pythontech 0:5868e8752d44 129 return elem->value;
pythontech 0:5868e8752d44 130 }
pythontech 0:5868e8752d44 131 }
pythontech 0:5868e8752d44 132 #endif
pythontech 0:5868e8752d44 133 elem = mp_map_lookup((mp_map_t*)&mp_module_builtins_globals.map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 134 if (elem == NULL) {
pythontech 0:5868e8752d44 135 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 136 nlr_raise(mp_obj_new_exception_msg(&mp_type_NameError,
pythontech 0:5868e8752d44 137 "name not defined"));
pythontech 0:5868e8752d44 138 } else {
pythontech 0:5868e8752d44 139 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NameError,
pythontech 0:5868e8752d44 140 "name '%q' is not defined", qst));
pythontech 0:5868e8752d44 141 }
pythontech 0:5868e8752d44 142 }
pythontech 0:5868e8752d44 143 }
pythontech 0:5868e8752d44 144 return elem->value;
pythontech 0:5868e8752d44 145 }
pythontech 0:5868e8752d44 146
pythontech 0:5868e8752d44 147 mp_obj_t mp_load_build_class(void) {
pythontech 0:5868e8752d44 148 DEBUG_OP_printf("load_build_class\n");
pythontech 0:5868e8752d44 149 #if MICROPY_CAN_OVERRIDE_BUILTINS
pythontech 0:5868e8752d44 150 if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {
pythontech 0:5868e8752d44 151 // lookup in additional dynamic table of builtins first
pythontech 0:5868e8752d44 152 mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_VM(mp_module_builtins_override_dict)->map, MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 153 if (elem != NULL) {
pythontech 0:5868e8752d44 154 return elem->value;
pythontech 0:5868e8752d44 155 }
pythontech 0:5868e8752d44 156 }
pythontech 0:5868e8752d44 157 #endif
pythontech 0:5868e8752d44 158 return MP_OBJ_FROM_PTR(&mp_builtin___build_class___obj);
pythontech 0:5868e8752d44 159 }
pythontech 0:5868e8752d44 160
pythontech 0:5868e8752d44 161 void mp_store_name(qstr qst, mp_obj_t obj) {
pythontech 0:5868e8752d44 162 DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qst), obj);
pythontech 0:5868e8752d44 163 mp_obj_dict_store(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_locals)), MP_OBJ_NEW_QSTR(qst), obj);
pythontech 0:5868e8752d44 164 }
pythontech 0:5868e8752d44 165
pythontech 0:5868e8752d44 166 void mp_delete_name(qstr qst) {
pythontech 0:5868e8752d44 167 DEBUG_OP_printf("delete name %s\n", qstr_str(qst));
pythontech 0:5868e8752d44 168 // TODO convert KeyError to NameError if qst not found
pythontech 0:5868e8752d44 169 mp_obj_dict_delete(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_locals)), MP_OBJ_NEW_QSTR(qst));
pythontech 0:5868e8752d44 170 }
pythontech 0:5868e8752d44 171
pythontech 0:5868e8752d44 172 void mp_store_global(qstr qst, mp_obj_t obj) {
pythontech 0:5868e8752d44 173 DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qst), obj);
pythontech 0:5868e8752d44 174 mp_obj_dict_store(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_globals)), MP_OBJ_NEW_QSTR(qst), obj);
pythontech 0:5868e8752d44 175 }
pythontech 0:5868e8752d44 176
pythontech 0:5868e8752d44 177 void mp_delete_global(qstr qst) {
pythontech 0:5868e8752d44 178 DEBUG_OP_printf("delete global %s\n", qstr_str(qst));
pythontech 0:5868e8752d44 179 // TODO convert KeyError to NameError if qst not found
pythontech 0:5868e8752d44 180 mp_obj_dict_delete(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_globals)), MP_OBJ_NEW_QSTR(qst));
pythontech 0:5868e8752d44 181 }
pythontech 0:5868e8752d44 182
pythontech 0:5868e8752d44 183 mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
pythontech 0:5868e8752d44 184 DEBUG_OP_printf("unary " UINT_FMT " %p\n", op, arg);
pythontech 0:5868e8752d44 185
pythontech 0:5868e8752d44 186 if (op == MP_UNARY_OP_NOT) {
pythontech 0:5868e8752d44 187 // "not x" is the negative of whether "x" is true per Python semantics
pythontech 0:5868e8752d44 188 return mp_obj_new_bool(mp_obj_is_true(arg) == 0);
pythontech 0:5868e8752d44 189 } else if (MP_OBJ_IS_SMALL_INT(arg)) {
pythontech 0:5868e8752d44 190 mp_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
pythontech 0:5868e8752d44 191 switch (op) {
pythontech 0:5868e8752d44 192 case MP_UNARY_OP_BOOL:
pythontech 0:5868e8752d44 193 return mp_obj_new_bool(val != 0);
pythontech 0:5868e8752d44 194 case MP_UNARY_OP_HASH:
pythontech 0:5868e8752d44 195 return arg;
pythontech 0:5868e8752d44 196 case MP_UNARY_OP_POSITIVE:
pythontech 0:5868e8752d44 197 return arg;
pythontech 0:5868e8752d44 198 case MP_UNARY_OP_NEGATIVE:
pythontech 0:5868e8752d44 199 // check for overflow
pythontech 0:5868e8752d44 200 if (val == MP_SMALL_INT_MIN) {
pythontech 0:5868e8752d44 201 return mp_obj_new_int(-val);
pythontech 0:5868e8752d44 202 } else {
pythontech 0:5868e8752d44 203 return MP_OBJ_NEW_SMALL_INT(-val);
pythontech 0:5868e8752d44 204 }
pythontech 0:5868e8752d44 205 case MP_UNARY_OP_INVERT:
pythontech 0:5868e8752d44 206 return MP_OBJ_NEW_SMALL_INT(~val);
pythontech 0:5868e8752d44 207 default:
pythontech 0:5868e8752d44 208 assert(0);
pythontech 0:5868e8752d44 209 return arg;
pythontech 0:5868e8752d44 210 }
pythontech 0:5868e8752d44 211 } else if (op == MP_UNARY_OP_HASH && MP_OBJ_IS_STR_OR_BYTES(arg)) {
pythontech 0:5868e8752d44 212 // fast path for hashing str/bytes
pythontech 0:5868e8752d44 213 GET_STR_HASH(arg, h);
pythontech 0:5868e8752d44 214 return MP_OBJ_NEW_SMALL_INT(h);
pythontech 0:5868e8752d44 215 } else {
pythontech 0:5868e8752d44 216 mp_obj_type_t *type = mp_obj_get_type(arg);
pythontech 0:5868e8752d44 217 if (type->unary_op != NULL) {
pythontech 0:5868e8752d44 218 mp_obj_t result = type->unary_op(op, arg);
pythontech 0:5868e8752d44 219 if (result != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 220 return result;
pythontech 0:5868e8752d44 221 }
pythontech 0:5868e8752d44 222 }
pythontech 0:5868e8752d44 223 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 224 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
pythontech 0:5868e8752d44 225 "unsupported type for operator"));
pythontech 0:5868e8752d44 226 } else {
pythontech 0:5868e8752d44 227 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
pythontech 0:5868e8752d44 228 "unsupported type for %q: '%s'",
pythontech 0:5868e8752d44 229 mp_unary_op_method_name[op], mp_obj_get_type_str(arg)));
pythontech 0:5868e8752d44 230 }
pythontech 0:5868e8752d44 231 }
pythontech 0:5868e8752d44 232 }
pythontech 0:5868e8752d44 233
pythontech 0:5868e8752d44 234 mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
pythontech 0:5868e8752d44 235 DEBUG_OP_printf("binary " UINT_FMT " %p %p\n", op, lhs, rhs);
pythontech 0:5868e8752d44 236
pythontech 0:5868e8752d44 237 // TODO correctly distinguish inplace operators for mutable objects
pythontech 0:5868e8752d44 238 // lookup logic that CPython uses for +=:
pythontech 0:5868e8752d44 239 // check for implemented +=
pythontech 0:5868e8752d44 240 // then check for implemented +
pythontech 0:5868e8752d44 241 // then check for implemented seq.inplace_concat
pythontech 0:5868e8752d44 242 // then check for implemented seq.concat
pythontech 0:5868e8752d44 243 // then fail
pythontech 0:5868e8752d44 244 // note that list does not implement + or +=, so that inplace_concat is reached first for +=
pythontech 0:5868e8752d44 245
pythontech 0:5868e8752d44 246 // deal with is
pythontech 0:5868e8752d44 247 if (op == MP_BINARY_OP_IS) {
pythontech 0:5868e8752d44 248 return mp_obj_new_bool(lhs == rhs);
pythontech 0:5868e8752d44 249 }
pythontech 0:5868e8752d44 250
pythontech 0:5868e8752d44 251 // deal with == and != for all types
pythontech 0:5868e8752d44 252 if (op == MP_BINARY_OP_EQUAL || op == MP_BINARY_OP_NOT_EQUAL) {
pythontech 0:5868e8752d44 253 if (mp_obj_equal(lhs, rhs)) {
pythontech 0:5868e8752d44 254 if (op == MP_BINARY_OP_EQUAL) {
pythontech 0:5868e8752d44 255 return mp_const_true;
pythontech 0:5868e8752d44 256 } else {
pythontech 0:5868e8752d44 257 return mp_const_false;
pythontech 0:5868e8752d44 258 }
pythontech 0:5868e8752d44 259 } else {
pythontech 0:5868e8752d44 260 if (op == MP_BINARY_OP_EQUAL) {
pythontech 0:5868e8752d44 261 return mp_const_false;
pythontech 0:5868e8752d44 262 } else {
pythontech 0:5868e8752d44 263 return mp_const_true;
pythontech 0:5868e8752d44 264 }
pythontech 0:5868e8752d44 265 }
pythontech 0:5868e8752d44 266 }
pythontech 0:5868e8752d44 267
pythontech 0:5868e8752d44 268 // deal with exception_match for all types
pythontech 0:5868e8752d44 269 if (op == MP_BINARY_OP_EXCEPTION_MATCH) {
pythontech 0:5868e8752d44 270 // rhs must be issubclass(rhs, BaseException)
pythontech 0:5868e8752d44 271 if (mp_obj_is_exception_type(rhs)) {
pythontech 0:5868e8752d44 272 if (mp_obj_exception_match(lhs, rhs)) {
pythontech 0:5868e8752d44 273 return mp_const_true;
pythontech 0:5868e8752d44 274 } else {
pythontech 0:5868e8752d44 275 return mp_const_false;
pythontech 0:5868e8752d44 276 }
pythontech 0:5868e8752d44 277 } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_tuple)) {
pythontech 0:5868e8752d44 278 mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(rhs);
pythontech 0:5868e8752d44 279 for (mp_uint_t i = 0; i < tuple->len; i++) {
pythontech 0:5868e8752d44 280 rhs = tuple->items[i];
pythontech 0:5868e8752d44 281 if (!mp_obj_is_exception_type(rhs)) {
pythontech 0:5868e8752d44 282 goto unsupported_op;
pythontech 0:5868e8752d44 283 }
pythontech 0:5868e8752d44 284 if (mp_obj_exception_match(lhs, rhs)) {
pythontech 0:5868e8752d44 285 return mp_const_true;
pythontech 0:5868e8752d44 286 }
pythontech 0:5868e8752d44 287 }
pythontech 0:5868e8752d44 288 return mp_const_false;
pythontech 0:5868e8752d44 289 }
pythontech 0:5868e8752d44 290 goto unsupported_op;
pythontech 0:5868e8752d44 291 }
pythontech 0:5868e8752d44 292
pythontech 0:5868e8752d44 293 if (MP_OBJ_IS_SMALL_INT(lhs)) {
pythontech 0:5868e8752d44 294 mp_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
pythontech 0:5868e8752d44 295 if (MP_OBJ_IS_SMALL_INT(rhs)) {
pythontech 0:5868e8752d44 296 mp_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
pythontech 0:5868e8752d44 297 // This is a binary operation: lhs_val op rhs_val
pythontech 0:5868e8752d44 298 // We need to be careful to handle overflow; see CERT INT32-C
pythontech 0:5868e8752d44 299 // Operations that can overflow:
pythontech 0:5868e8752d44 300 // + result always fits in mp_int_t, then handled by SMALL_INT check
pythontech 0:5868e8752d44 301 // - result always fits in mp_int_t, then handled by SMALL_INT check
pythontech 0:5868e8752d44 302 // * checked explicitly
pythontech 0:5868e8752d44 303 // / if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check
pythontech 0:5868e8752d44 304 // % if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check
pythontech 0:5868e8752d44 305 // << checked explicitly
pythontech 0:5868e8752d44 306 switch (op) {
pythontech 0:5868e8752d44 307 case MP_BINARY_OP_OR:
pythontech 0:5868e8752d44 308 case MP_BINARY_OP_INPLACE_OR: lhs_val |= rhs_val; break;
pythontech 0:5868e8752d44 309 case MP_BINARY_OP_XOR:
pythontech 0:5868e8752d44 310 case MP_BINARY_OP_INPLACE_XOR: lhs_val ^= rhs_val; break;
pythontech 0:5868e8752d44 311 case MP_BINARY_OP_AND:
pythontech 0:5868e8752d44 312 case MP_BINARY_OP_INPLACE_AND: lhs_val &= rhs_val; break;
pythontech 0:5868e8752d44 313 case MP_BINARY_OP_LSHIFT:
pythontech 0:5868e8752d44 314 case MP_BINARY_OP_INPLACE_LSHIFT: {
pythontech 0:5868e8752d44 315 if (rhs_val < 0) {
pythontech 0:5868e8752d44 316 // negative shift not allowed
pythontech 0:5868e8752d44 317 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
pythontech 0:5868e8752d44 318 } else if (rhs_val >= (mp_int_t)BITS_PER_WORD || lhs_val > (MP_SMALL_INT_MAX >> rhs_val) || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) {
pythontech 0:5868e8752d44 319 // left-shift will overflow, so use higher precision integer
pythontech 0:5868e8752d44 320 lhs = mp_obj_new_int_from_ll(lhs_val);
pythontech 0:5868e8752d44 321 goto generic_binary_op;
pythontech 0:5868e8752d44 322 } else {
pythontech 0:5868e8752d44 323 // use standard precision
pythontech 0:5868e8752d44 324 lhs_val <<= rhs_val;
pythontech 0:5868e8752d44 325 }
pythontech 0:5868e8752d44 326 break;
pythontech 0:5868e8752d44 327 }
pythontech 0:5868e8752d44 328 case MP_BINARY_OP_RSHIFT:
pythontech 0:5868e8752d44 329 case MP_BINARY_OP_INPLACE_RSHIFT:
pythontech 0:5868e8752d44 330 if (rhs_val < 0) {
pythontech 0:5868e8752d44 331 // negative shift not allowed
pythontech 0:5868e8752d44 332 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
pythontech 0:5868e8752d44 333 } else {
pythontech 0:5868e8752d44 334 // standard precision is enough for right-shift
pythontech 0:5868e8752d44 335 if (rhs_val >= (mp_int_t)BITS_PER_WORD) {
pythontech 0:5868e8752d44 336 // Shifting to big amounts is underfined behavior
pythontech 0:5868e8752d44 337 // in C and is CPU-dependent; propagate sign bit.
pythontech 0:5868e8752d44 338 rhs_val = BITS_PER_WORD - 1;
pythontech 0:5868e8752d44 339 }
pythontech 0:5868e8752d44 340 lhs_val >>= rhs_val;
pythontech 0:5868e8752d44 341 }
pythontech 0:5868e8752d44 342 break;
pythontech 0:5868e8752d44 343 case MP_BINARY_OP_ADD:
pythontech 0:5868e8752d44 344 case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
pythontech 0:5868e8752d44 345 case MP_BINARY_OP_SUBTRACT:
pythontech 0:5868e8752d44 346 case MP_BINARY_OP_INPLACE_SUBTRACT: lhs_val -= rhs_val; break;
pythontech 0:5868e8752d44 347 case MP_BINARY_OP_MULTIPLY:
pythontech 0:5868e8752d44 348 case MP_BINARY_OP_INPLACE_MULTIPLY: {
pythontech 0:5868e8752d44 349
pythontech 0:5868e8752d44 350 // If long long type exists and is larger than mp_int_t, then
pythontech 0:5868e8752d44 351 // we can use the following code to perform overflow-checked multiplication.
pythontech 0:5868e8752d44 352 // Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow.
pythontech 0:5868e8752d44 353 #if 0
pythontech 0:5868e8752d44 354 // compute result using long long precision
pythontech 0:5868e8752d44 355 long long res = (long long)lhs_val * (long long)rhs_val;
pythontech 0:5868e8752d44 356 if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) {
pythontech 0:5868e8752d44 357 // result overflowed SMALL_INT, so return higher precision integer
pythontech 0:5868e8752d44 358 return mp_obj_new_int_from_ll(res);
pythontech 0:5868e8752d44 359 } else {
pythontech 0:5868e8752d44 360 // use standard precision
pythontech 0:5868e8752d44 361 lhs_val = (mp_int_t)res;
pythontech 0:5868e8752d44 362 }
pythontech 0:5868e8752d44 363 #endif
pythontech 0:5868e8752d44 364
pythontech 0:5868e8752d44 365 if (mp_small_int_mul_overflow(lhs_val, rhs_val)) {
pythontech 0:5868e8752d44 366 // use higher precision
pythontech 0:5868e8752d44 367 lhs = mp_obj_new_int_from_ll(lhs_val);
pythontech 0:5868e8752d44 368 goto generic_binary_op;
pythontech 0:5868e8752d44 369 } else {
pythontech 0:5868e8752d44 370 // use standard precision
pythontech 0:5868e8752d44 371 return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val);
pythontech 0:5868e8752d44 372 }
pythontech 0:5868e8752d44 373 break;
pythontech 0:5868e8752d44 374 }
pythontech 0:5868e8752d44 375 case MP_BINARY_OP_FLOOR_DIVIDE:
pythontech 0:5868e8752d44 376 case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE:
pythontech 0:5868e8752d44 377 if (rhs_val == 0) {
pythontech 0:5868e8752d44 378 goto zero_division;
pythontech 0:5868e8752d44 379 }
pythontech 0:5868e8752d44 380 lhs_val = mp_small_int_floor_divide(lhs_val, rhs_val);
pythontech 0:5868e8752d44 381 break;
pythontech 0:5868e8752d44 382
pythontech 0:5868e8752d44 383 #if MICROPY_PY_BUILTINS_FLOAT
pythontech 0:5868e8752d44 384 case MP_BINARY_OP_TRUE_DIVIDE:
pythontech 0:5868e8752d44 385 case MP_BINARY_OP_INPLACE_TRUE_DIVIDE:
pythontech 0:5868e8752d44 386 if (rhs_val == 0) {
pythontech 0:5868e8752d44 387 goto zero_division;
pythontech 0:5868e8752d44 388 }
pythontech 0:5868e8752d44 389 return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val);
pythontech 0:5868e8752d44 390 #endif
pythontech 0:5868e8752d44 391
pythontech 0:5868e8752d44 392 case MP_BINARY_OP_MODULO:
pythontech 0:5868e8752d44 393 case MP_BINARY_OP_INPLACE_MODULO: {
pythontech 0:5868e8752d44 394 if (rhs_val == 0) {
pythontech 0:5868e8752d44 395 goto zero_division;
pythontech 0:5868e8752d44 396 }
pythontech 0:5868e8752d44 397 lhs_val = mp_small_int_modulo(lhs_val, rhs_val);
pythontech 0:5868e8752d44 398 break;
pythontech 0:5868e8752d44 399 }
pythontech 0:5868e8752d44 400
pythontech 0:5868e8752d44 401 case MP_BINARY_OP_POWER:
pythontech 0:5868e8752d44 402 case MP_BINARY_OP_INPLACE_POWER:
pythontech 0:5868e8752d44 403 if (rhs_val < 0) {
pythontech 0:5868e8752d44 404 #if MICROPY_PY_BUILTINS_FLOAT
pythontech 0:5868e8752d44 405 lhs = mp_obj_new_float(lhs_val);
pythontech 0:5868e8752d44 406 goto generic_binary_op;
pythontech 0:5868e8752d44 407 #else
pythontech 0:5868e8752d44 408 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative power with no float support"));
pythontech 0:5868e8752d44 409 #endif
pythontech 0:5868e8752d44 410 } else {
pythontech 0:5868e8752d44 411 mp_int_t ans = 1;
pythontech 0:5868e8752d44 412 while (rhs_val > 0) {
pythontech 0:5868e8752d44 413 if (rhs_val & 1) {
pythontech 0:5868e8752d44 414 if (mp_small_int_mul_overflow(ans, lhs_val)) {
pythontech 0:5868e8752d44 415 goto power_overflow;
pythontech 0:5868e8752d44 416 }
pythontech 0:5868e8752d44 417 ans *= lhs_val;
pythontech 0:5868e8752d44 418 }
pythontech 0:5868e8752d44 419 if (rhs_val == 1) {
pythontech 0:5868e8752d44 420 break;
pythontech 0:5868e8752d44 421 }
pythontech 0:5868e8752d44 422 rhs_val /= 2;
pythontech 0:5868e8752d44 423 if (mp_small_int_mul_overflow(lhs_val, lhs_val)) {
pythontech 0:5868e8752d44 424 goto power_overflow;
pythontech 0:5868e8752d44 425 }
pythontech 0:5868e8752d44 426 lhs_val *= lhs_val;
pythontech 0:5868e8752d44 427 }
pythontech 0:5868e8752d44 428 lhs_val = ans;
pythontech 0:5868e8752d44 429 }
pythontech 0:5868e8752d44 430 break;
pythontech 0:5868e8752d44 431
pythontech 0:5868e8752d44 432 power_overflow:
pythontech 0:5868e8752d44 433 // use higher precision
pythontech 0:5868e8752d44 434 lhs = mp_obj_new_int_from_ll(MP_OBJ_SMALL_INT_VALUE(lhs));
pythontech 0:5868e8752d44 435 goto generic_binary_op;
pythontech 0:5868e8752d44 436
pythontech 0:5868e8752d44 437 case MP_BINARY_OP_DIVMOD: {
pythontech 0:5868e8752d44 438 if (rhs_val == 0) {
pythontech 0:5868e8752d44 439 goto zero_division;
pythontech 0:5868e8752d44 440 }
pythontech 0:5868e8752d44 441 // to reduce stack usage we don't pass a temp array of the 2 items
pythontech 0:5868e8752d44 442 mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
pythontech 0:5868e8752d44 443 tuple->items[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(lhs_val, rhs_val));
pythontech 0:5868e8752d44 444 tuple->items[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(lhs_val, rhs_val));
pythontech 0:5868e8752d44 445 return MP_OBJ_FROM_PTR(tuple);
pythontech 0:5868e8752d44 446 }
pythontech 0:5868e8752d44 447
pythontech 0:5868e8752d44 448 case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); break;
pythontech 0:5868e8752d44 449 case MP_BINARY_OP_MORE: return mp_obj_new_bool(lhs_val > rhs_val); break;
pythontech 0:5868e8752d44 450 case MP_BINARY_OP_LESS_EQUAL: return mp_obj_new_bool(lhs_val <= rhs_val); break;
pythontech 0:5868e8752d44 451 case MP_BINARY_OP_MORE_EQUAL: return mp_obj_new_bool(lhs_val >= rhs_val); break;
pythontech 0:5868e8752d44 452
pythontech 0:5868e8752d44 453 default:
pythontech 0:5868e8752d44 454 goto unsupported_op;
pythontech 0:5868e8752d44 455 }
pythontech 0:5868e8752d44 456 // TODO: We just should make mp_obj_new_int() inline and use that
pythontech 0:5868e8752d44 457 if (MP_SMALL_INT_FITS(lhs_val)) {
pythontech 0:5868e8752d44 458 return MP_OBJ_NEW_SMALL_INT(lhs_val);
pythontech 0:5868e8752d44 459 } else {
pythontech 0:5868e8752d44 460 return mp_obj_new_int(lhs_val);
pythontech 0:5868e8752d44 461 }
pythontech 0:5868e8752d44 462 #if MICROPY_PY_BUILTINS_FLOAT
pythontech 0:5868e8752d44 463 } else if (mp_obj_is_float(rhs)) {
pythontech 0:5868e8752d44 464 mp_obj_t res = mp_obj_float_binary_op(op, lhs_val, rhs);
pythontech 0:5868e8752d44 465 if (res == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 466 goto unsupported_op;
pythontech 0:5868e8752d44 467 } else {
pythontech 0:5868e8752d44 468 return res;
pythontech 0:5868e8752d44 469 }
pythontech 0:5868e8752d44 470 #if MICROPY_PY_BUILTINS_COMPLEX
pythontech 0:5868e8752d44 471 } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {
pythontech 0:5868e8752d44 472 mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
pythontech 0:5868e8752d44 473 if (res == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 474 goto unsupported_op;
pythontech 0:5868e8752d44 475 } else {
pythontech 0:5868e8752d44 476 return res;
pythontech 0:5868e8752d44 477 }
pythontech 0:5868e8752d44 478 #endif
pythontech 0:5868e8752d44 479 #endif
pythontech 0:5868e8752d44 480 }
pythontech 0:5868e8752d44 481 }
pythontech 0:5868e8752d44 482
pythontech 0:5868e8752d44 483 /* deal with `in`
pythontech 0:5868e8752d44 484 *
pythontech 0:5868e8752d44 485 * NOTE `a in b` is `b.__contains__(a)`, hence why the generic dispatch
pythontech 0:5868e8752d44 486 * needs to go below with swapped arguments
pythontech 0:5868e8752d44 487 */
pythontech 0:5868e8752d44 488 if (op == MP_BINARY_OP_IN) {
pythontech 0:5868e8752d44 489 mp_obj_type_t *type = mp_obj_get_type(rhs);
pythontech 0:5868e8752d44 490 if (type->binary_op != NULL) {
pythontech 0:5868e8752d44 491 mp_obj_t res = type->binary_op(op, rhs, lhs);
pythontech 0:5868e8752d44 492 if (res != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 493 return res;
pythontech 0:5868e8752d44 494 }
pythontech 0:5868e8752d44 495 }
pythontech 0:5868e8752d44 496 if (type->getiter != NULL) {
pythontech 0:5868e8752d44 497 /* second attempt, walk the iterator */
pythontech 0:5868e8752d44 498 mp_obj_t iter = mp_getiter(rhs);
pythontech 0:5868e8752d44 499 mp_obj_t next;
pythontech 0:5868e8752d44 500 while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 501 if (mp_obj_equal(next, lhs)) {
pythontech 0:5868e8752d44 502 return mp_const_true;
pythontech 0:5868e8752d44 503 }
pythontech 0:5868e8752d44 504 }
pythontech 0:5868e8752d44 505 return mp_const_false;
pythontech 0:5868e8752d44 506 }
pythontech 0:5868e8752d44 507
pythontech 0:5868e8752d44 508 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 509 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
pythontech 0:5868e8752d44 510 "object not iterable"));
pythontech 0:5868e8752d44 511 } else {
pythontech 0:5868e8752d44 512 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
pythontech 0:5868e8752d44 513 "'%s' object is not iterable", mp_obj_get_type_str(rhs)));
pythontech 0:5868e8752d44 514 }
pythontech 0:5868e8752d44 515 }
pythontech 0:5868e8752d44 516
pythontech 0:5868e8752d44 517 // generic binary_op supplied by type
pythontech 0:5868e8752d44 518 mp_obj_type_t *type;
pythontech 0:5868e8752d44 519 generic_binary_op:
pythontech 0:5868e8752d44 520 type = mp_obj_get_type(lhs);
pythontech 0:5868e8752d44 521 if (type->binary_op != NULL) {
pythontech 0:5868e8752d44 522 mp_obj_t result = type->binary_op(op, lhs, rhs);
pythontech 0:5868e8752d44 523 if (result != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 524 return result;
pythontech 0:5868e8752d44 525 }
pythontech 0:5868e8752d44 526 }
pythontech 0:5868e8752d44 527
pythontech 0:5868e8752d44 528 // TODO implement dispatch for reverse binary ops
pythontech 0:5868e8752d44 529
pythontech 0:5868e8752d44 530 unsupported_op:
pythontech 0:5868e8752d44 531 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 532 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
pythontech 0:5868e8752d44 533 "unsupported type for operator"));
pythontech 0:5868e8752d44 534 } else {
pythontech 0:5868e8752d44 535 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
pythontech 0:5868e8752d44 536 "unsupported types for %q: '%s', '%s'",
pythontech 0:5868e8752d44 537 mp_binary_op_method_name[op], mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
pythontech 0:5868e8752d44 538 }
pythontech 0:5868e8752d44 539
pythontech 0:5868e8752d44 540 zero_division:
pythontech 0:5868e8752d44 541 nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero"));
pythontech 0:5868e8752d44 542 }
pythontech 0:5868e8752d44 543
pythontech 0:5868e8752d44 544 mp_obj_t mp_call_function_0(mp_obj_t fun) {
pythontech 0:5868e8752d44 545 return mp_call_function_n_kw(fun, 0, 0, NULL);
pythontech 0:5868e8752d44 546 }
pythontech 0:5868e8752d44 547
pythontech 0:5868e8752d44 548 mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg) {
pythontech 0:5868e8752d44 549 return mp_call_function_n_kw(fun, 1, 0, &arg);
pythontech 0:5868e8752d44 550 }
pythontech 0:5868e8752d44 551
pythontech 0:5868e8752d44 552 mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {
pythontech 0:5868e8752d44 553 mp_obj_t args[2];
pythontech 0:5868e8752d44 554 args[0] = arg1;
pythontech 0:5868e8752d44 555 args[1] = arg2;
pythontech 0:5868e8752d44 556 return mp_call_function_n_kw(fun, 2, 0, args);
pythontech 0:5868e8752d44 557 }
pythontech 0:5868e8752d44 558
pythontech 0:5868e8752d44 559 // args contains, eg: arg0 arg1 key0 value0 key1 value1
pythontech 0:5868e8752d44 560 mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
pythontech 0:5868e8752d44 561 // TODO improve this: fun object can specify its type and we parse here the arguments,
pythontech 0:5868e8752d44 562 // passing to the function arrays of fixed and keyword arguments
pythontech 0:5868e8752d44 563
pythontech 0:5868e8752d44 564 DEBUG_OP_printf("calling function %p(n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", fun_in, n_args, n_kw, args);
pythontech 0:5868e8752d44 565
pythontech 0:5868e8752d44 566 // get the type
pythontech 0:5868e8752d44 567 mp_obj_type_t *type = mp_obj_get_type(fun_in);
pythontech 0:5868e8752d44 568
pythontech 0:5868e8752d44 569 // do the call
pythontech 0:5868e8752d44 570 if (type->call != NULL) {
pythontech 0:5868e8752d44 571 return type->call(fun_in, n_args, n_kw, args);
pythontech 0:5868e8752d44 572 }
pythontech 0:5868e8752d44 573
pythontech 0:5868e8752d44 574 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 575 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
pythontech 0:5868e8752d44 576 "object not callable"));
pythontech 0:5868e8752d44 577 } else {
pythontech 0:5868e8752d44 578 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
pythontech 0:5868e8752d44 579 "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
pythontech 0:5868e8752d44 580 }
pythontech 0:5868e8752d44 581 }
pythontech 0:5868e8752d44 582
pythontech 0:5868e8752d44 583 // args contains: fun self/NULL arg(0) ... arg(n_args-2) arg(n_args-1) kw_key(0) kw_val(0) ... kw_key(n_kw-1) kw_val(n_kw-1)
pythontech 0:5868e8752d44 584 // if n_args==0 and n_kw==0 then there are only fun and self/NULL
pythontech 0:5868e8752d44 585 mp_obj_t mp_call_method_n_kw(mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
pythontech 0:5868e8752d44 586 DEBUG_OP_printf("call method (fun=%p, self=%p, n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", args[0], args[1], n_args, n_kw, args);
pythontech 0:5868e8752d44 587 int adjust = (args[1] == MP_OBJ_NULL) ? 0 : 1;
pythontech 0:5868e8752d44 588 return mp_call_function_n_kw(args[0], n_args + adjust, n_kw, args + 2 - adjust);
pythontech 0:5868e8752d44 589 }
pythontech 0:5868e8752d44 590
pythontech 0:5868e8752d44 591 // This function only needs to be exposed externally when in stackless mode.
pythontech 0:5868e8752d44 592 #if !MICROPY_STACKLESS
pythontech 0:5868e8752d44 593 STATIC
pythontech 0:5868e8752d44 594 #endif
pythontech 0:5868e8752d44 595 void mp_call_prepare_args_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args) {
pythontech 0:5868e8752d44 596 mp_obj_t fun = *args++;
pythontech 0:5868e8752d44 597 mp_obj_t self = MP_OBJ_NULL;
pythontech 0:5868e8752d44 598 if (have_self) {
pythontech 0:5868e8752d44 599 self = *args++; // may be MP_OBJ_NULL
pythontech 0:5868e8752d44 600 }
pythontech 0:5868e8752d44 601 uint n_args = n_args_n_kw & 0xff;
pythontech 0:5868e8752d44 602 uint n_kw = (n_args_n_kw >> 8) & 0xff;
pythontech 0:5868e8752d44 603 mp_obj_t pos_seq = args[n_args + 2 * n_kw]; // may be MP_OBJ_NULL
pythontech 0:5868e8752d44 604 mp_obj_t kw_dict = args[n_args + 2 * n_kw + 1]; // may be MP_OBJ_NULL
pythontech 0:5868e8752d44 605
pythontech 0:5868e8752d44 606 DEBUG_OP_printf("call method var (fun=%p, self=%p, n_args=%u, n_kw=%u, args=%p, seq=%p, dict=%p)\n", fun, self, n_args, n_kw, args, pos_seq, kw_dict);
pythontech 0:5868e8752d44 607
pythontech 0:5868e8752d44 608 // We need to create the following array of objects:
pythontech 0:5868e8752d44 609 // args[0 .. n_args] unpacked(pos_seq) args[n_args .. n_args + 2 * n_kw] unpacked(kw_dict)
pythontech 0:5868e8752d44 610 // TODO: optimize one day to avoid constructing new arg array? Will be hard.
pythontech 0:5868e8752d44 611
pythontech 0:5868e8752d44 612 // The new args array
pythontech 0:5868e8752d44 613 mp_obj_t *args2;
pythontech 0:5868e8752d44 614 uint args2_alloc;
pythontech 0:5868e8752d44 615 uint args2_len = 0;
pythontech 0:5868e8752d44 616
pythontech 0:5868e8752d44 617 // Try to get a hint for the size of the kw_dict
pythontech 0:5868e8752d44 618 uint kw_dict_len = 0;
pythontech 0:5868e8752d44 619 if (kw_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(kw_dict, &mp_type_dict)) {
pythontech 0:5868e8752d44 620 kw_dict_len = mp_obj_dict_len(kw_dict);
pythontech 0:5868e8752d44 621 }
pythontech 0:5868e8752d44 622
pythontech 0:5868e8752d44 623 // Extract the pos_seq sequence to the new args array.
pythontech 0:5868e8752d44 624 // Note that it can be arbitrary iterator.
pythontech 0:5868e8752d44 625 if (pos_seq == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 626 // no sequence
pythontech 0:5868e8752d44 627
pythontech 0:5868e8752d44 628 // allocate memory for the new array of args
pythontech 0:5868e8752d44 629 args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len);
pythontech 0:5868e8752d44 630 args2 = m_new(mp_obj_t, args2_alloc);
pythontech 0:5868e8752d44 631
pythontech 0:5868e8752d44 632 // copy the self
pythontech 0:5868e8752d44 633 if (self != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 634 args2[args2_len++] = self;
pythontech 0:5868e8752d44 635 }
pythontech 0:5868e8752d44 636
pythontech 0:5868e8752d44 637 // copy the fixed pos args
pythontech 0:5868e8752d44 638 mp_seq_copy(args2 + args2_len, args, n_args, mp_obj_t);
pythontech 0:5868e8752d44 639 args2_len += n_args;
pythontech 0:5868e8752d44 640
pythontech 0:5868e8752d44 641 } else if (MP_OBJ_IS_TYPE(pos_seq, &mp_type_tuple) || MP_OBJ_IS_TYPE(pos_seq, &mp_type_list)) {
pythontech 0:5868e8752d44 642 // optimise the case of a tuple and list
pythontech 0:5868e8752d44 643
pythontech 0:5868e8752d44 644 // get the items
pythontech 0:5868e8752d44 645 mp_uint_t len;
pythontech 0:5868e8752d44 646 mp_obj_t *items;
pythontech 0:5868e8752d44 647 mp_obj_get_array(pos_seq, &len, &items);
pythontech 0:5868e8752d44 648
pythontech 0:5868e8752d44 649 // allocate memory for the new array of args
pythontech 0:5868e8752d44 650 args2_alloc = 1 + n_args + len + 2 * (n_kw + kw_dict_len);
pythontech 0:5868e8752d44 651 args2 = m_new(mp_obj_t, args2_alloc);
pythontech 0:5868e8752d44 652
pythontech 0:5868e8752d44 653 // copy the self
pythontech 0:5868e8752d44 654 if (self != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 655 args2[args2_len++] = self;
pythontech 0:5868e8752d44 656 }
pythontech 0:5868e8752d44 657
pythontech 0:5868e8752d44 658 // copy the fixed and variable position args
pythontech 0:5868e8752d44 659 mp_seq_cat(args2 + args2_len, args, n_args, items, len, mp_obj_t);
pythontech 0:5868e8752d44 660 args2_len += n_args + len;
pythontech 0:5868e8752d44 661
pythontech 0:5868e8752d44 662 } else {
pythontech 0:5868e8752d44 663 // generic iterator
pythontech 0:5868e8752d44 664
pythontech 0:5868e8752d44 665 // allocate memory for the new array of args
pythontech 0:5868e8752d44 666 args2_alloc = 1 + n_args + 2 * (n_kw + kw_dict_len) + 3;
pythontech 0:5868e8752d44 667 args2 = m_new(mp_obj_t, args2_alloc);
pythontech 0:5868e8752d44 668
pythontech 0:5868e8752d44 669 // copy the self
pythontech 0:5868e8752d44 670 if (self != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 671 args2[args2_len++] = self;
pythontech 0:5868e8752d44 672 }
pythontech 0:5868e8752d44 673
pythontech 0:5868e8752d44 674 // copy the fixed position args
pythontech 0:5868e8752d44 675 mp_seq_copy(args2 + args2_len, args, n_args, mp_obj_t);
pythontech 0:5868e8752d44 676 args2_len += n_args;
pythontech 0:5868e8752d44 677
pythontech 0:5868e8752d44 678 // extract the variable position args from the iterator
pythontech 0:5868e8752d44 679 mp_obj_t iterable = mp_getiter(pos_seq);
pythontech 0:5868e8752d44 680 mp_obj_t item;
pythontech 0:5868e8752d44 681 while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 682 if (args2_len >= args2_alloc) {
pythontech 0:5868e8752d44 683 args2 = m_renew(mp_obj_t, args2, args2_alloc, args2_alloc * 2);
pythontech 0:5868e8752d44 684 args2_alloc *= 2;
pythontech 0:5868e8752d44 685 }
pythontech 0:5868e8752d44 686 args2[args2_len++] = item;
pythontech 0:5868e8752d44 687 }
pythontech 0:5868e8752d44 688 }
pythontech 0:5868e8752d44 689
pythontech 0:5868e8752d44 690 // The size of the args2 array now is the number of positional args.
pythontech 0:5868e8752d44 691 uint pos_args_len = args2_len;
pythontech 0:5868e8752d44 692
pythontech 0:5868e8752d44 693 // Copy the fixed kw args.
pythontech 0:5868e8752d44 694 mp_seq_copy(args2 + args2_len, args + n_args, 2 * n_kw, mp_obj_t);
pythontech 0:5868e8752d44 695 args2_len += 2 * n_kw;
pythontech 0:5868e8752d44 696
pythontech 0:5868e8752d44 697 // Extract (key,value) pairs from kw_dict dictionary and append to args2.
pythontech 0:5868e8752d44 698 // Note that it can be arbitrary iterator.
pythontech 0:5868e8752d44 699 if (kw_dict == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 700 // pass
pythontech 0:5868e8752d44 701 } else if (MP_OBJ_IS_TYPE(kw_dict, &mp_type_dict)) {
pythontech 0:5868e8752d44 702 // dictionary
pythontech 0:5868e8752d44 703 mp_map_t *map = mp_obj_dict_get_map(kw_dict);
pythontech 0:5868e8752d44 704 assert(args2_len + 2 * map->used <= args2_alloc); // should have enough, since kw_dict_len is in this case hinted correctly above
pythontech 0:5868e8752d44 705 for (mp_uint_t i = 0; i < map->alloc; i++) {
pythontech 0:5868e8752d44 706 if (MP_MAP_SLOT_IS_FILLED(map, i)) {
pythontech 0:5868e8752d44 707 args2[args2_len++] = map->table[i].key;
pythontech 0:5868e8752d44 708 args2[args2_len++] = map->table[i].value;
pythontech 0:5868e8752d44 709 }
pythontech 0:5868e8752d44 710 }
pythontech 0:5868e8752d44 711 } else {
pythontech 0:5868e8752d44 712 // generic mapping
pythontech 0:5868e8752d44 713 // TODO is calling 'items' on the mapping the correct thing to do here?
pythontech 0:5868e8752d44 714 mp_obj_t dest[2];
pythontech 0:5868e8752d44 715 mp_load_method(kw_dict, MP_QSTR_items, dest);
pythontech 0:5868e8752d44 716 mp_obj_t iterable = mp_getiter(mp_call_method_n_kw(0, 0, dest));
pythontech 0:5868e8752d44 717 mp_obj_t item;
pythontech 0:5868e8752d44 718 while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 719 if (args2_len + 1 >= args2_alloc) {
pythontech 0:5868e8752d44 720 uint new_alloc = args2_alloc * 2;
pythontech 0:5868e8752d44 721 if (new_alloc < 4) {
pythontech 0:5868e8752d44 722 new_alloc = 4;
pythontech 0:5868e8752d44 723 }
pythontech 0:5868e8752d44 724 args2 = m_renew(mp_obj_t, args2, args2_alloc, new_alloc);
pythontech 0:5868e8752d44 725 args2_alloc = new_alloc;
pythontech 0:5868e8752d44 726 }
pythontech 0:5868e8752d44 727 mp_obj_t *items;
pythontech 0:5868e8752d44 728 mp_obj_get_array_fixed_n(item, 2, &items);
pythontech 0:5868e8752d44 729 args2[args2_len++] = items[0];
pythontech 0:5868e8752d44 730 args2[args2_len++] = items[1];
pythontech 0:5868e8752d44 731 }
pythontech 0:5868e8752d44 732 }
pythontech 0:5868e8752d44 733
pythontech 0:5868e8752d44 734 out_args->fun = fun;
pythontech 0:5868e8752d44 735 out_args->args = args2;
pythontech 0:5868e8752d44 736 out_args->n_args = pos_args_len;
pythontech 0:5868e8752d44 737 out_args->n_kw = (args2_len - pos_args_len) / 2;
pythontech 0:5868e8752d44 738 out_args->n_alloc = args2_alloc;
pythontech 0:5868e8752d44 739 }
pythontech 0:5868e8752d44 740
pythontech 0:5868e8752d44 741 mp_obj_t mp_call_method_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const mp_obj_t *args) {
pythontech 0:5868e8752d44 742 mp_call_args_t out_args;
pythontech 0:5868e8752d44 743 mp_call_prepare_args_n_kw_var(have_self, n_args_n_kw, args, &out_args);
pythontech 0:5868e8752d44 744
pythontech 0:5868e8752d44 745 mp_obj_t res = mp_call_function_n_kw(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args);
pythontech 0:5868e8752d44 746 m_del(mp_obj_t, out_args.args, out_args.n_alloc);
pythontech 0:5868e8752d44 747
pythontech 0:5868e8752d44 748 return res;
pythontech 0:5868e8752d44 749 }
pythontech 0:5868e8752d44 750
pythontech 0:5868e8752d44 751 // unpacked items are stored in reverse order into the array pointed to by items
pythontech 0:5868e8752d44 752 void mp_unpack_sequence(mp_obj_t seq_in, mp_uint_t num, mp_obj_t *items) {
pythontech 0:5868e8752d44 753 mp_uint_t seq_len;
pythontech 0:5868e8752d44 754 if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
pythontech 0:5868e8752d44 755 mp_obj_t *seq_items;
pythontech 0:5868e8752d44 756 if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) {
pythontech 0:5868e8752d44 757 mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
pythontech 0:5868e8752d44 758 } else {
pythontech 0:5868e8752d44 759 mp_obj_list_get(seq_in, &seq_len, &seq_items);
pythontech 0:5868e8752d44 760 }
pythontech 0:5868e8752d44 761 if (seq_len < num) {
pythontech 0:5868e8752d44 762 goto too_short;
pythontech 0:5868e8752d44 763 } else if (seq_len > num) {
pythontech 0:5868e8752d44 764 goto too_long;
pythontech 0:5868e8752d44 765 }
pythontech 0:5868e8752d44 766 for (mp_uint_t i = 0; i < num; i++) {
pythontech 0:5868e8752d44 767 items[i] = seq_items[num - 1 - i];
pythontech 0:5868e8752d44 768 }
pythontech 0:5868e8752d44 769 } else {
pythontech 0:5868e8752d44 770 mp_obj_t iterable = mp_getiter(seq_in);
pythontech 0:5868e8752d44 771
pythontech 0:5868e8752d44 772 for (seq_len = 0; seq_len < num; seq_len++) {
pythontech 0:5868e8752d44 773 mp_obj_t el = mp_iternext(iterable);
pythontech 0:5868e8752d44 774 if (el == MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 775 goto too_short;
pythontech 0:5868e8752d44 776 }
pythontech 0:5868e8752d44 777 items[num - 1 - seq_len] = el;
pythontech 0:5868e8752d44 778 }
pythontech 0:5868e8752d44 779 if (mp_iternext(iterable) != MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 780 goto too_long;
pythontech 0:5868e8752d44 781 }
pythontech 0:5868e8752d44 782 }
pythontech 0:5868e8752d44 783 return;
pythontech 0:5868e8752d44 784
pythontech 0:5868e8752d44 785 too_short:
pythontech 0:5868e8752d44 786 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 787 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
pythontech 0:5868e8752d44 788 "wrong number of values to unpack"));
pythontech 0:5868e8752d44 789 } else {
pythontech 0:5868e8752d44 790 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
pythontech 0:5868e8752d44 791 "need more than %d values to unpack", (int)seq_len));
pythontech 0:5868e8752d44 792 }
pythontech 0:5868e8752d44 793 too_long:
pythontech 0:5868e8752d44 794 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 795 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
pythontech 0:5868e8752d44 796 "wrong number of values to unpack"));
pythontech 0:5868e8752d44 797 } else {
pythontech 0:5868e8752d44 798 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
pythontech 0:5868e8752d44 799 "too many values to unpack (expected %d)", (int)num));
pythontech 0:5868e8752d44 800 }
pythontech 0:5868e8752d44 801 }
pythontech 0:5868e8752d44 802
pythontech 0:5868e8752d44 803 // unpacked items are stored in reverse order into the array pointed to by items
pythontech 0:5868e8752d44 804 void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) {
pythontech 0:5868e8752d44 805 mp_uint_t num_left = num_in & 0xff;
pythontech 0:5868e8752d44 806 mp_uint_t num_right = (num_in >> 8) & 0xff;
pythontech 0:5868e8752d44 807 DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right);
pythontech 0:5868e8752d44 808 mp_uint_t seq_len;
pythontech 0:5868e8752d44 809 if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
pythontech 0:5868e8752d44 810 mp_obj_t *seq_items;
pythontech 0:5868e8752d44 811 if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) {
pythontech 0:5868e8752d44 812 mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
pythontech 0:5868e8752d44 813 } else {
pythontech 0:5868e8752d44 814 if (num_left == 0 && num_right == 0) {
pythontech 0:5868e8752d44 815 // *a, = b # sets a to b if b is a list
pythontech 0:5868e8752d44 816 items[0] = seq_in;
pythontech 0:5868e8752d44 817 return;
pythontech 0:5868e8752d44 818 }
pythontech 0:5868e8752d44 819 mp_obj_list_get(seq_in, &seq_len, &seq_items);
pythontech 0:5868e8752d44 820 }
pythontech 0:5868e8752d44 821 if (seq_len < num_left + num_right) {
pythontech 0:5868e8752d44 822 goto too_short;
pythontech 0:5868e8752d44 823 }
pythontech 0:5868e8752d44 824 for (mp_uint_t i = 0; i < num_right; i++) {
pythontech 0:5868e8752d44 825 items[i] = seq_items[seq_len - 1 - i];
pythontech 0:5868e8752d44 826 }
pythontech 0:5868e8752d44 827 items[num_right] = mp_obj_new_list(seq_len - num_left - num_right, seq_items + num_left);
pythontech 0:5868e8752d44 828 for (mp_uint_t i = 0; i < num_left; i++) {
pythontech 0:5868e8752d44 829 items[num_right + 1 + i] = seq_items[num_left - 1 - i];
pythontech 0:5868e8752d44 830 }
pythontech 0:5868e8752d44 831 } else {
pythontech 0:5868e8752d44 832 // Generic iterable; this gets a bit messy: we unpack known left length to the
pythontech 0:5868e8752d44 833 // items destination array, then the rest to a dynamically created list. Once the
pythontech 0:5868e8752d44 834 // iterable is exhausted, we take from this list for the right part of the items.
pythontech 0:5868e8752d44 835 // TODO Improve to waste less memory in the dynamically created list.
pythontech 0:5868e8752d44 836 mp_obj_t iterable = mp_getiter(seq_in);
pythontech 0:5868e8752d44 837 mp_obj_t item;
pythontech 0:5868e8752d44 838 for (seq_len = 0; seq_len < num_left; seq_len++) {
pythontech 0:5868e8752d44 839 item = mp_iternext(iterable);
pythontech 0:5868e8752d44 840 if (item == MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 841 goto too_short;
pythontech 0:5868e8752d44 842 }
pythontech 0:5868e8752d44 843 items[num_left + num_right + 1 - 1 - seq_len] = item;
pythontech 0:5868e8752d44 844 }
pythontech 0:5868e8752d44 845 mp_obj_list_t *rest = MP_OBJ_TO_PTR(mp_obj_new_list(0, NULL));
pythontech 0:5868e8752d44 846 while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 847 mp_obj_list_append(MP_OBJ_FROM_PTR(rest), item);
pythontech 0:5868e8752d44 848 }
pythontech 0:5868e8752d44 849 if (rest->len < num_right) {
pythontech 0:5868e8752d44 850 goto too_short;
pythontech 0:5868e8752d44 851 }
pythontech 0:5868e8752d44 852 items[num_right] = MP_OBJ_FROM_PTR(rest);
pythontech 0:5868e8752d44 853 for (mp_uint_t i = 0; i < num_right; i++) {
pythontech 0:5868e8752d44 854 items[num_right - 1 - i] = rest->items[rest->len - num_right + i];
pythontech 0:5868e8752d44 855 }
pythontech 0:5868e8752d44 856 mp_obj_list_set_len(MP_OBJ_FROM_PTR(rest), rest->len - num_right);
pythontech 0:5868e8752d44 857 }
pythontech 0:5868e8752d44 858 return;
pythontech 0:5868e8752d44 859
pythontech 0:5868e8752d44 860 too_short:
pythontech 0:5868e8752d44 861 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 862 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
pythontech 0:5868e8752d44 863 "wrong number of values to unpack"));
pythontech 0:5868e8752d44 864 } else {
pythontech 0:5868e8752d44 865 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
pythontech 0:5868e8752d44 866 "need more than %d values to unpack", (int)seq_len));
pythontech 0:5868e8752d44 867 }
pythontech 0:5868e8752d44 868 }
pythontech 0:5868e8752d44 869
pythontech 0:5868e8752d44 870 mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
pythontech 0:5868e8752d44 871 DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
pythontech 0:5868e8752d44 872 // use load_method
pythontech 0:5868e8752d44 873 mp_obj_t dest[2];
pythontech 0:5868e8752d44 874 mp_load_method(base, attr, dest);
pythontech 0:5868e8752d44 875 if (dest[1] == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 876 // load_method returned just a normal attribute
pythontech 0:5868e8752d44 877 return dest[0];
pythontech 0:5868e8752d44 878 } else {
pythontech 0:5868e8752d44 879 // load_method returned a method, so build a bound method object
pythontech 0:5868e8752d44 880 return mp_obj_new_bound_meth(dest[0], dest[1]);
pythontech 0:5868e8752d44 881 }
pythontech 0:5868e8752d44 882 }
pythontech 0:5868e8752d44 883
pythontech 0:5868e8752d44 884 #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
pythontech 0:5868e8752d44 885
pythontech 0:5868e8752d44 886 // The following "checked fun" type is local to the mp_convert_member_lookup
pythontech 0:5868e8752d44 887 // function, and serves to check that the first argument to a builtin function
pythontech 0:5868e8752d44 888 // has the correct type.
pythontech 0:5868e8752d44 889
pythontech 0:5868e8752d44 890 typedef struct _mp_obj_checked_fun_t {
pythontech 0:5868e8752d44 891 mp_obj_base_t base;
pythontech 0:5868e8752d44 892 const mp_obj_type_t *type;
pythontech 0:5868e8752d44 893 mp_obj_t fun;
pythontech 0:5868e8752d44 894 } mp_obj_checked_fun_t;
pythontech 0:5868e8752d44 895
pythontech 0:5868e8752d44 896 STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
pythontech 0:5868e8752d44 897 mp_obj_checked_fun_t *self = MP_OBJ_TO_PTR(self_in);
pythontech 0:5868e8752d44 898 if (n_args > 0) {
pythontech 0:5868e8752d44 899 const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]);
pythontech 0:5868e8752d44 900 if (arg0_type != self->type) {
pythontech 0:5868e8752d44 901 if (MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED) {
pythontech 0:5868e8752d44 902 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
pythontech 0:5868e8752d44 903 "argument has wrong type"));
pythontech 0:5868e8752d44 904 } else {
pythontech 0:5868e8752d44 905 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
pythontech 0:5868e8752d44 906 "argument should be a '%q' not a '%q'", self->type->name, arg0_type->name));
pythontech 0:5868e8752d44 907 }
pythontech 0:5868e8752d44 908 }
pythontech 0:5868e8752d44 909 }
pythontech 0:5868e8752d44 910 return mp_call_function_n_kw(self->fun, n_args, n_kw, args);
pythontech 0:5868e8752d44 911 }
pythontech 0:5868e8752d44 912
pythontech 0:5868e8752d44 913 STATIC const mp_obj_type_t mp_type_checked_fun = {
pythontech 0:5868e8752d44 914 { &mp_type_type },
pythontech 0:5868e8752d44 915 .name = MP_QSTR_function,
pythontech 0:5868e8752d44 916 .call = checked_fun_call,
pythontech 0:5868e8752d44 917 };
pythontech 0:5868e8752d44 918
pythontech 0:5868e8752d44 919 STATIC mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun) {
pythontech 0:5868e8752d44 920 mp_obj_checked_fun_t *o = m_new_obj(mp_obj_checked_fun_t);
pythontech 0:5868e8752d44 921 o->base.type = &mp_type_checked_fun;
pythontech 0:5868e8752d44 922 o->type = type;
pythontech 0:5868e8752d44 923 o->fun = fun;
pythontech 0:5868e8752d44 924 return MP_OBJ_FROM_PTR(o);
pythontech 0:5868e8752d44 925 }
pythontech 0:5868e8752d44 926
pythontech 0:5868e8752d44 927 #endif // MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
pythontech 0:5868e8752d44 928
pythontech 0:5868e8752d44 929 // Given a member that was extracted from an instance, convert it correctly
pythontech 0:5868e8752d44 930 // and put the result in the dest[] array for a possible method call.
pythontech 0:5868e8752d44 931 // Conversion means dealing with static/class methods, callables, and values.
pythontech 0:5868e8752d44 932 // see http://docs.python.org/3/howto/descriptor.html
pythontech 0:5868e8752d44 933 void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest) {
pythontech 0:5868e8752d44 934 if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
pythontech 0:5868e8752d44 935 // return just the function
pythontech 0:5868e8752d44 936 dest[0] = ((mp_obj_static_class_method_t*)MP_OBJ_TO_PTR(member))->fun;
pythontech 0:5868e8752d44 937 } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
pythontech 0:5868e8752d44 938 // return a bound method, with self being the type of this object
pythontech 0:5868e8752d44 939 // this type should be the type of the original instance, not the base
pythontech 0:5868e8752d44 940 // type (which is what is passed in the 'type' argument to this function)
pythontech 0:5868e8752d44 941 if (self != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 942 type = mp_obj_get_type(self);
pythontech 0:5868e8752d44 943 }
pythontech 0:5868e8752d44 944 dest[0] = ((mp_obj_static_class_method_t*)MP_OBJ_TO_PTR(member))->fun;
pythontech 0:5868e8752d44 945 dest[1] = MP_OBJ_FROM_PTR(type);
pythontech 0:5868e8752d44 946 } else if (MP_OBJ_IS_TYPE(member, &mp_type_type)) {
pythontech 0:5868e8752d44 947 // Don't try to bind types (even though they're callable)
pythontech 0:5868e8752d44 948 dest[0] = member;
pythontech 0:5868e8752d44 949 } else if (MP_OBJ_IS_FUN(member)
pythontech 0:5868e8752d44 950 || (MP_OBJ_IS_OBJ(member)
pythontech 0:5868e8752d44 951 && (((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type->name == MP_QSTR_closure
pythontech 0:5868e8752d44 952 || ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type->name == MP_QSTR_generator))) {
pythontech 0:5868e8752d44 953 // only functions, closures and generators objects can be bound to self
pythontech 0:5868e8752d44 954 #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
pythontech 0:5868e8752d44 955 if (self == MP_OBJ_NULL && mp_obj_get_type(member) == &mp_type_fun_builtin) {
pythontech 0:5868e8752d44 956 // we extracted a builtin method without a first argument, so we must
pythontech 0:5868e8752d44 957 // wrap this function in a type checker
pythontech 0:5868e8752d44 958 dest[0] = mp_obj_new_checked_fun(type, member);
pythontech 0:5868e8752d44 959 } else
pythontech 0:5868e8752d44 960 #endif
pythontech 0:5868e8752d44 961 {
pythontech 0:5868e8752d44 962 // return a bound method, with self being this object
pythontech 0:5868e8752d44 963 dest[0] = member;
pythontech 0:5868e8752d44 964 dest[1] = self;
pythontech 0:5868e8752d44 965 }
pythontech 0:5868e8752d44 966 } else {
pythontech 0:5868e8752d44 967 // class member is a value, so just return that value
pythontech 0:5868e8752d44 968 dest[0] = member;
pythontech 0:5868e8752d44 969 }
pythontech 0:5868e8752d44 970 }
pythontech 0:5868e8752d44 971
pythontech 0:5868e8752d44 972 // no attribute found, returns: dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL
pythontech 0:5868e8752d44 973 // normal attribute found, returns: dest[0] == <attribute>, dest[1] == MP_OBJ_NULL
pythontech 0:5868e8752d44 974 // method attribute found, returns: dest[0] == <method>, dest[1] == <self>
pythontech 0:5868e8752d44 975 void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) {
pythontech 0:5868e8752d44 976 // clear output to indicate no attribute/method found yet
pythontech 0:5868e8752d44 977 dest[0] = MP_OBJ_NULL;
pythontech 0:5868e8752d44 978 dest[1] = MP_OBJ_NULL;
pythontech 0:5868e8752d44 979
pythontech 0:5868e8752d44 980 // get the type
pythontech 0:5868e8752d44 981 mp_obj_type_t *type = mp_obj_get_type(obj);
pythontech 0:5868e8752d44 982
pythontech 0:5868e8752d44 983 // look for built-in names
pythontech 0:5868e8752d44 984 if (0) {
pythontech 0:5868e8752d44 985 #if MICROPY_CPYTHON_COMPAT
pythontech 0:5868e8752d44 986 } else if (attr == MP_QSTR___class__) {
pythontech 0:5868e8752d44 987 // a.__class__ is equivalent to type(a)
pythontech 0:5868e8752d44 988 dest[0] = MP_OBJ_FROM_PTR(type);
pythontech 0:5868e8752d44 989 #endif
pythontech 0:5868e8752d44 990
pythontech 0:5868e8752d44 991 } else if (attr == MP_QSTR___next__ && type->iternext != NULL) {
pythontech 0:5868e8752d44 992 dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj);
pythontech 0:5868e8752d44 993 dest[1] = obj;
pythontech 0:5868e8752d44 994
pythontech 0:5868e8752d44 995 } else if (type->attr != NULL) {
pythontech 0:5868e8752d44 996 // this type can do its own load, so call it
pythontech 0:5868e8752d44 997 type->attr(obj, attr, dest);
pythontech 0:5868e8752d44 998
pythontech 0:5868e8752d44 999 } else if (type->locals_dict != NULL) {
pythontech 0:5868e8752d44 1000 // generic method lookup
pythontech 0:5868e8752d44 1001 // this is a lookup in the object (ie not class or type)
pythontech 0:5868e8752d44 1002 assert(type->locals_dict->base.type == &mp_type_dict); // Micro Python restriction, for now
pythontech 0:5868e8752d44 1003 mp_map_t *locals_map = &type->locals_dict->map;
pythontech 0:5868e8752d44 1004 mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
pythontech 0:5868e8752d44 1005 if (elem != NULL) {
pythontech 0:5868e8752d44 1006 mp_convert_member_lookup(obj, type, elem->value, dest);
pythontech 0:5868e8752d44 1007 }
pythontech 0:5868e8752d44 1008 }
pythontech 0:5868e8752d44 1009 }
pythontech 0:5868e8752d44 1010
pythontech 0:5868e8752d44 1011 void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
pythontech 0:5868e8752d44 1012 DEBUG_OP_printf("load method %p.%s\n", base, qstr_str(attr));
pythontech 0:5868e8752d44 1013
pythontech 0:5868e8752d44 1014 mp_load_method_maybe(base, attr, dest);
pythontech 0:5868e8752d44 1015
pythontech 0:5868e8752d44 1016 if (dest[0] == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1017 // no attribute/method called attr
pythontech 0:5868e8752d44 1018 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 1019 nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError,
pythontech 0:5868e8752d44 1020 "no such attribute"));
pythontech 0:5868e8752d44 1021 } else {
pythontech 0:5868e8752d44 1022 // following CPython, we give a more detailed error message for type objects
pythontech 0:5868e8752d44 1023 if (MP_OBJ_IS_TYPE(base, &mp_type_type)) {
pythontech 0:5868e8752d44 1024 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
pythontech 0:5868e8752d44 1025 "type object '%q' has no attribute '%q'",
pythontech 0:5868e8752d44 1026 ((mp_obj_type_t*)MP_OBJ_TO_PTR(base))->name, attr));
pythontech 0:5868e8752d44 1027 } else {
pythontech 0:5868e8752d44 1028 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
pythontech 0:5868e8752d44 1029 "'%s' object has no attribute '%q'",
pythontech 0:5868e8752d44 1030 mp_obj_get_type_str(base), attr));
pythontech 0:5868e8752d44 1031 }
pythontech 0:5868e8752d44 1032 }
pythontech 0:5868e8752d44 1033 }
pythontech 0:5868e8752d44 1034 }
pythontech 0:5868e8752d44 1035
pythontech 0:5868e8752d44 1036 void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
pythontech 0:5868e8752d44 1037 DEBUG_OP_printf("store attr %p.%s <- %p\n", base, qstr_str(attr), value);
pythontech 0:5868e8752d44 1038 mp_obj_type_t *type = mp_obj_get_type(base);
pythontech 0:5868e8752d44 1039 if (type->attr != NULL) {
pythontech 0:5868e8752d44 1040 mp_obj_t dest[2] = {MP_OBJ_SENTINEL, value};
pythontech 0:5868e8752d44 1041 type->attr(base, attr, dest);
pythontech 0:5868e8752d44 1042 if (dest[0] == MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1043 // success
pythontech 0:5868e8752d44 1044 return;
pythontech 0:5868e8752d44 1045 }
pythontech 0:5868e8752d44 1046 }
pythontech 0:5868e8752d44 1047 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 1048 nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError,
pythontech 0:5868e8752d44 1049 "no such attribute"));
pythontech 0:5868e8752d44 1050 } else {
pythontech 0:5868e8752d44 1051 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
pythontech 0:5868e8752d44 1052 "'%s' object has no attribute '%q'",
pythontech 0:5868e8752d44 1053 mp_obj_get_type_str(base), attr));
pythontech 0:5868e8752d44 1054 }
pythontech 0:5868e8752d44 1055 }
pythontech 0:5868e8752d44 1056
pythontech 0:5868e8752d44 1057 mp_obj_t mp_getiter(mp_obj_t o_in) {
pythontech 0:5868e8752d44 1058 assert(o_in);
pythontech 0:5868e8752d44 1059
pythontech 0:5868e8752d44 1060 // check for native getiter (corresponds to __iter__)
pythontech 0:5868e8752d44 1061 mp_obj_type_t *type = mp_obj_get_type(o_in);
pythontech 0:5868e8752d44 1062 if (type->getiter != NULL) {
pythontech 0:5868e8752d44 1063 mp_obj_t iter = type->getiter(o_in);
pythontech 0:5868e8752d44 1064 if (iter != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1065 return iter;
pythontech 0:5868e8752d44 1066 }
pythontech 0:5868e8752d44 1067 }
pythontech 0:5868e8752d44 1068
pythontech 0:5868e8752d44 1069 // check for __getitem__
pythontech 0:5868e8752d44 1070 mp_obj_t dest[2];
pythontech 0:5868e8752d44 1071 mp_load_method_maybe(o_in, MP_QSTR___getitem__, dest);
pythontech 0:5868e8752d44 1072 if (dest[0] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1073 // __getitem__ exists, create and return an iterator
pythontech 0:5868e8752d44 1074 return mp_obj_new_getitem_iter(dest);
pythontech 0:5868e8752d44 1075 }
pythontech 0:5868e8752d44 1076
pythontech 0:5868e8752d44 1077 // object not iterable
pythontech 0:5868e8752d44 1078 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 1079 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
pythontech 0:5868e8752d44 1080 "object not iterable"));
pythontech 0:5868e8752d44 1081 } else {
pythontech 0:5868e8752d44 1082 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
pythontech 0:5868e8752d44 1083 "'%s' object is not iterable", mp_obj_get_type_str(o_in)));
pythontech 0:5868e8752d44 1084 }
pythontech 0:5868e8752d44 1085 }
pythontech 0:5868e8752d44 1086
pythontech 0:5868e8752d44 1087 // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raise StopIteration()
pythontech 0:5868e8752d44 1088 // may also raise StopIteration()
pythontech 0:5868e8752d44 1089 mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) {
pythontech 0:5868e8752d44 1090 mp_obj_type_t *type = mp_obj_get_type(o_in);
pythontech 0:5868e8752d44 1091 if (type->iternext != NULL) {
pythontech 0:5868e8752d44 1092 return type->iternext(o_in);
pythontech 0:5868e8752d44 1093 } else {
pythontech 0:5868e8752d44 1094 // check for __next__ method
pythontech 0:5868e8752d44 1095 mp_obj_t dest[2];
pythontech 0:5868e8752d44 1096 mp_load_method_maybe(o_in, MP_QSTR___next__, dest);
pythontech 0:5868e8752d44 1097 if (dest[0] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1098 // __next__ exists, call it and return its result
pythontech 0:5868e8752d44 1099 return mp_call_method_n_kw(0, 0, dest);
pythontech 0:5868e8752d44 1100 } else {
pythontech 0:5868e8752d44 1101 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 1102 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
pythontech 0:5868e8752d44 1103 "object not an iterator"));
pythontech 0:5868e8752d44 1104 } else {
pythontech 0:5868e8752d44 1105 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
pythontech 0:5868e8752d44 1106 "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
pythontech 0:5868e8752d44 1107 }
pythontech 0:5868e8752d44 1108 }
pythontech 0:5868e8752d44 1109 }
pythontech 0:5868e8752d44 1110 }
pythontech 0:5868e8752d44 1111
pythontech 0:5868e8752d44 1112 // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration() (or any subclass thereof)
pythontech 0:5868e8752d44 1113 // may raise other exceptions
pythontech 0:5868e8752d44 1114 mp_obj_t mp_iternext(mp_obj_t o_in) {
pythontech 0:5868e8752d44 1115 MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext
pythontech 0:5868e8752d44 1116 mp_obj_type_t *type = mp_obj_get_type(o_in);
pythontech 0:5868e8752d44 1117 if (type->iternext != NULL) {
pythontech 0:5868e8752d44 1118 return type->iternext(o_in);
pythontech 0:5868e8752d44 1119 } else {
pythontech 0:5868e8752d44 1120 // check for __next__ method
pythontech 0:5868e8752d44 1121 mp_obj_t dest[2];
pythontech 0:5868e8752d44 1122 mp_load_method_maybe(o_in, MP_QSTR___next__, dest);
pythontech 0:5868e8752d44 1123 if (dest[0] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1124 // __next__ exists, call it and return its result
pythontech 0:5868e8752d44 1125 nlr_buf_t nlr;
pythontech 0:5868e8752d44 1126 if (nlr_push(&nlr) == 0) {
pythontech 0:5868e8752d44 1127 mp_obj_t ret = mp_call_method_n_kw(0, 0, dest);
pythontech 0:5868e8752d44 1128 nlr_pop();
pythontech 0:5868e8752d44 1129 return ret;
pythontech 0:5868e8752d44 1130 } else {
pythontech 0:5868e8752d44 1131 if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
pythontech 0:5868e8752d44 1132 return MP_OBJ_STOP_ITERATION;
pythontech 0:5868e8752d44 1133 } else {
pythontech 0:5868e8752d44 1134 nlr_jump(nlr.ret_val);
pythontech 0:5868e8752d44 1135 }
pythontech 0:5868e8752d44 1136 }
pythontech 0:5868e8752d44 1137 } else {
pythontech 0:5868e8752d44 1138 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
pythontech 0:5868e8752d44 1139 nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
pythontech 0:5868e8752d44 1140 "object not an iterator"));
pythontech 0:5868e8752d44 1141 } else {
pythontech 0:5868e8752d44 1142 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
pythontech 0:5868e8752d44 1143 "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
pythontech 0:5868e8752d44 1144 }
pythontech 0:5868e8752d44 1145 }
pythontech 0:5868e8752d44 1146 }
pythontech 0:5868e8752d44 1147 }
pythontech 0:5868e8752d44 1148
pythontech 0:5868e8752d44 1149 // TODO: Unclear what to do with StopIterarion exception here.
pythontech 0:5868e8752d44 1150 mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
pythontech 0:5868e8752d44 1151 assert((send_value != MP_OBJ_NULL) ^ (throw_value != MP_OBJ_NULL));
pythontech 0:5868e8752d44 1152 mp_obj_type_t *type = mp_obj_get_type(self_in);
pythontech 0:5868e8752d44 1153
pythontech 0:5868e8752d44 1154 if (type == &mp_type_gen_instance) {
pythontech 0:5868e8752d44 1155 return mp_obj_gen_resume(self_in, send_value, throw_value, ret_val);
pythontech 0:5868e8752d44 1156 }
pythontech 0:5868e8752d44 1157
pythontech 0:5868e8752d44 1158 if (type->iternext != NULL && send_value == mp_const_none) {
pythontech 0:5868e8752d44 1159 mp_obj_t ret = type->iternext(self_in);
pythontech 0:5868e8752d44 1160 if (ret != MP_OBJ_STOP_ITERATION) {
pythontech 0:5868e8752d44 1161 *ret_val = ret;
pythontech 0:5868e8752d44 1162 return MP_VM_RETURN_YIELD;
pythontech 0:5868e8752d44 1163 } else {
pythontech 0:5868e8752d44 1164 // Emulate raise StopIteration()
pythontech 0:5868e8752d44 1165 // Special case, handled in vm.c
pythontech 0:5868e8752d44 1166 *ret_val = MP_OBJ_NULL;
pythontech 0:5868e8752d44 1167 return MP_VM_RETURN_NORMAL;
pythontech 0:5868e8752d44 1168 }
pythontech 0:5868e8752d44 1169 }
pythontech 0:5868e8752d44 1170
pythontech 0:5868e8752d44 1171 mp_obj_t dest[3]; // Reserve slot for send() arg
pythontech 0:5868e8752d44 1172
pythontech 0:5868e8752d44 1173 if (send_value == mp_const_none) {
pythontech 0:5868e8752d44 1174 mp_load_method_maybe(self_in, MP_QSTR___next__, dest);
pythontech 0:5868e8752d44 1175 if (dest[0] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1176 *ret_val = mp_call_method_n_kw(0, 0, dest);
pythontech 0:5868e8752d44 1177 return MP_VM_RETURN_YIELD;
pythontech 0:5868e8752d44 1178 }
pythontech 0:5868e8752d44 1179 }
pythontech 0:5868e8752d44 1180
pythontech 0:5868e8752d44 1181 if (send_value != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1182 mp_load_method(self_in, MP_QSTR_send, dest);
pythontech 0:5868e8752d44 1183 dest[2] = send_value;
pythontech 0:5868e8752d44 1184 *ret_val = mp_call_method_n_kw(1, 0, dest);
pythontech 0:5868e8752d44 1185 return MP_VM_RETURN_YIELD;
pythontech 0:5868e8752d44 1186 }
pythontech 0:5868e8752d44 1187
pythontech 0:5868e8752d44 1188 if (throw_value != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1189 if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(throw_value)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) {
pythontech 0:5868e8752d44 1190 mp_load_method_maybe(self_in, MP_QSTR_close, dest);
pythontech 0:5868e8752d44 1191 if (dest[0] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1192 // TODO: Exceptions raised in close() are not propagated,
pythontech 0:5868e8752d44 1193 // printed to sys.stderr
pythontech 0:5868e8752d44 1194 *ret_val = mp_call_method_n_kw(0, 0, dest);
pythontech 0:5868e8752d44 1195 // We assume one can't "yield" from close()
pythontech 0:5868e8752d44 1196 return MP_VM_RETURN_NORMAL;
pythontech 0:5868e8752d44 1197 }
pythontech 0:5868e8752d44 1198 }
pythontech 0:5868e8752d44 1199 mp_load_method_maybe(self_in, MP_QSTR_throw, dest);
pythontech 0:5868e8752d44 1200 if (dest[0] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1201 *ret_val = mp_call_method_n_kw(1, 0, &throw_value);
pythontech 0:5868e8752d44 1202 // If .throw() method returned, we assume it's value to yield
pythontech 0:5868e8752d44 1203 // - any exception would be thrown with nlr_raise().
pythontech 0:5868e8752d44 1204 return MP_VM_RETURN_YIELD;
pythontech 0:5868e8752d44 1205 }
pythontech 0:5868e8752d44 1206 // If there's nowhere to throw exception into, then we assume that object
pythontech 0:5868e8752d44 1207 // is just incapable to handle it, so any exception thrown into it
pythontech 0:5868e8752d44 1208 // will be propagated up. This behavior is approved by test_pep380.py
pythontech 0:5868e8752d44 1209 // test_delegation_of_close_to_non_generator(),
pythontech 0:5868e8752d44 1210 // test_delegating_throw_to_non_generator()
pythontech 0:5868e8752d44 1211 *ret_val = throw_value;
pythontech 0:5868e8752d44 1212 return MP_VM_RETURN_EXCEPTION;
pythontech 0:5868e8752d44 1213 }
pythontech 0:5868e8752d44 1214
pythontech 0:5868e8752d44 1215 assert(0);
pythontech 0:5868e8752d44 1216 return MP_VM_RETURN_NORMAL; // Should be unreachable
pythontech 0:5868e8752d44 1217 }
pythontech 0:5868e8752d44 1218
pythontech 0:5868e8752d44 1219 mp_obj_t mp_make_raise_obj(mp_obj_t o) {
pythontech 0:5868e8752d44 1220 DEBUG_printf("raise %p\n", o);
pythontech 0:5868e8752d44 1221 if (mp_obj_is_exception_type(o)) {
pythontech 0:5868e8752d44 1222 // o is an exception type (it is derived from BaseException (or is BaseException))
pythontech 0:5868e8752d44 1223 // create and return a new exception instance by calling o
pythontech 0:5868e8752d44 1224 // TODO could have an option to disable traceback, then builtin exceptions (eg TypeError)
pythontech 0:5868e8752d44 1225 // could have const instances in ROM which we return here instead
pythontech 0:5868e8752d44 1226 return mp_call_function_n_kw(o, 0, 0, NULL);
pythontech 0:5868e8752d44 1227 } else if (mp_obj_is_exception_instance(o)) {
pythontech 0:5868e8752d44 1228 // o is an instance of an exception, so use it as the exception
pythontech 0:5868e8752d44 1229 return o;
pythontech 0:5868e8752d44 1230 } else {
pythontech 0:5868e8752d44 1231 // o cannot be used as an exception, so return a type error (which will be raised by the caller)
pythontech 0:5868e8752d44 1232 return mp_obj_new_exception_msg(&mp_type_TypeError, "exceptions must derive from BaseException");
pythontech 0:5868e8752d44 1233 }
pythontech 0:5868e8752d44 1234 }
pythontech 0:5868e8752d44 1235
pythontech 0:5868e8752d44 1236 mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) {
pythontech 0:5868e8752d44 1237 DEBUG_printf("import name '%s' level=%d\n", qstr_str(name), MP_OBJ_SMALL_INT_VALUE(level));
pythontech 0:5868e8752d44 1238
pythontech 0:5868e8752d44 1239 // build args array
pythontech 0:5868e8752d44 1240 mp_obj_t args[5];
pythontech 0:5868e8752d44 1241 args[0] = MP_OBJ_NEW_QSTR(name);
pythontech 0:5868e8752d44 1242 args[1] = mp_const_none; // TODO should be globals
pythontech 0:5868e8752d44 1243 args[2] = mp_const_none; // TODO should be locals
pythontech 0:5868e8752d44 1244 args[3] = fromlist;
pythontech 0:5868e8752d44 1245 args[4] = level; // must be 0; we don't yet support other values
pythontech 0:5868e8752d44 1246
pythontech 0:5868e8752d44 1247 // TODO lookup __import__ and call that instead of going straight to builtin implementation
pythontech 0:5868e8752d44 1248 return mp_builtin___import__(5, args);
pythontech 0:5868e8752d44 1249 }
pythontech 0:5868e8752d44 1250
pythontech 0:5868e8752d44 1251 mp_obj_t mp_import_from(mp_obj_t module, qstr name) {
pythontech 0:5868e8752d44 1252 DEBUG_printf("import from %p %s\n", module, qstr_str(name));
pythontech 0:5868e8752d44 1253
pythontech 0:5868e8752d44 1254 mp_obj_t dest[2];
pythontech 0:5868e8752d44 1255
pythontech 0:5868e8752d44 1256 mp_load_method_maybe(module, name, dest);
pythontech 0:5868e8752d44 1257
pythontech 0:5868e8752d44 1258 if (dest[1] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1259 // Hopefully we can't import bound method from an object
pythontech 0:5868e8752d44 1260 import_error:
pythontech 0:5868e8752d44 1261 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "cannot import name %q", name));
pythontech 0:5868e8752d44 1262 }
pythontech 0:5868e8752d44 1263
pythontech 0:5868e8752d44 1264 if (dest[0] != MP_OBJ_NULL) {
pythontech 0:5868e8752d44 1265 return dest[0];
pythontech 0:5868e8752d44 1266 }
pythontech 0:5868e8752d44 1267
pythontech 0:5868e8752d44 1268 // See if it's a package, then can try FS import
pythontech 0:5868e8752d44 1269 if (!mp_obj_is_package(module)) {
pythontech 0:5868e8752d44 1270 goto import_error;
pythontech 0:5868e8752d44 1271 }
pythontech 0:5868e8752d44 1272
pythontech 0:5868e8752d44 1273 mp_load_method_maybe(module, MP_QSTR___name__, dest);
pythontech 0:5868e8752d44 1274 mp_uint_t pkg_name_len;
pythontech 0:5868e8752d44 1275 const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len);
pythontech 0:5868e8752d44 1276
pythontech 0:5868e8752d44 1277 const uint dot_name_len = pkg_name_len + 1 + qstr_len(name);
pythontech 0:5868e8752d44 1278 char *dot_name = alloca(dot_name_len);
pythontech 0:5868e8752d44 1279 memcpy(dot_name, pkg_name, pkg_name_len);
pythontech 0:5868e8752d44 1280 dot_name[pkg_name_len] = '.';
pythontech 0:5868e8752d44 1281 memcpy(dot_name + pkg_name_len + 1, qstr_str(name), qstr_len(name));
pythontech 0:5868e8752d44 1282 qstr dot_name_q = qstr_from_strn(dot_name, dot_name_len);
pythontech 0:5868e8752d44 1283
pythontech 0:5868e8752d44 1284 mp_obj_t args[5];
pythontech 0:5868e8752d44 1285 args[0] = MP_OBJ_NEW_QSTR(dot_name_q);
pythontech 0:5868e8752d44 1286 args[1] = mp_const_none; // TODO should be globals
pythontech 0:5868e8752d44 1287 args[2] = mp_const_none; // TODO should be locals
pythontech 0:5868e8752d44 1288 args[3] = mp_const_true; // Pass sentinel "non empty" value to force returning of leaf module
pythontech 0:5868e8752d44 1289 args[4] = MP_OBJ_NEW_SMALL_INT(0);
pythontech 0:5868e8752d44 1290
pythontech 0:5868e8752d44 1291 // TODO lookup __import__ and call that instead of going straight to builtin implementation
pythontech 0:5868e8752d44 1292 return mp_builtin___import__(5, args);
pythontech 0:5868e8752d44 1293 }
pythontech 0:5868e8752d44 1294
pythontech 0:5868e8752d44 1295 void mp_import_all(mp_obj_t module) {
pythontech 0:5868e8752d44 1296 DEBUG_printf("import all %p\n", module);
pythontech 0:5868e8752d44 1297
pythontech 0:5868e8752d44 1298 // TODO: Support __all__
pythontech 0:5868e8752d44 1299 mp_map_t *map = mp_obj_dict_get_map(MP_OBJ_FROM_PTR(mp_obj_module_get_globals(module)));
pythontech 0:5868e8752d44 1300 for (mp_uint_t i = 0; i < map->alloc; i++) {
pythontech 0:5868e8752d44 1301 if (MP_MAP_SLOT_IS_FILLED(map, i)) {
pythontech 0:5868e8752d44 1302 qstr name = MP_OBJ_QSTR_VALUE(map->table[i].key);
pythontech 0:5868e8752d44 1303 if (*qstr_str(name) != '_') {
pythontech 0:5868e8752d44 1304 mp_store_name(name, map->table[i].value);
pythontech 0:5868e8752d44 1305 }
pythontech 0:5868e8752d44 1306 }
pythontech 0:5868e8752d44 1307 }
pythontech 0:5868e8752d44 1308 }
pythontech 0:5868e8752d44 1309
pythontech 0:5868e8752d44 1310 #if MICROPY_ENABLE_COMPILER
pythontech 0:5868e8752d44 1311
pythontech 0:5868e8752d44 1312 // this is implemented in this file so it can optimise access to locals/globals
pythontech 0:5868e8752d44 1313 mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_input_kind, mp_obj_dict_t *globals, mp_obj_dict_t *locals) {
pythontech 0:5868e8752d44 1314 // save context
pythontech 0:5868e8752d44 1315 mp_obj_dict_t *volatile old_globals = mp_globals_get();
pythontech 0:5868e8752d44 1316 mp_obj_dict_t *volatile old_locals = mp_locals_get();
pythontech 0:5868e8752d44 1317
pythontech 0:5868e8752d44 1318 // set new context
pythontech 0:5868e8752d44 1319 mp_globals_set(globals);
pythontech 0:5868e8752d44 1320 mp_locals_set(locals);
pythontech 0:5868e8752d44 1321
pythontech 0:5868e8752d44 1322 nlr_buf_t nlr;
pythontech 0:5868e8752d44 1323 if (nlr_push(&nlr) == 0) {
pythontech 0:5868e8752d44 1324 qstr source_name = lex->source_name;
pythontech 0:5868e8752d44 1325 mp_parse_tree_t parse_tree = mp_parse(lex, parse_input_kind);
pythontech 0:5868e8752d44 1326 mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false);
pythontech 0:5868e8752d44 1327
pythontech 0:5868e8752d44 1328 mp_obj_t ret;
pythontech 0:5868e8752d44 1329 if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) {
pythontech 0:5868e8752d44 1330 // for compile only, return value is the module function
pythontech 0:5868e8752d44 1331 ret = module_fun;
pythontech 0:5868e8752d44 1332 } else {
pythontech 0:5868e8752d44 1333 // execute module function and get return value
pythontech 0:5868e8752d44 1334 ret = mp_call_function_0(module_fun);
pythontech 0:5868e8752d44 1335 }
pythontech 0:5868e8752d44 1336
pythontech 0:5868e8752d44 1337 // finish nlr block, restore context and return value
pythontech 0:5868e8752d44 1338 nlr_pop();
pythontech 0:5868e8752d44 1339 mp_globals_set(old_globals);
pythontech 0:5868e8752d44 1340 mp_locals_set(old_locals);
pythontech 0:5868e8752d44 1341 return ret;
pythontech 0:5868e8752d44 1342 } else {
pythontech 0:5868e8752d44 1343 // exception; restore context and re-raise same exception
pythontech 0:5868e8752d44 1344 mp_globals_set(old_globals);
pythontech 0:5868e8752d44 1345 mp_locals_set(old_locals);
pythontech 0:5868e8752d44 1346 nlr_jump(nlr.ret_val);
pythontech 0:5868e8752d44 1347 }
pythontech 0:5868e8752d44 1348 }
pythontech 0:5868e8752d44 1349
pythontech 0:5868e8752d44 1350 #endif // MICROPY_ENABLE_COMPILER
pythontech 0:5868e8752d44 1351
pythontech 0:5868e8752d44 1352 void *m_malloc_fail(size_t num_bytes) {
pythontech 0:5868e8752d44 1353 DEBUG_printf("memory allocation failed, allocating %u bytes\n", (uint)num_bytes);
pythontech 0:5868e8752d44 1354 if (0) {
pythontech 0:5868e8752d44 1355 // dummy
pythontech 0:5868e8752d44 1356 #if MICROPY_ENABLE_GC
pythontech 0:5868e8752d44 1357 } else if (gc_is_locked()) {
pythontech 0:5868e8752d44 1358 nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError,
pythontech 0:5868e8752d44 1359 "memory allocation failed, heap is locked"));
pythontech 0:5868e8752d44 1360 #endif
pythontech 0:5868e8752d44 1361 } else {
pythontech 0:5868e8752d44 1362 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError,
pythontech 0:5868e8752d44 1363 "memory allocation failed, allocating %u bytes", (uint)num_bytes));
pythontech 0:5868e8752d44 1364 }
pythontech 0:5868e8752d44 1365 }
pythontech 0:5868e8752d44 1366
pythontech 0:5868e8752d44 1367 NORETURN void mp_not_implemented(const char *msg) {
pythontech 0:5868e8752d44 1368 nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, msg));
pythontech 0:5868e8752d44 1369 }