summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorGlenn Ruben Bakke <glennbakke@gmail.com>2017-10-04 21:45:04 +0200
committerGlenn Ruben Bakke <glennbakke@gmail.com>2017-10-04 21:45:04 +0200
commitbcab2ba0a80297100919366add6bada140c6ed75 (patch)
tree5133218f4fc010d5688f006dbdd1e2f346a843f7 /py
parent4468731e3d039a3f72ac25aa43e936cf5ebb3f78 (diff)
parentf869d6b2e339c04469c6c9ea3fb2fabd7bbb2d8c (diff)
ports/nrf: Upmerging port with upstream master
Diffstat (limited to 'py')
-rw-r--r--py/argcheck.c3
-rw-r--r--py/asmthumb.c3
-rw-r--r--py/bc.c6
-rw-r--r--py/bc.h1
-rw-r--r--py/bc0.h2
-rw-r--r--py/binary.c5
-rw-r--r--py/binary.h5
-rw-r--r--py/builtin.h2
-rw-r--r--py/builtinevex.c1
-rw-r--r--py/builtinhelp.c15
-rw-r--r--py/builtinimport.c3
-rw-r--r--py/compile.c7
-rw-r--r--py/emit.h1
-rw-r--r--py/emitbc.c2
-rw-r--r--py/emitglue.c2
-rw-r--r--py/emitnative.c11
-rw-r--r--py/formatfloat.c2
-rw-r--r--py/gc.c4
-rw-r--r--py/lexer.c3
-rw-r--r--py/malloc.c10
-rw-r--r--py/map.c19
-rw-r--r--py/misc.h2
-rw-r--r--py/mkenv.mk6
-rw-r--r--py/mkrules.mk10
-rw-r--r--py/modbuiltins.c23
-rw-r--r--py/modcmath.c32
-rw-r--r--py/modgc.c17
-rw-r--r--py/modmath.c86
-rw-r--r--py/modmicropython.c1
-rw-r--r--py/modstruct.c85
-rw-r--r--py/modsys.c28
-rw-r--r--py/modthread.c10
-rw-r--r--py/mpconfig.h32
-rw-r--r--py/mpprint.c15
-rw-r--r--py/nativeglue.c4
-rw-r--r--py/nlrthumb.c8
-rw-r--r--py/nlrx64.c7
-rw-r--r--py/nlrx86.c10
-rw-r--r--py/nlrxtensa.c1
-rw-r--r--py/obj.c42
-rw-r--r--py/obj.h14
-rw-r--r--py/objarray.c12
-rw-r--r--py/objbool.c6
-rw-r--r--py/objcomplex.c12
-rw-r--r--py/objdict.c15
-rw-r--r--py/objexcept.c244
-rw-r--r--py/objfloat.c29
-rw-r--r--py/objfun.c4
-rw-r--r--py/objgenerator.c2
-rw-r--r--py/objgetitemiter.c1
-rw-r--r--py/objint.c18
-rw-r--r--py/objint.h7
-rw-r--r--py/objint_longlong.c40
-rw-r--r--py/objint_mpz.c38
-rw-r--r--py/objlist.c42
-rw-r--r--py/objmodule.c2
-rw-r--r--py/objnamedtuple.c1
-rw-r--r--py/objnone.c2
-rw-r--r--py/objpolyiter.c1
-rw-r--r--py/objproperty.c1
-rw-r--r--py/objrange.c4
-rw-r--r--py/objreversed.c1
-rw-r--r--py/objset.c83
-rw-r--r--py/objsingleton.c2
-rw-r--r--py/objslice.c2
-rw-r--r--py/objstr.c44
-rw-r--r--py/objstr.h2
-rw-r--r--py/objstringio.c22
-rw-r--r--py/objstrunicode.c6
-rw-r--r--py/objtuple.c22
-rw-r--r--py/objtuple.h4
-rw-r--r--py/objtype.c78
-rw-r--r--py/parse.c2
-rw-r--r--py/persistentcode.c3
-rw-r--r--py/py.mk12
-rw-r--r--py/qstr.c2
-rw-r--r--py/qstrdefs.h8
-rw-r--r--py/runtime.c37
-rw-r--r--py/runtime.h15
-rw-r--r--py/runtime0.h95
-rw-r--r--py/runtime_utils.c2
-rw-r--r--py/sequence.c3
-rw-r--r--py/showbc.c2
-rw-r--r--py/stackctrl.c3
-rw-r--r--py/stream.c15
-rw-r--r--py/stream.h8
-rw-r--r--py/unicode.c28
-rw-r--r--py/unicode.h1
-rw-r--r--py/vm.c4
-rw-r--r--py/vmentrytable.h2
-rw-r--r--py/vstr.c59
-rw-r--r--py/warning.c6
92 files changed, 852 insertions, 742 deletions
diff --git a/py/argcheck.c b/py/argcheck.c
index 22fd9cd2c..add6f8de8 100644
--- a/py/argcheck.c
+++ b/py/argcheck.c
@@ -27,7 +27,6 @@
#include <stdlib.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/runtime.h"
void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) {
@@ -142,6 +141,6 @@ NORETURN void mp_arg_error_terse_mismatch(void) {
#if MICROPY_CPYTHON_COMPAT
NORETURN void mp_arg_error_unimpl_kw(void) {
- mp_not_implemented("keyword argument(s) not yet implemented - use normal args instead");
+ mp_raise_NotImplementedError("keyword argument(s) not yet implemented - use normal args instead");
}
#endif
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 4360a6af9..5316a7efb 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -33,6 +33,7 @@
// wrapper around everything in this file
#if MICROPY_EMIT_THUMB || MICROPY_EMIT_INLINE_THUMB
+#include "py/mphal.h"
#include "py/asmthumb.h"
#define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0)
@@ -53,7 +54,7 @@ void asm_thumb_end_pass(asm_thumb_t *as) {
#if defined(MCU_SERIES_F7)
if (as->base.pass == MP_ASM_PASS_EMIT) {
// flush D-cache, so the code emitted is stored in memory
- SCB_CleanDCache_by_Addr((uint32_t*)as->base.code_base, as->base.code_size);
+ MP_HAL_CLEAN_DCACHE(as->base.code_base, as->base.code_size);
// invalidate I-cache
SCB_InvalidateICache();
}
diff --git a/py/bc.c b/py/bc.c
index 522eb0aeb..991b0cf26 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -29,13 +29,11 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
-#include "py/objfun.h"
-#include "py/runtime0.h"
+#include "py/runtime.h"
#include "py/bc0.h"
#include "py/bc.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#else // don't print debugging info
#define DEBUG_PRINT (0)
diff --git a/py/bc.h b/py/bc.h
index 69e213e42..ebfdeaac1 100644
--- a/py/bc.h
+++ b/py/bc.h
@@ -27,7 +27,6 @@
#define MICROPY_INCLUDED_PY_BC_H
#include "py/runtime.h"
-#include "py/obj.h"
#include "py/objfun.h"
// bytecode layout:
diff --git a/py/bc0.h b/py/bc0.h
index f671c5b5a..38e23c0fd 100644
--- a/py/bc0.h
+++ b/py/bc0.h
@@ -113,7 +113,7 @@
#define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // + N(64)
#define MP_BC_LOAD_FAST_MULTI (0xb0) // + N(16)
#define MP_BC_STORE_FAST_MULTI (0xc0) // + N(16)
-#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(7)
+#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(<MP_UNARY_OP_NON_BYTECODE)
#define MP_BC_BINARY_OP_MULTI (0xd7) // + op(36)
#endif // MICROPY_INCLUDED_PY_BC0_H
diff --git a/py/binary.c b/py/binary.c
index e38aae8ea..870a0942b 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -303,7 +303,10 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
// zero/sign extend if needed
if (BYTES_PER_WORD < 8 && size > sizeof(val)) {
int c = (is_signed(val_type) && (mp_int_t)val < 0) ? 0xff : 0x00;
- memset(p + sizeof(val), c, size - sizeof(val));
+ memset(p, c, size);
+ if (struct_type == '>') {
+ p += size - sizeof(val);
+ }
}
}
}
diff --git a/py/binary.h b/py/binary.h
index 7b5c60f1a..0dae6a29e 100644
--- a/py/binary.h
+++ b/py/binary.h
@@ -29,8 +29,9 @@
#include "py/obj.h"
// Use special typecode to differentiate repr() of bytearray vs array.array('B')
-// (underlyingly they're same).
-#define BYTEARRAY_TYPECODE 0
+// (underlyingly they're same). Can't use 0 here because that's used to detect
+// type-specification errors due to end-of-string.
+#define BYTEARRAY_TYPECODE 1
size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign);
mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index);
diff --git a/py/builtin.h b/py/builtin.h
index a637b6e22..84b99a8a4 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -118,6 +118,6 @@ extern const mp_obj_module_t mp_module_webrepl;
extern const mp_obj_module_t mp_module_framebuf;
extern const mp_obj_module_t mp_module_btree;
-extern const char *MICROPY_PY_BUILTINS_HELP_TEXT;
+extern const char MICROPY_PY_BUILTINS_HELP_TEXT[];
#endif // MICROPY_INCLUDED_PY_BUILTIN_H
diff --git a/py/builtinevex.c b/py/builtinevex.c
index ba8048f70..846603f46 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -26,7 +26,6 @@
#include <stdint.h>
-#include "py/nlr.h"
#include "py/objfun.h"
#include "py/compile.h"
#include "py/runtime.h"
diff --git a/py/builtinhelp.c b/py/builtinhelp.c
index dbcd6e00f..c9992906d 100644
--- a/py/builtinhelp.c
+++ b/py/builtinhelp.c
@@ -32,7 +32,7 @@
#if MICROPY_PY_BUILTINS_HELP
-const char *mp_help_default_text =
+const char mp_help_default_text[] =
"Welcome to MicroPython!\n"
"\n"
"For online docs please visit http://docs.micropython.org/\n"
@@ -136,20 +136,19 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) {
}
#endif
+ mp_obj_type_t *type = mp_obj_get_type(obj);
+
// try to print something sensible about the given object
mp_print_str(MP_PYTHON_PRINTER, "object ");
mp_obj_print(obj, PRINT_STR);
- mp_printf(MP_PYTHON_PRINTER, " is of type %s\n", mp_obj_get_type_str(obj));
+ mp_printf(MP_PYTHON_PRINTER, " is of type %q\n", type->name);
mp_map_t *map = NULL;
- if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) {
+ if (type == &mp_type_module) {
map = mp_obj_dict_get_map(mp_obj_module_get_globals(obj));
} else {
- mp_obj_type_t *type;
- if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) {
- type = obj;
- } else {
- type = mp_obj_get_type(obj);
+ if (type == &mp_type_type) {
+ type = MP_OBJ_TO_PTR(obj);
}
if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
map = mp_obj_dict_get_map(type->locals_dict);
diff --git a/py/builtinimport.c b/py/builtinimport.c
index e0ce91d9b..04ce66723 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -29,7 +29,6 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/compile.h"
#include "py/objmodule.h"
#include "py/persistentcode.h"
@@ -37,7 +36,7 @@
#include "py/builtin.h"
#include "py/frozenmod.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
diff --git a/py/compile.c b/py/compile.c
index 00052e190..4e704abfb 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -613,13 +613,11 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
} else {
mp_parse_node_t pn_id;
- mp_parse_node_t pn_colon;
mp_parse_node_t pn_equal;
if (pn_kind == -1) {
// this parameter is just an id
pn_id = pn;
- pn_colon = MP_PARSE_NODE_NULL;
pn_equal = MP_PARSE_NODE_NULL;
} else if (pn_kind == PN_typedargslist_name) {
@@ -627,7 +625,7 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
pn_id = pns->nodes[0];
- pn_colon = pns->nodes[1];
+ //pn_colon = pns->nodes[1]; // unused
pn_equal = pns->nodes[2];
} else {
@@ -676,9 +674,6 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
compile_node(comp, pn_equal);
}
}
-
- // TODO pn_colon not implemented
- (void)pn_colon;
}
}
diff --git a/py/emit.h b/py/emit.h
index 2b2c904f6..270a40633 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -28,7 +28,6 @@
#include "py/lexer.h"
#include "py/scope.h"
-#include "py/runtime0.h"
/* Notes on passes:
* We don't know exactly the opcodes in pass 1 because they depend on the
diff --git a/py/emitbc.c b/py/emitbc.c
index 677020925..3f4dfc178 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -550,7 +550,7 @@ void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj) {
void mp_emit_bc_load_null(emit_t *emit) {
emit_bc_pre(emit, 1);
emit_write_bytecode_byte(emit, MP_BC_LOAD_NULL);
-};
+}
void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
(void)qst;
diff --git a/py/emitglue.c b/py/emitglue.c
index 383e6a136..d2add988f 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -35,7 +35,7 @@
#include "py/runtime0.h"
#include "py/bc.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#define WRITE_CODE (1)
#define DEBUG_printf DEBUG_printf
diff --git a/py/emitnative.c b/py/emitnative.c
index 5ed69ff9b..b2c9a7366 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -46,11 +46,10 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/emit.h"
#include "py/bc.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
@@ -824,7 +823,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de
break;
default:
// not handled
- mp_not_implemented("conversion to object");
+ mp_raise_NotImplementedError("conversion to object");
}
}
@@ -2158,7 +2157,7 @@ STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_u
break;
default:
// this can happen when casting a cast: int(int)
- mp_not_implemented("casting");
+ mp_raise_NotImplementedError("casting");
}
} else {
assert(vtype_fun == VTYPE_PYOBJ);
@@ -2232,12 +2231,12 @@ STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) {
STATIC void emit_native_yield_value(emit_t *emit) {
// not supported (for now)
(void)emit;
- mp_not_implemented("native yield");
+ mp_raise_NotImplementedError("native yield");
}
STATIC void emit_native_yield_from(emit_t *emit) {
// not supported (for now)
(void)emit;
- mp_not_implemented("native yield from");
+ mp_raise_NotImplementedError("native yield from");
}
STATIC void emit_native_start_except_handler(emit_t *emit) {
diff --git a/py/formatfloat.c b/py/formatfloat.c
index 4130e8b26..35cd5d51a 100644
--- a/py/formatfloat.c
+++ b/py/formatfloat.c
@@ -118,7 +118,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
*s++ = '?';
}
if (buf_size >= 1) {
- *s++ = '\0';
+ *s = '\0';
}
return buf_size >= 2;
}
diff --git a/py/gc.c b/py/gc.c
index 7253b7db6..9752b3532 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -28,14 +28,12 @@
#include <stdio.h>
#include <string.h>
-#include "py/mpstate.h"
#include "py/gc.h"
-#include "py/obj.h"
#include "py/runtime.h"
#if MICROPY_ENABLE_GC
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
diff --git a/py/lexer.c b/py/lexer.c
index 32b3567cc..6017d69d6 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -28,7 +28,6 @@
#include <string.h>
#include <assert.h>
-#include "py/mpstate.h"
#include "py/reader.h"
#include "py/lexer.h"
#include "py/runtime.h"
@@ -341,7 +340,7 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw) {
// 3MB of text; even gzip-compressed and with minimal structure, it'll take
// roughly half a meg of storage. This form of Unicode escape may be added
// later on, but it's definitely not a priority right now. -- CJA 20140607
- mp_not_implemented("unicode name escapes");
+ mp_raise_NotImplementedError("unicode name escapes");
break;
default:
if (c >= '0' && c <= '7') {
diff --git a/py/malloc.c b/py/malloc.c
index e679e2092..ea1d4c4b9 100644
--- a/py/malloc.c
+++ b/py/malloc.c
@@ -32,7 +32,7 @@
#include "py/misc.h"
#include "py/mpstate.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
@@ -74,7 +74,7 @@ STATIC void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) {
void *m_malloc(size_t num_bytes) {
void *ptr = malloc(num_bytes);
if (ptr == NULL && num_bytes != 0) {
- return m_malloc_fail(num_bytes);
+ m_malloc_fail(num_bytes);
}
#if MICROPY_MEM_STATS
MP_STATE_MEM(total_bytes_allocated) += num_bytes;
@@ -100,7 +100,7 @@ void *m_malloc_maybe(size_t num_bytes) {
void *m_malloc_with_finaliser(size_t num_bytes) {
void *ptr = malloc_with_finaliser(num_bytes);
if (ptr == NULL && num_bytes != 0) {
- return m_malloc_fail(num_bytes);
+ m_malloc_fail(num_bytes);
}
#if MICROPY_MEM_STATS
MP_STATE_MEM(total_bytes_allocated) += num_bytes;
@@ -115,7 +115,7 @@ void *m_malloc_with_finaliser(size_t num_bytes) {
void *m_malloc0(size_t num_bytes) {
void *ptr = m_malloc(num_bytes);
if (ptr == NULL && num_bytes != 0) {
- return m_malloc_fail(num_bytes);
+ m_malloc_fail(num_bytes);
}
// If this config is set then the GC clears all memory, so we don't need to.
#if !MICROPY_GC_CONSERVATIVE_CLEAR
@@ -131,7 +131,7 @@ void *m_realloc(void *ptr, size_t new_num_bytes) {
#endif
void *new_ptr = realloc(ptr, new_num_bytes);
if (new_ptr == NULL && new_num_bytes != 0) {
- return m_malloc_fail(new_num_bytes);
+ m_malloc_fail(new_num_bytes);
}
#if MICROPY_MEM_STATS
// At first thought, "Total bytes allocated" should only grow,
diff --git a/py/map.c b/py/map.c
index 7f3c90059..4f76b9b16 100644
--- a/py/map.c
+++ b/py/map.c
@@ -31,7 +31,6 @@
#include "py/mpconfig.h"
#include "py/misc.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
// Fixed empty map. Useful when need to call kw-receiving functions
@@ -93,12 +92,6 @@ void mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table) {
map->table = (mp_map_elem_t*)table;
}
-mp_map_t *mp_map_new(size_t n) {
- mp_map_t *map = m_new(mp_map_t, 1);
- mp_map_init(map, n);
- return map;
-}
-
// Differentiate from mp_map_clear() - semantics is different
void mp_map_deinit(mp_map_t *map) {
if (!map->is_fixed) {
@@ -107,11 +100,6 @@ void mp_map_deinit(mp_map_t *map) {
map->used = map->alloc = 0;
}
-void mp_map_free(mp_map_t *map) {
- mp_map_deinit(map);
- m_del_obj(mp_map_t, map);
-}
-
void mp_map_clear(mp_map_t *map) {
if (!map->is_fixed) {
m_del(mp_map_elem_t, map->table, map->alloc);
@@ -148,11 +136,8 @@ STATIC void mp_map_rehash(mp_map_t *map) {
// MP_MAP_LOOKUP_REMOVE_IF_FOUND behaviour:
// - returns NULL if not found, else the slot if was found in with key null and value non-null
mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) {
-
- if (map->is_fixed && lookup_kind != MP_MAP_LOOKUP) {
- // can't add/remove from a fixed array
- return NULL;
- }
+ // If the map is a fixed array then we must only be called for a lookup
+ assert(!map->is_fixed || lookup_kind == MP_MAP_LOOKUP);
// Work out if we can compare just pointers
bool compare_only_ptrs = map->all_keys_are_qstrs;
diff --git a/py/misc.h b/py/misc.h
index 71425b85e..b9f2dae90 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -92,7 +92,7 @@ void *m_realloc(void *ptr, size_t new_num_bytes);
void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move);
void m_free(void *ptr);
#endif
-NORETURN void *m_malloc_fail(size_t num_bytes);
+NORETURN void m_malloc_fail(size_t num_bytes);
#if MICROPY_MEM_STATS
size_t m_get_total_bytes_allocated(void);
diff --git a/py/mkenv.mk b/py/mkenv.mk
index b167b2533..8b637e9ac 100644
--- a/py/mkenv.mk
+++ b/py/mkenv.mk
@@ -59,7 +59,13 @@ LD += -m32
endif
MAKE_FROZEN = $(TOP)/tools/make-frozen.py
+# allow mpy-cross (for WSL) and mpy-cross.exe (for cygwin) to coexist
+ifeq ($(OS),Windows_NT)
+MPY_CROSS = $(TOP)/mpy-cross/mpy-cross.exe
+PROG_EXT = .exe
+else
MPY_CROSS = $(TOP)/mpy-cross/mpy-cross
+endif
MPY_TOOL = $(TOP)/tools/mpy-tool.py
all:
diff --git a/py/mkrules.mk b/py/mkrules.mk
index de2c92a3f..fd579557f 100644
--- a/py/mkrules.mk
+++ b/py/mkrules.mk
@@ -103,7 +103,7 @@ endif
ifneq ($(FROZEN_MPY_DIR),)
# to build the MicroPython cross compiler
-$(TOP)/mpy-cross/mpy-cross: $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/windows/fmode.c
+$(TOP)/mpy-cross/mpy-cross: $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/ports/windows/fmode.c
$(Q)$(MAKE) -C $(TOP)/mpy-cross
# make a list of all the .py files that need compiling and freezing
@@ -111,7 +111,7 @@ FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' |
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
# to build .mpy files from .py files
-$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py $(TOP)/mpy-cross/mpy-cross
+$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py $(MPY_CROSS)
@$(ECHO) "MPY $<"
$(Q)$(MKDIR) -p $(dir $@)
$(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $<
@@ -133,13 +133,13 @@ $(PROG): $(OBJ)
# we may want to compile using Thumb, but link with non-Thumb libc.
$(Q)$(CC) -o $@ $^ $(LIB) $(LDFLAGS)
ifndef DEBUG
- $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)
+ $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)$(PROG_EXT)
endif
- $(Q)$(SIZE) $$(find $(BUILD)/build -name "frozen*.o") $(PROG)
+ $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $(PROG)$(PROG_EXT)
clean: clean-prog
clean-prog:
- $(RM) -f $(PROG)
+ $(RM) -f $(PROG)$(PROG_EXT)
$(RM) -f $(PROG).map
.PHONY: clean-prog
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 1c76b8073..82b08cdc9 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -27,12 +27,10 @@
#include <stdio.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/smallint.h"
#include "py/objint.h"
#include "py/objstr.h"
#include "py/objtype.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/stream.h"
@@ -91,26 +89,7 @@ STATIC mp_obj_t mp_builtin___build_class__(size_t n_args, const mp_obj_t *args)
MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__);
STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
- #if MICROPY_PY_BUILTINS_FLOAT
- if (mp_obj_is_float(o_in)) {
- mp_float_t value = mp_obj_float_get(o_in);
- // TODO check for NaN etc
- if (value < 0) {
- return mp_obj_new_float(-value);
- } else {
- return o_in;
- }
- #if MICROPY_PY_BUILTINS_COMPLEX
- } else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) {
- mp_float_t real, imag;
- mp_obj_complex_get(o_in, &real, &imag);
- return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag));
- #endif
- }
- #endif
-
- // this will raise a TypeError if the argument is not integral
- return mp_obj_int_abs(o_in);
+ return mp_unary_op(MP_UNARY_OP_ABS, o_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);
diff --git a/py/modcmath.c b/py/modcmath.c
index 627a2cbad..70fd542af 100644
--- a/py/modcmath.c
+++ b/py/modcmath.c
@@ -30,13 +30,7 @@
#include <math.h>
-/// \module cmath - mathematical functions for complex numbers
-///
-/// The `cmath` module provides some basic mathematical funtions for
-/// working with complex numbers.
-
-/// \function phase(z)
-/// Returns the phase of the number `z`, in the range (-pi, +pi].
+// phase(z): returns the phase of the number z in the range (-pi, +pi]
STATIC mp_obj_t mp_cmath_phase(mp_obj_t z_obj) {
mp_float_t real, imag;
mp_obj_get_complex(z_obj, &real, &imag);
@@ -44,8 +38,7 @@ STATIC mp_obj_t mp_cmath_phase(mp_obj_t z_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase);
-/// \function polar(z)
-/// Returns, as a tuple, the polar form of `z`.
+// polar(z): returns the polar form of z as a tuple
STATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) {
mp_float_t real, imag;
mp_obj_get_complex(z_obj, &real, &imag);
@@ -57,8 +50,7 @@ STATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar);
-/// \function rect(r, phi)
-/// Returns the complex number with modulus `r` and phase `phi`.
+// rect(r, phi): returns the complex number with modulus r and phase phi
STATIC mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) {
mp_float_t r = mp_obj_get_float(r_obj);
mp_float_t phi = mp_obj_get_float(phi_obj);
@@ -66,8 +58,7 @@ STATIC mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect);
-/// \function exp(z)
-/// Return the exponential of `z`.
+// exp(z): return the exponential of z
STATIC mp_obj_t mp_cmath_exp(mp_obj_t z_obj) {
mp_float_t real, imag;
mp_obj_get_complex(z_obj, &real, &imag);
@@ -76,8 +67,7 @@ STATIC mp_obj_t mp_cmath_exp(mp_obj_t z_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp);
-/// \function log(z)
-/// Return the natural logarithm of `z`. The branch cut is along the negative real axis.
+// log(z): return the natural logarithm of z, with branch cut along the negative real axis
// TODO can take second argument, being the base
STATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) {
mp_float_t real, imag;
@@ -87,8 +77,7 @@ STATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log);
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
-/// \function log10(z)
-/// Return the base-10 logarithm of `z`. The branch cut is along the negative real axis.
+// log10(z): return the base-10 logarithm of z, with branch cut along the negative real axis
STATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) {
mp_float_t real, imag;
mp_obj_get_complex(z_obj, &real, &imag);
@@ -97,8 +86,7 @@ STATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10);
#endif
-/// \function sqrt(z)
-/// Return the square-root of `z`.
+// sqrt(z): return the square-root of z
STATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) {
mp_float_t real, imag;
mp_obj_get_complex(z_obj, &real, &imag);
@@ -108,8 +96,7 @@ STATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt);
-/// \function cos(z)
-/// Return the cosine of `z`.
+// cos(z): return the cosine of z
STATIC mp_obj_t mp_cmath_cos(mp_obj_t z_obj) {
mp_float_t real, imag;
mp_obj_get_complex(z_obj, &real, &imag);
@@ -117,8 +104,7 @@ STATIC mp_obj_t mp_cmath_cos(mp_obj_t z_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos);
-/// \function sin(z)
-/// Return the sine of `z`.
+// sin(z): return the sine of z
STATIC mp_obj_t mp_cmath_sin(mp_obj_t z_obj) {
mp_float_t real, imag;
mp_obj_get_complex(z_obj, &real, &imag);
diff --git a/py/modgc.c b/py/modgc.c
index d45e007eb..55e73defc 100644
--- a/py/modgc.c
+++ b/py/modgc.c
@@ -30,10 +30,7 @@
#if MICROPY_PY_GC && MICROPY_ENABLE_GC
-/// \module gc - control the garbage collector
-
-/// \function collect()
-/// Run a garbage collection.
+// collect(): run a garbage collection
STATIC mp_obj_t py_gc_collect(void) {
gc_collect();
#if MICROPY_PY_GC_COLLECT_RETVAL
@@ -44,16 +41,14 @@ STATIC mp_obj_t py_gc_collect(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect);
-/// \function disable()
-/// Disable the garbage collector.
+// disable(): disable the garbage collector
STATIC mp_obj_t gc_disable(void) {
MP_STATE_MEM(gc_auto_collect_enabled) = 0;
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable);
-/// \function enable()
-/// Enable the garbage collector.
+// enable(): enable the garbage collector
STATIC mp_obj_t gc_enable(void) {
MP_STATE_MEM(gc_auto_collect_enabled) = 1;
return mp_const_none;
@@ -65,8 +60,7 @@ STATIC mp_obj_t gc_isenabled(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_isenabled_obj, gc_isenabled);
-/// \function mem_free()
-/// Return the number of bytes of available heap RAM.
+// mem_free(): return the number of bytes of available heap RAM
STATIC mp_obj_t gc_mem_free(void) {
gc_info_t info;
gc_info(&info);
@@ -74,8 +68,7 @@ STATIC mp_obj_t gc_mem_free(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free);
-/// \function mem_alloc()
-/// Return the number of bytes of heap RAM that are allocated.
+// mem_alloc(): return the number of bytes of heap RAM that are allocated
STATIC mp_obj_t gc_mem_alloc(void) {
gc_info_t info;
gc_info(&info);
diff --git a/py/modmath.c b/py/modmath.c
index c56056a5d..4d627c67f 100644
--- a/py/modmath.c
+++ b/py/modmath.c
@@ -35,11 +35,6 @@
// And by defining our own we can ensure it uses the correct const format.
#define MP_PI MICROPY_FLOAT_CONST(3.14159265358979323846)
-/// \module math - mathematical functions
-///
-/// The `math` module provides some basic mathematical funtions for
-/// working with floating-point numbers.
-
STATIC NORETURN void math_error(void) {
mp_raise_ValueError("math domain error");
}
@@ -75,80 +70,74 @@ STATIC NORETURN void math_error(void) {
#define log2(x) (log(x) * 1.442695040888963407354163704)
#endif
-/// \function sqrt(x)
-/// Returns the square root of `x`.
+// sqrt(x): returns the square root of x
MATH_FUN_1_ERRCOND(sqrt, sqrt, (x < (mp_float_t)0.0))
-/// \function pow(x, y)
-/// Returns `x` to the power of `y`.
+// pow(x, y): returns x to the power of y
MATH_FUN_2(pow, pow)
-/// \function exp(x)
+// exp(x)
MATH_FUN_1(exp, exp)
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
-/// \function expm1(x)
+// expm1(x)
MATH_FUN_1(expm1, expm1)
-/// \function log2(x)
+// log2(x)
MATH_FUN_1_ERRCOND(log2, log2, (x <= (mp_float_t)0.0))
-/// \function log10(x)
+// log10(x)
MATH_FUN_1_ERRCOND(log10, log10, (x <= (mp_float_t)0.0))
-/// \function cosh(x)
+// cosh(x)
MATH_FUN_1(cosh, cosh)
-/// \function sinh(x)
+// sinh(x)
MATH_FUN_1(sinh, sinh)
-/// \function tanh(x)
+// tanh(x)
MATH_FUN_1(tanh, tanh)
-/// \function acosh(x)
+// acosh(x)
MATH_FUN_1(acosh, acosh)
-/// \function asinh(x)
+// asinh(x)
MATH_FUN_1(asinh, asinh)
-/// \function atanh(x)
+// atanh(x)
MATH_FUN_1(atanh, atanh)
#endif
-/// \function cos(x)
+// cos(x)
MATH_FUN_1(cos, cos)
-/// \function sin(x)
+// sin(x)
MATH_FUN_1(sin, sin)
-/// \function tan(x)
+// tan(x)
MATH_FUN_1(tan, tan)
-/// \function acos(x)
+// acos(x)
MATH_FUN_1(acos, acos)
-/// \function asin(x)
+// asin(x)
MATH_FUN_1(asin, asin)
-/// \function atan(x)
+// atan(x)
MATH_FUN_1(atan, atan)
-/// \function atan2(y, x)
+// atan2(y, x)
MATH_FUN_2(atan2, atan2)
-/// \function ceil(x)
+// ceil(x)
MATH_FUN_1_TO_INT(ceil, ceil)
-/// \function copysign(x, y)
+// copysign(x, y)
MATH_FUN_2(copysign, copysign)
-/// \function fabs(x)
+// fabs(x)
MATH_FUN_1(fabs, fabs)
-/// \function floor(x)
+// floor(x)
MATH_FUN_1_TO_INT(floor, floor) //TODO: delegate to x.__floor__() if x is not a float
-/// \function fmod(x, y)
+// fmod(x, y)
MATH_FUN_2(fmod, fmod)
-/// \function isfinite(x)
+// isfinite(x)
MATH_FUN_1_TO_BOOL(isfinite, isfinite)
-/// \function isinf(x)
+// isinf(x)
MATH_FUN_1_TO_BOOL(isinf, isinf)
-/// \function isnan(x)
+// isnan(x)
MATH_FUN_1_TO_BOOL(isnan, isnan)
-/// \function trunc(x)
+// trunc(x)
MATH_FUN_1_TO_INT(trunc, trunc)
-/// \function ldexp(x, exp)
+// ldexp(x, exp)
MATH_FUN_2(ldexp, ldexp)
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
-/// \function erf(x)
-/// Return the error function of `x`.
+// erf(x): return the error function of x
MATH_FUN_1(erf, erf)
-/// \function erfc(x)
-/// Return the complementary error function of `x`.
+// erfc(x): return the complementary error function of x
MATH_FUN_1(erfc, erfc)
-/// \function gamma(x)
-/// Return the gamma function of `x`.
+// gamma(x): return the gamma function of x
MATH_FUN_1(gamma, tgamma)
-/// \function lgamma(x)
-/// return the natural logarithm of the gamma function of `x`.
+// lgamma(x): return the natural logarithm of the gamma function of x
MATH_FUN_1(lgamma, lgamma)
#endif
//TODO: factorial, fsum
@@ -178,8 +167,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_math_log_obj, 1, 2, mp_math_log);
// Functions that return a tuple
-/// \function frexp(x)
-/// Converts a floating-point number to fractional and integral components.
+// frexp(x): converts a floating-point number to fractional and integral components
STATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) {
int int_exponent = 0;
mp_float_t significand = MICROPY_FLOAT_C_FUN(frexp)(mp_obj_get_float(x_obj), &int_exponent);
@@ -190,7 +178,7 @@ STATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_frexp_obj, mp_math_frexp);
-/// \function modf(x)
+// modf(x)
STATIC mp_obj_t mp_math_modf(mp_obj_t x_obj) {
mp_float_t int_part = 0.0;
mp_float_t fractional_part = MICROPY_FLOAT_C_FUN(modf)(mp_obj_get_float(x_obj), &int_part);
@@ -203,13 +191,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf);
// Angular conversions
-/// \function radians(x)
+// radians(x)
STATIC mp_obj_t mp_math_radians(mp_obj_t x_obj) {
return mp_obj_new_float(mp_obj_get_float(x_obj) * (MP_PI / MICROPY_FLOAT_CONST(180.0)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians);
-/// \function degrees(x)
+// degrees(x)
STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) {
return mp_obj_new_float(mp_obj_get_float(x_obj) * (MICROPY_FLOAT_CONST(180.0) / MP_PI));
}
diff --git a/py/modmicropython.c b/py/modmicropython.c
index 6fa3f9ad2..2aac53adc 100644
--- a/py/modmicropython.c
+++ b/py/modmicropython.c
@@ -26,7 +26,6 @@
#include <stdio.h>
-#include "py/mpstate.h"
#include "py/builtin.h"
#include "py/stackctrl.h"
#include "py/runtime.h"
diff --git a/py/modstruct.c b/py/modstruct.c
index 1daa33338..8617a8e0d 100644
--- a/py/modstruct.c
+++ b/py/modstruct.c
@@ -82,26 +82,10 @@ STATIC mp_uint_t get_fmt_num(const char **p) {
return val;
}
-STATIC uint calcsize_items(const char *fmt) {
- uint cnt = 0;
- while (*fmt) {
- int num = 1;
- if (unichar_isdigit(*fmt)) {
- num = get_fmt_num(&fmt);
- if (*fmt == 's') {
- num = 1;
- }
- }
- cnt += num;
- fmt++;
- }
- return cnt;
-}
-
-STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
- const char *fmt = mp_obj_str_get_str(fmt_in);
+STATIC size_t calc_size_items(const char *fmt, size_t *total_sz) {
char fmt_type = get_fmt_type(&fmt);
- mp_uint_t size;
+ size_t total_cnt = 0;
+ size_t size;
for (size = 0; *fmt; fmt++) {
mp_uint_t cnt = 1;
if (unichar_isdigit(*fmt)) {
@@ -109,8 +93,10 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
}
if (*fmt == 's') {
+ total_cnt += 1;
size += cnt;
} else {
+ total_cnt += cnt;
mp_uint_t align;
size_t sz = mp_binary_get_size(fmt_type, *fmt, &align);
while (cnt--) {
@@ -120,6 +106,14 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
}
}
}
+ *total_sz = size;
+ return total_cnt;
+}
+
+STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
+ const char *fmt = mp_obj_str_get_str(fmt_in);
+ size_t size;
+ calc_size_items(fmt, &size);
return MP_OBJ_NEW_SMALL_INT(size);
}
MP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize);
@@ -130,8 +124,9 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) {
// Since we implement unpack and unpack_from using the same function
// we relax the "exact" requirement, and only implement "big enough".
const char *fmt = mp_obj_str_get_str(args[0]);
+ size_t total_sz;
+ size_t num_items = calc_size_items(fmt, &total_sz);
char fmt_type = get_fmt_type(&fmt);
- uint num_items = calcsize_items(fmt);
mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_items, NULL));
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
@@ -152,21 +147,23 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) {
p += offset;
}
- for (uint i = 0; i < num_items;) {
- mp_uint_t sz = 1;
+ // Check that the input buffer is big enough to unpack all the values
+ if (p + total_sz > end_p) {
+ mp_raise_ValueError("buffer too small");
+ }
+
+ for (size_t i = 0; i < num_items;) {
+ mp_uint_t cnt = 1;
if (unichar_isdigit(*fmt)) {
- sz = get_fmt_num(&fmt);
- }
- if (p + sz > end_p) {
- mp_raise_ValueError("buffer too small");
+ cnt = get_fmt_num(&fmt);
}
mp_obj_t item;
if (*fmt == 's') {
- item = mp_obj_new_bytes(p, sz);
- p += sz;
+ item = mp_obj_new_bytes(p, cnt);
+ p += cnt;
res->items[i++] = item;
} else {
- while (sz--) {
+ while (cnt--) {
item = mp_binary_get_val(fmt_type, *fmt, &p);
res->items[i++] = item;
}
@@ -177,36 +174,35 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_unpack_from_obj, 2, 3, struct_unpack_from);
-STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, byte* end_p, size_t n_args, const mp_obj_t *args) {
+// This function assumes there is enough room in p to store all the values
+STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, const mp_obj_t *args) {
const char *fmt = mp_obj_str_get_str(fmt_in);
char fmt_type = get_fmt_type(&fmt);
size_t i;
for (i = 0; i < n_args;) {
- mp_uint_t sz = 1;
+ mp_uint_t cnt = 1;
if (*fmt == '\0') {
// more arguments given than used by format string; CPython raises struct.error here
break;
}
if (unichar_isdigit(*fmt)) {
- sz = get_fmt_num(&fmt);
- }
- if (p + sz > end_p) {
- mp_raise_ValueError("buffer too small");
+ cnt = get_fmt_num(&fmt);
}
if (*fmt == 's') {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[i++], &bufinfo, MP_BUFFER_READ);
- mp_uint_t to_copy = sz;
+ mp_uint_t to_copy = cnt;
if (bufinfo.len < to_copy) {
to_copy = bufinfo.len;
}
memcpy(p, bufinfo.buf, to_copy);
- memset(p + to_copy, 0, sz - to_copy);
- p += sz;
+ memset(p + to_copy, 0, cnt - to_copy);
+ p += cnt;
} else {
- while (sz--) {
+ // If we run out of args then we just finish; CPython would raise struct.error
+ while (cnt-- && i < n_args) {
mp_binary_set_val(fmt_type, *fmt, args[i++], &p);
}
}
@@ -221,8 +217,7 @@ STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) {
vstr_init_len(&vstr, size);
byte *p = (byte*)vstr.buf;
memset(p, 0, size);
- byte *end_p = &p[size];
- struct_pack_into_internal(args[0], p, end_p, n_args - 1, &args[1]);
+ struct_pack_into_internal(args[0], p, n_args - 1, &args[1]);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack);
@@ -242,7 +237,13 @@ STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) {
byte *end_p = &p[bufinfo.len];
p += offset;
- struct_pack_into_internal(args[0], p, end_p, n_args - 3, &args[3]);
+ // Check that the output buffer is big enough to hold all the values
+ mp_int_t sz = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0]));
+ if (p + sz > end_p) {
+ mp_raise_ValueError("buffer too small");
+ }
+
+ struct_pack_into_internal(args[0], p, n_args - 3, &args[3]);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_into_obj, 3, MP_OBJ_FUN_ARGS_MAX, struct_pack_into);
diff --git a/py/modsys.c b/py/modsys.c
index ee6f8686e..84a4eb0f4 100644
--- a/py/modsys.c
+++ b/py/modsys.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2014-2017 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,22 +25,20 @@
* THE SOFTWARE.
*/
-#include "py/mpstate.h"
-#include "py/nlr.h"
#include "py/builtin.h"
#include "py/objlist.h"
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/objint.h"
+#include "py/objtype.h"
#include "py/stream.h"
#include "py/smallint.h"
+#include "py/runtime.h"
#if MICROPY_PY_SYS
#include "genhdr/mpversion.h"
-/// \module sys - system specific functions
-
// defined per port; type of these is irrelevant, just need pointer
extern struct _mp_dummy_t mp_sys_stdin_obj;
extern struct _mp_dummy_t mp_sys_stdout_obj;
@@ -49,10 +48,10 @@ extern struct _mp_dummy_t mp_sys_stderr_obj;
const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, mp_stream_write_adaptor};
#endif
-/// \constant version - Python language version that this implementation conforms to, as a string
+// version - Python language version that this implementation conforms to, as a string
STATIC const MP_DEFINE_STR_OBJ(version_obj, "3.4.0");
-/// \constant version_info - Python language version that this implementation conforms to, as a tuple of ints
+// version_info - Python language version that this implementation conforms to, as a tuple of ints
#define I(n) MP_OBJ_NEW_SMALL_INT(n)
// TODO: CPython is now at 5-element array, but save 2 els so far...
STATIC const mp_obj_tuple_t mp_sys_version_info_obj = {{&mp_type_tuple}, 3, {I(3), I(4), I(0)}};
@@ -87,13 +86,11 @@ STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = {
#undef I
#ifdef MICROPY_PY_SYS_PLATFORM
-/// \constant platform - the platform that MicroPython is running on
+// platform - the platform that MicroPython is running on
STATIC const MP_DEFINE_STR_OBJ(platform_obj, MICROPY_PY_SYS_PLATFORM);
#endif
-/// \function exit([retval])
-/// Raise a `SystemExit` exception. If an argument is given, it is the
-/// value given to `SystemExit`.
+// exit([retval]): raise SystemExit, with optional argument given to the exception
STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) {
mp_obj_t exc;
if (n_args == 0) {
@@ -143,6 +140,11 @@ STATIC mp_obj_t mp_sys_exc_info(void) {
MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info);
#endif
+STATIC mp_obj_t mp_sys_getsizeof(mp_obj_t obj) {
+ return mp_unary_op(MP_UNARY_OP_SIZEOF, obj);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof);
+
STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) },
@@ -154,7 +156,6 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
#ifdef MICROPY_PY_SYS_PLATFORM
{ MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_obj) },
#endif
- /// \constant byteorder - the byte order of the system ("little" or "big")
#if MP_ENDIANNESS_LITTLE
{ MP_ROM_QSTR(MP_QSTR_byteorder), MP_ROM_QSTR(MP_QSTR_little) },
#else
@@ -175,12 +176,10 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
#endif
#if MICROPY_PY_SYS_EXIT
- // documented per-port
{ MP_ROM_QSTR(MP_QSTR_exit), MP_ROM_PTR(&mp_sys_exit_obj) },
#endif
#if MICROPY_PY_SYS_STDFILES
- // documented per-port
{ MP_ROM_QSTR(MP_QSTR_stdin), MP_ROM_PTR(&mp_sys_stdin_obj) },
{ MP_ROM_QSTR(MP_QSTR_stdout), MP_ROM_PTR(&mp_sys_stdout_obj) },
{ MP_ROM_QSTR(MP_QSTR_stderr), MP_ROM_PTR(&mp_sys_stderr_obj) },
@@ -192,6 +191,9 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
#if MICROPY_PY_SYS_EXC_INFO
{ MP_ROM_QSTR(MP_QSTR_exc_info), MP_ROM_PTR(&mp_sys_exc_info_obj) },
#endif
+ #if MICROPY_PY_SYS_GETSIZEOF
+ { MP_ROM_QSTR(MP_QSTR_getsizeof), MP_ROM_PTR(&mp_sys_getsizeof_obj) },
+ #endif
/*
* Extensions to CPython
diff --git a/py/modthread.c b/py/modthread.c
index 1d7602789..cb071d0f8 100644
--- a/py/modthread.c
+++ b/py/modthread.c
@@ -34,7 +34,7 @@
#include "py/mpthread.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
@@ -192,10 +192,10 @@ STATIC void *thread_entry(void *args_in) {
// swallow exception silently
} else {
// print exception out
- mp_printf(&mp_plat_print, "Unhandled exception in thread started by ");
- mp_obj_print_helper(&mp_plat_print, args->fun, PRINT_REPR);
- mp_printf(&mp_plat_print, "\n");
- mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(exc));
+ mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in thread started by ");
+ mp_obj_print_helper(MICROPY_ERROR_PRINTER, args->fun, PRINT_REPR);
+ mp_printf(MICROPY_ERROR_PRINTER, "\n");
+ mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(exc));
}
}
diff --git a/py/mpconfig.h b/py/mpconfig.h
index fb507a503..44de3beeb 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -373,11 +373,18 @@
#define MICROPY_DEBUG_PRINTERS (0)
#endif
+// Whether to enable all debugging outputs (it will be extremely verbose)
+#ifndef MICROPY_DEBUG_VERBOSE
+#define MICROPY_DEBUG_VERBOSE (0)
+#endif
+
/*****************************************************************************/
/* Optimisations */
// Whether to use computed gotos in the VM, or a switch
// Computed gotos are roughly 10% faster, and increase VM code size by a little
+// Note: enabling this will use the gcc-specific extensions of ranged designated
+// initialisers and addresses of labels, which are not part of the C99 standard.
#ifndef MICROPY_OPT_COMPUTED_GOTO
#define MICROPY_OPT_COMPUTED_GOTO (0)
#endif
@@ -526,6 +533,11 @@ typedef long long mp_longint_impl_t;
#define MICROPY_WARNINGS (0)
#endif
+// This macro is used when printing runtime warnings and errors
+#ifndef MICROPY_ERROR_PRINTER
+#define MICROPY_ERROR_PRINTER (&mp_plat_print)
+#endif
+
// Float and complex implementation
#define MICROPY_FLOAT_IMPL_NONE (0)
#define MICROPY_FLOAT_IMPL_FLOAT (1)
@@ -686,6 +698,11 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
#endif
+// Whether to check for valid UTF-8 when converting bytes to str
+#ifndef MICROPY_PY_BUILTINS_STR_UNICODE_CHECK
+#define MICROPY_PY_BUILTINS_STR_UNICODE_CHECK (MICROPY_PY_BUILTINS_STR_UNICODE)
+#endif
+
// Whether str.center() method provided
#ifndef MICROPY_PY_BUILTINS_STR_CENTER
#define MICROPY_PY_BUILTINS_STR_CENTER (0)
@@ -749,11 +766,19 @@ typedef double mp_float_t;
#endif
// Whether to support complete set of special methods
-// for user classes, otherwise only the most used
+// for user classes, or only the most used ones. "Reverse"
+// methods are controlled by MICROPY_PY_REVERSE_SPECIAL_METHODS
+// below.
#ifndef MICROPY_PY_ALL_SPECIAL_METHODS
#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
#endif
+// Whether to support reverse arithmetic operarions methods
+// (__radd__, etc.)
+#ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS
+#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
+#endif
+
// Whether to support compile function
#ifndef MICROPY_PY_BUILTINS_COMPILE
#define MICROPY_PY_BUILTINS_COMPILE (0)
@@ -944,6 +969,11 @@ typedef double mp_float_t;
#define MICROPY_PY_SYS_EXIT (1)
#endif
+// Whether to provide "sys.getsizeof" function
+#ifndef MICROPY_PY_SYS_GETSIZEOF
+#define MICROPY_PY_SYS_GETSIZEOF (0)
+#endif
+
// Whether to provide sys.{stdin,stdout,stderr} objects
#ifndef MICROPY_PY_SYS_STDFILES
#define MICROPY_PY_SYS_STDFILES (0)
diff --git a/py/mpprint.c b/py/mpprint.c
index 6c02d7cef..a569ef793 100644
--- a/py/mpprint.c
+++ b/py/mpprint.c
@@ -485,14 +485,17 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
case 's':
{
const char *str = va_arg(args, const char*);
- if (str) {
- if (prec < 0) {
- prec = strlen(str);
- }
- chrs += mp_print_strn(print, str, prec, flags, fill, width);
- } else {
+ #ifndef NDEBUG
+ // With debugging enabled, catch printing of null string pointers
+ if (prec != 0 && str == NULL) {
chrs += mp_print_strn(print, "(null)", 6, flags, fill, width);
+ break;
}
+ #endif
+ if (prec < 0) {
+ prec = strlen(str);
+ }
+ chrs += mp_print_strn(print, str, prec, flags, fill, width);
break;
}
case 'u':
diff --git a/py/nativeglue.c b/py/nativeglue.c
index 46c6906d9..61b624ec7 100644
--- a/py/nativeglue.c
+++ b/py/nativeglue.c
@@ -28,13 +28,11 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/emitglue.h"
#include "py/bc.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
diff --git a/py/nlrthumb.c b/py/nlrthumb.c
index 08a71ac7d..6e7d71766 100644
--- a/py/nlrthumb.c
+++ b/py/nlrthumb.c
@@ -25,7 +25,6 @@
*/
#include "py/mpstate.h"
-#include "py/nlr.h"
#if (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
@@ -67,7 +66,14 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) {
"str lr, [r0, #8] \n" // store lr into nlr_buf
#endif
+#if defined(__ARM_ARCH_6M__)
+ "ldr r1, nlr_push_tail_var \n"
+ "bx r1 \n" // do the rest in C
+ ".align 2 \n"
+ "nlr_push_tail_var: .word nlr_push_tail \n"
+#else
"b nlr_push_tail \n" // do the rest in C
+#endif
);
return 0; // needed to silence compiler warning
diff --git a/py/nlrx64.c b/py/nlrx64.c
index c23fd8fc6..847d10398 100644
--- a/py/nlrx64.c
+++ b/py/nlrx64.c
@@ -25,7 +25,6 @@
*/
#include "py/mpstate.h"
-#include "py/nlr.h"
#if !MICROPY_NLR_SETJMP && defined(__x86_64__)
@@ -34,7 +33,11 @@
// x86-64 callee-save registers are:
// rbx, rbp, rsp, r12, r13, r14, r15
-#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__))
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define NLR_OS_WINDOWS 1
+#else
+#define NLR_OS_WINDOWS 0
+#endif
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
diff --git a/py/nlrx86.c b/py/nlrx86.c
index 58aaa1a57..094dea3cc 100644
--- a/py/nlrx86.c
+++ b/py/nlrx86.c
@@ -24,9 +24,7 @@
* THE SOFTWARE.
*/
-#include "py/mpconfig.h"
#include "py/mpstate.h"
-#include "py/nlr.h"
#if !MICROPY_NLR_SETJMP && defined(__i386__)
@@ -35,7 +33,11 @@
// For reference, x86 callee save regs are:
// ebx, esi, edi, ebp, esp, eip
-#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__))
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define NLR_OS_WINDOWS 1
+#else
+#define NLR_OS_WINDOWS 0
+#endif
#if NLR_OS_WINDOWS
unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail");
@@ -51,7 +53,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
// by default.
// TODE: Better support for various x86 calling conventions
// (unfortunately, __attribute__((naked)) is not supported on x86).
- #ifndef __ZEPHYR__
+ #if !(defined(__ZEPHYR__) || defined(__ANDROID__))
"pop %ebp \n" // undo function's prelude
#endif
"mov 4(%esp), %edx \n" // load nlr_buf
diff --git a/py/nlrxtensa.c b/py/nlrxtensa.c
index ccac3597b..4520e7e7a 100644
--- a/py/nlrxtensa.c
+++ b/py/nlrxtensa.c
@@ -25,7 +25,6 @@
*/
#include "py/mpstate.h"
-#include "py/nlr.h"
#if !MICROPY_NLR_SETJMP && defined(__xtensa__)
diff --git a/py/obj.c b/py/obj.c
index 515a95b2e..a1de89a03 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -29,12 +29,10 @@
#include <stdarg.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/obj.h"
#include "py/objtype.h"
#include "py/objint.h"
#include "py/objstr.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
#include "py/stream.h" // for mp_obj_print
@@ -162,7 +160,16 @@ bool mp_obj_is_callable(mp_obj_t o_in) {
// comparison returns NotImplemented, == and != are decided by comparing the object
// pointer."
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
- if (o1 == o2) {
+ // Float (and complex) NaN is never equal to anything, not even itself,
+ // so we must have a special check here to cover those cases.
+ if (o1 == o2
+ #if MICROPY_PY_BUILTINS_FLOAT
+ && !mp_obj_is_float(o1)
+ #endif
+ #if MICROPY_PY_BUILTINS_COMPLEX
+ && !MP_OBJ_IS_TYPE(o1, &mp_type_complex)
+ #endif
+ ) {
return true;
}
if (o1 == mp_const_none || o2 == mp_const_none) {
@@ -264,20 +271,33 @@ bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) {
}
#if MICROPY_PY_BUILTINS_FLOAT
-mp_float_t mp_obj_get_float(mp_obj_t arg) {
+bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) {
+ mp_float_t val;
+
if (arg == mp_const_false) {
- return 0;
+ val = 0;
} else if (arg == mp_const_true) {
- return 1;
+ val = 1;
} else if (MP_OBJ_IS_SMALL_INT(arg)) {
- return MP_OBJ_SMALL_INT_VALUE(arg);
+ val = MP_OBJ_SMALL_INT_VALUE(arg);
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
} else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) {
- return mp_obj_int_as_float_impl(arg);
+ val = mp_obj_int_as_float_impl(arg);
#endif
} else if (mp_obj_is_float(arg)) {
- return mp_obj_float_get(arg);
+ val = mp_obj_float_get(arg);
} else {
+ return false;
+ }
+
+ *value = val;
+ return true;
+}
+
+mp_float_t mp_obj_get_float(mp_obj_t arg) {
+ mp_float_t val;
+
+ if (!mp_obj_get_float_maybe(arg, &val)) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_raise_TypeError("can't convert to float");
} else {
@@ -285,6 +305,8 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
"can't convert %s to float", mp_obj_get_type_str(arg)));
}
}
+
+ return val;
}
#if MICROPY_PY_BUILTINS_COMPLEX
@@ -505,7 +527,7 @@ void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flag
}
}
-mp_obj_t mp_generic_unary_op(mp_uint_t op, mp_obj_t o_in) {
+mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
switch (op) {
case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in);
default: return MP_OBJ_NULL; // op not supported
diff --git a/py/obj.h b/py/obj.h
index 22bfda0f9..77f0f2298 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -30,6 +30,7 @@
#include "py/misc.h"
#include "py/qstr.h"
#include "py/mpprint.h"
+#include "py/runtime0.h"
// This is the definition of the opaque MicroPython object type.
// All concrete objects have an encoding within this type and the
@@ -429,8 +430,8 @@ typedef struct _mp_obj_iter_buf_t {
typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);
typedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);
-typedef mp_obj_t (*mp_unary_op_fun_t)(mp_uint_t op, mp_obj_t);
-typedef mp_obj_t (*mp_binary_op_fun_t)(mp_uint_t op, mp_obj_t, mp_obj_t);
+typedef mp_obj_t (*mp_unary_op_fun_t)(mp_unary_op_t op, mp_obj_t);
+typedef mp_obj_t (*mp_binary_op_fun_t)(mp_binary_op_t op, mp_obj_t, mp_obj_t);
typedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf);
@@ -615,6 +616,7 @@ extern const mp_obj_type_t mp_type_ZeroDivisionError;
#define mp_const_true (MP_OBJ_FROM_PTR(&mp_const_true_obj))
#define mp_const_empty_bytes (MP_OBJ_FROM_PTR(&mp_const_empty_bytes_obj))
#define mp_const_empty_tuple (MP_OBJ_FROM_PTR(&mp_const_empty_tuple_obj))
+#define mp_const_notimplemented (MP_OBJ_FROM_PTR(&mp_const_notimplemented_obj))
extern const struct _mp_obj_none_t mp_const_none_obj;
extern const struct _mp_obj_bool_t mp_const_false_obj;
extern const struct _mp_obj_bool_t mp_const_true_obj;
@@ -628,7 +630,6 @@ extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj;
// General API for objects
mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict);
-mp_obj_t mp_obj_new_none(void);
static inline mp_obj_t mp_obj_new_bool(mp_int_t x) { return x ? mp_const_true : mp_const_false; }
mp_obj_t mp_obj_new_cell(mp_obj_t obj);
mp_obj_t mp_obj_new_int(mp_int_t value);
@@ -684,6 +685,7 @@ mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg);
bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value);
#if MICROPY_PY_BUILTINS_FLOAT
mp_float_t mp_obj_get_float(mp_obj_t self_in);
+bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value);
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
#endif
//qstr mp_obj_get_qstr(mp_obj_t arg);
@@ -694,7 +696,7 @@ mp_obj_t mp_obj_id(mp_obj_t o_in);
mp_obj_t mp_obj_len(mp_obj_t o_in);
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL
mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
-mp_obj_t mp_generic_unary_op(mp_uint_t op, mp_obj_t o_in);
+mp_obj_t mp_generic_unary_op(mp_unary_op_t op, mp_obj_t o_in);
// cell
mp_obj_t mp_obj_cell_get(mp_obj_t self_in);
@@ -734,11 +736,11 @@ mp_int_t mp_float_hash(mp_float_t val);
#else
static inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; }
#endif
-mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported
+mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported
// complex
void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
-mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NULL if op not supported
+mp_obj_t mp_obj_complex_binary_op(mp_binary_op_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NULL if op not supported
#else
#define mp_obj_is_float(o) (false)
#endif
diff --git a/py/objarray.c b/py/objarray.c
index 99146bd4c..8a3e7faad 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -29,8 +29,6 @@
#include <assert.h>
#include <stdint.h>
-#include "py/nlr.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/binary.h"
#include "py/objstr.h"
@@ -231,7 +229,7 @@ STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args,
}
#endif
-STATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) {
+STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->len != 0);
@@ -240,7 +238,7 @@ STATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) {
}
}
-STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in);
switch (op) {
case MP_BINARY_OP_ADD: {
@@ -288,7 +286,7 @@ STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
// Otherwise, can only look for a scalar numeric value in an array
if (MP_OBJ_IS_INT(rhs_in) || mp_obj_is_float(rhs_in)) {
- mp_not_implemented("");
+ mp_raise_NotImplementedError("");
}
return mp_const_false;
@@ -378,7 +376,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
} else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &slice)) {
- mp_not_implemented("only slices with step=1 (aka None) are supported");
+ mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported");
}
if (value != MP_OBJ_SENTINEL) {
#if MICROPY_PY_ARRAY_SLICE_ASSIGN
@@ -409,7 +407,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
src_len = bufinfo.len;
src_items = bufinfo.buf;
} else {
- mp_not_implemented("array/bytes required on right side");
+ mp_raise_NotImplementedError("array/bytes required on right side");
}
// TODO: check src/dst compat
diff --git a/py/objbool.c b/py/objbool.c
index e5bc3c228..5755b188e 100644
--- a/py/objbool.c
+++ b/py/objbool.c
@@ -26,8 +26,6 @@
#include <stdlib.h>
-#include "py/obj.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
typedef struct _mp_obj_bool_t {
@@ -63,7 +61,7 @@ STATIC mp_obj_t bool_make_new(const mp_obj_type_t *type_in, size_t n_args, size_
}
}
-STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) {
+STATIC mp_obj_t bool_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
if (op == MP_UNARY_OP_LEN) {
return MP_OBJ_NULL;
}
@@ -71,7 +69,7 @@ STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) {
return mp_unary_op(op, MP_OBJ_NEW_SMALL_INT(self->value));
}
-STATIC mp_obj_t bool_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+STATIC mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_bool_t *self = MP_OBJ_TO_PTR(lhs_in);
return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(self->value), rhs_in);
}
diff --git a/py/objcomplex.c b/py/objcomplex.c
index f945f3560..409d65666 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -28,10 +28,7 @@
#include <stdio.h>
#include <assert.h>
-#include "py/nlr.h"
-#include "py/obj.h"
#include "py/parsenum.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#if MICROPY_PY_BUILTINS_COMPLEX
@@ -117,18 +114,20 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si
}
}
-STATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) {
+STATIC mp_obj_t complex_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->real != 0 || o->imag != 0);
case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(o->real) ^ mp_float_hash(o->imag));
case MP_UNARY_OP_POSITIVE: return o_in;
case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag);
+ case MP_UNARY_OP_ABS:
+ return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(o->real*o->real + o->imag*o->imag));
default: return MP_OBJ_NULL; // op not supported
}
}
-STATIC mp_obj_t complex_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+STATIC mp_obj_t complex_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_complex_t *lhs = MP_OBJ_TO_PTR(lhs_in);
return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in);
}
@@ -171,7 +170,7 @@ void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) {
*imag = self->imag;
}
-mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_complex_binary_op(mp_binary_op_t op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in) {
mp_float_t rhs_real, rhs_imag;
mp_obj_get_complex(rhs_in, &rhs_real, &rhs_imag); // can be any type, this function will convert to float (if possible)
switch (op) {
@@ -229,7 +228,6 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t
if (abs1 == 0) {
if (rhs_imag == 0 && rhs_real >= 0) {
lhs_real = (rhs_real == 0);
- rhs_real = 0;
} else {
mp_raise_msg(&mp_type_ZeroDivisionError, "0.0 to a complex power");
}
diff --git a/py/objdict.c b/py/objdict.c
index a272ebdb6..1553a83b4 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -27,9 +27,6 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
-#include "py/obj.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/objtype.h"
@@ -100,16 +97,22 @@ STATIC mp_obj_t dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
return dict_out;
}
-STATIC mp_obj_t dict_unary_op(mp_uint_t op, mp_obj_t self_in) {
+STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->map.used != 0);
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->map.used);
+ #if MICROPY_PY_SYS_GETSIZEOF
+ case MP_UNARY_OP_SIZEOF: {
+ size_t sz = sizeof(*self) + sizeof(*self->map.table) * self->map.alloc;
+ return MP_OBJ_NEW_SMALL_INT(sz);
+ }
+ #endif
default: return MP_OBJ_NULL; // op not supported
}
}
-STATIC mp_obj_t dict_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in);
switch (op) {
case MP_BINARY_OP_IN: {
@@ -476,7 +479,7 @@ STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
mp_print_str(print, "])");
}
-STATIC mp_obj_t dict_view_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// only supported for the 'keys' kind until sets and dicts are refactored
mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(lhs_in);
if (o->kind != MP_DICT_VIEW_KEYS) {
diff --git a/py/objexcept.c b/py/objexcept.c
index a9fe04094..b87609a6b 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -29,7 +29,6 @@
#include <assert.h>
#include <stdio.h>
-#include "py/mpstate.h"
#include "py/objlist.h"
#include "py/objstr.h"
#include "py/objtuple.h"
@@ -38,6 +37,12 @@
#include "py/gc.h"
#include "py/mperrno.h"
+// Number of items per traceback entry (file, line, block)
+#define TRACEBACK_ENTRY_LEN (3)
+
+// Number of traceback entries to reserve in the emergency exception buffer
+#define EMG_TRACEBACK_ALLOC (2 * TRACEBACK_ENTRY_LEN)
+
// Instance of MemoryError exception - needed by mp_malloc_fail
const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};
@@ -127,18 +132,51 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr
mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false);
- mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0);
- if (o == NULL) {
- // Couldn't allocate heap memory; use local data instead.
- o = &MP_STATE_VM(mp_emergency_exception_obj);
- // We can't store any args.
- o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
+
+ // Try to allocate memory for the exception, with fallback to emergency exception object
+ mp_obj_exception_t *o_exc = m_new_obj_maybe(mp_obj_exception_t);
+ if (o_exc == NULL) {
+ o_exc = &MP_STATE_VM(mp_emergency_exception_obj);
+ }
+
+ // Populate the exception object
+ o_exc->base.type = type;
+ o_exc->traceback_data = NULL;
+
+ mp_obj_tuple_t *o_tuple;
+ if (n_args == 0) {
+ // No args, can use the empty tuple straightaway
+ o_tuple = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
} else {
- o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_args, args));
+ // Try to allocate memory for the tuple containing the args
+ o_tuple = m_new_obj_var_maybe(mp_obj_tuple_t, mp_obj_t, n_args);
+
+ #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
+ // If we are called by mp_obj_new_exception_msg_varg then it will have
+ // reserved room (after the traceback data) for a tuple with 1 element.
+ // Otherwise we are free to use the whole buffer after the traceback data.
+ if (o_tuple == NULL && mp_emergency_exception_buf_size >=
+ EMG_TRACEBACK_ALLOC * sizeof(size_t) + sizeof(mp_obj_tuple_t) + n_args * sizeof(mp_obj_t)) {
+ o_tuple = (mp_obj_tuple_t*)
+ ((uint8_t*)MP_STATE_VM(mp_emergency_exception_buf) + EMG_TRACEBACK_ALLOC * sizeof(size_t));
+ }
+ #endif
+
+ if (o_tuple == NULL) {
+ // No memory for a tuple, fallback to an empty tuple
+ o_tuple = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
+ } else {
+ // Have memory for a tuple so populate it
+ o_tuple->base.type = &mp_type_tuple;
+ o_tuple->len = n_args;
+ memcpy(o_tuple->items, args, n_args * sizeof(mp_obj_t));
+ }
}
- o->base.type = type;
- o->traceback_data = NULL;
- return MP_OBJ_FROM_PTR(o);
+
+ // Store the tuple of args in the exception object
+ o_exc->args = o_tuple;
+
+ return MP_OBJ_FROM_PTR(o_exc);
}
// Get exception "value" - that is, first argument, or None
@@ -306,87 +344,95 @@ mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg
return mp_obj_new_exception_msg_varg(exc_type, msg);
}
-mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) {
- // check that the given type is an exception type
- assert(exc_type->make_new == mp_obj_exception_make_new);
-
- // make exception object
- mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0);
- if (o == NULL) {
- // Couldn't allocate heap memory; use local data instead.
- // Unfortunately, we won't be able to format the string...
- o = &MP_STATE_VM(mp_emergency_exception_obj);
- o->base.type = exc_type;
- o->traceback_data = NULL;
- o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
-
-#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
- // If the user has provided a buffer, then we try to create a tuple
- // of length 1, which has a string object and the string data.
+// The following struct and function implement a simple printer that conservatively
+// allocates memory and truncates the output data if no more memory can be obtained.
+// It leaves room for a null byte at the end of the buffer.
- if (mp_emergency_exception_buf_size > (sizeof(mp_obj_tuple_t) + sizeof(mp_obj_str_t) + sizeof(mp_obj_t))) {
- mp_obj_tuple_t *tuple = (mp_obj_tuple_t *)MP_STATE_VM(mp_emergency_exception_buf);
- mp_obj_str_t *str = (mp_obj_str_t *)&tuple->items[1];
-
- tuple->base.type = &mp_type_tuple;
- tuple->len = 1;
- tuple->items[0] = MP_OBJ_FROM_PTR(str);
-
- byte *str_data = (byte *)&str[1];
- size_t max_len = (byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size
- - str_data;
+struct _exc_printer_t {
+ bool allow_realloc;
+ size_t alloc;
+ size_t len;
+ byte *buf;
+};
- vstr_t vstr;
- vstr_init_fixed_buf(&vstr, max_len, (char *)str_data);
+STATIC void exc_add_strn(void *data, const char *str, size_t len) {
+ struct _exc_printer_t *pr = data;
+ if (pr->len + len >= pr->alloc) {
+ // Not enough room for data plus a null byte so try to grow the buffer
+ if (pr->allow_realloc) {
+ size_t new_alloc = pr->alloc + len + 16;
+ byte *new_buf = m_renew_maybe(byte, pr->buf, pr->alloc, new_alloc, true);
+ if (new_buf == NULL) {
+ pr->allow_realloc = false;
+ len = pr->alloc - pr->len - 1;
+ } else {
+ pr->alloc = new_alloc;
+ pr->buf = new_buf;
+ }
+ } else {
+ len = pr->alloc - pr->len - 1;
+ }
+ }
+ memcpy(pr->buf + pr->len, str, len);
+ pr->len += len;
+}
- va_list ap;
- va_start(ap, fmt);
- vstr_vprintf(&vstr, fmt, ap);
- va_end(ap);
+mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) {
+ assert(fmt != NULL);
- str->base.type = &mp_type_str;
- str->hash = qstr_compute_hash(str_data, str->len);
- str->len = vstr.len;
- str->data = str_data;
+ // Check that the given type is an exception type
+ assert(exc_type->make_new == mp_obj_exception_make_new);
- o->args = tuple;
+ // Try to allocate memory for the message
+ mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t);
+ size_t o_str_alloc = strlen(fmt) + 1;
+ byte *o_str_buf = m_new_maybe(byte, o_str_alloc);
+
+ bool used_emg_buf = false;
+ #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
+ // If memory allocation failed and there is an emergency buffer then try to use
+ // that buffer to store the string object and its data (at least 16 bytes for
+ // the string data), reserving room at the start for the traceback and 1-tuple.
+ if ((o_str == NULL || o_str_buf == NULL)
+ && mp_emergency_exception_buf_size >= EMG_TRACEBACK_ALLOC * sizeof(size_t)
+ + sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t) + sizeof(mp_obj_str_t) + 16) {
+ used_emg_buf = true;
+ o_str = (mp_obj_str_t*)((uint8_t*)MP_STATE_VM(mp_emergency_exception_buf)
+ + EMG_TRACEBACK_ALLOC * sizeof(size_t) + sizeof(mp_obj_tuple_t) + sizeof(mp_obj_t));
+ o_str_buf = (byte*)&o_str[1];
+ o_str_alloc = (uint8_t*)MP_STATE_VM(mp_emergency_exception_buf)
+ + mp_emergency_exception_buf_size - o_str_buf;
+ }
+ #endif
- size_t offset = &str_data[str->len] - (byte*)MP_STATE_VM(mp_emergency_exception_buf);
- offset += sizeof(void *) - 1;
- offset &= ~(sizeof(void *) - 1);
+ if (o_str == NULL) {
+ // No memory for the string object so create the exception with no args
+ return mp_obj_exception_make_new(exc_type, 0, 0, NULL);
+ }
- if ((mp_emergency_exception_buf_size - offset) > (sizeof(o->traceback_data[0]) * 3)) {
- // We have room to store some traceback.
- o->traceback_data = (size_t*)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset);
- o->traceback_alloc = ((byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]);
- o->traceback_len = 0;
- }
- }
-#endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
+ if (o_str_buf == NULL) {
+ // No memory for the string buffer: assume that the fmt string is in ROM
+ // and use that data as the data of the string
+ o_str->len = o_str_alloc - 1; // will be equal to strlen(fmt)
+ o_str->data = (const byte*)fmt;
} else {
- o->base.type = exc_type;
- o->traceback_data = NULL;
- o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(1, NULL));
-
- assert(fmt != NULL);
- {
- if (strchr(fmt, '%') == NULL) {
- // no formatting substitutions, avoid allocating vstr.
- o->args->items[0] = mp_obj_new_str(fmt, strlen(fmt), false);
- } else {
- // render exception message and store as .args[0]
- va_list ap;
- vstr_t vstr;
- vstr_init(&vstr, 16);
- va_start(ap, fmt);
- vstr_vprintf(&vstr, fmt, ap);
- va_end(ap);
- o->args->items[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
- }
- }
+ // We have some memory to format the string
+ struct _exc_printer_t exc_pr = {!used_emg_buf, o_str_alloc, 0, o_str_buf};
+ mp_print_t print = {&exc_pr, exc_add_strn};
+ va_list ap;
+ va_start(ap, fmt);
+ mp_vprintf(&print, fmt, ap);
+ va_end(ap);
+ exc_pr.buf[exc_pr.len] = '\0';
+ o_str->len = exc_pr.len;
+ o_str->data = exc_pr.buf;
}
- return MP_OBJ_FROM_PTR(o);
+ // Create the string object and call mp_obj_exception_make_new to create the exception
+ o_str->base.type = &mp_type_str;
+ o_str->hash = qstr_compute_hash(o_str->data, o_str->len);
+ mp_obj_t arg = MP_OBJ_FROM_PTR(o_str);
+ return mp_obj_exception_make_new(exc_type, 1, 0, &arg);
}
// return true if the given object is an exception type
@@ -443,24 +489,46 @@ void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qs
// if memory allocation fails (eg because gc is locked), just return
if (self->traceback_data == NULL) {
- self->traceback_data = m_new_maybe(size_t, 3);
+ self->traceback_data = m_new_maybe(size_t, TRACEBACK_ENTRY_LEN);
if (self->traceback_data == NULL) {
+ #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
+ if (mp_emergency_exception_buf_size >= EMG_TRACEBACK_ALLOC * sizeof(size_t)) {
+ // There is room in the emergency buffer for traceback data
+ size_t *tb = (size_t*)MP_STATE_VM(mp_emergency_exception_buf);
+ self->traceback_data = tb;
+ self->traceback_alloc = EMG_TRACEBACK_ALLOC;
+ } else {
+ // Can't allocate and no room in emergency buffer
+ return;
+ }
+ #else
+ // Can't allocate
return;
+ #endif
+ } else {
+ // Allocated the traceback data on the heap
+ self->traceback_alloc = TRACEBACK_ENTRY_LEN;
}
- self->traceback_alloc = 3;
self->traceback_len = 0;
- } else if (self->traceback_len + 3 > self->traceback_alloc) {
+ } else if (self->traceback_len + TRACEBACK_ENTRY_LEN > self->traceback_alloc) {
+ #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
+ if (self->traceback_data == (size_t*)MP_STATE_VM(mp_emergency_exception_buf)) {
+ // Can't resize the emergency buffer
+ return;
+ }
+ #endif
// be conservative with growing traceback data
- size_t *tb_data = m_renew_maybe(size_t, self->traceback_data, self->traceback_alloc, self->traceback_alloc + 3, true);
+ size_t *tb_data = m_renew_maybe(size_t, self->traceback_data, self->traceback_alloc,
+ self->traceback_alloc + TRACEBACK_ENTRY_LEN, true);
if (tb_data == NULL) {
return;
}
self->traceback_data = tb_data;
- self->traceback_alloc += 3;
+ self->traceback_alloc += TRACEBACK_ENTRY_LEN;
}
size_t *tb_data = &self->traceback_data[self->traceback_len];
- self->traceback_len += 3;
+ self->traceback_len += TRACEBACK_ENTRY_LEN;
tb_data[0] = file;
tb_data[1] = line;
tb_data[2] = block;
diff --git a/py/objfloat.c b/py/objfloat.c
index 15edd810f..743287be6 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -29,9 +29,7 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/parsenum.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#if MICROPY_PY_BUILTINS_FLOAT
@@ -155,18 +153,26 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size
}
}
-STATIC mp_obj_t float_unary_op(mp_uint_t op, mp_obj_t o_in) {
+STATIC mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
mp_float_t val = mp_obj_float_get(o_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(val != 0);
case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(val));
case MP_UNARY_OP_POSITIVE: return o_in;
case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-val);
+ case MP_UNARY_OP_ABS: {
+ // TODO check for NaN etc
+ if (val < 0) {
+ return mp_obj_new_float(-val);
+ } else {
+ return o_in;
+ }
+ }
default: return MP_OBJ_NULL; // op not supported
}
}
-STATIC mp_obj_t float_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_float_t lhs_val = mp_obj_float_get(lhs_in);
#if MICROPY_PY_BUILTINS_COMPLEX
if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
@@ -239,8 +245,12 @@ STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) {
*y = mod;
}
-mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_in) {
- mp_float_t rhs_val = mp_obj_get_float(rhs_in); // can be any type, this function will convert to float (if possible)
+mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t rhs_in) {
+ mp_float_t rhs_val;
+ if (!mp_obj_get_float_maybe(rhs_in, &rhs_val)) {
+ return MP_OBJ_NULL; // op not supported
+ }
+
switch (op) {
case MP_BINARY_OP_ADD:
case MP_BINARY_OP_INPLACE_ADD: lhs_val += rhs_val; break;
@@ -286,6 +296,13 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i
if (lhs_val == 0 && rhs_val < 0) {
goto zero_division_error;
}
+ if (lhs_val < 0 && rhs_val != MICROPY_FLOAT_C_FUN(floor)(rhs_val)) {
+ #if MICROPY_PY_BUILTINS_COMPLEX
+ return mp_obj_complex_binary_op(MP_BINARY_OP_POWER, lhs_val, 0, rhs_in);
+ #else
+ mp_raise_ValueError("complex values not supported");
+ #endif
+ }
lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val);
break;
case MP_BINARY_OP_DIVMOD: {
diff --git a/py/objfun.c b/py/objfun.c
index eaba13129..030b3f7cb 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -28,15 +28,13 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/objtuple.h"
#include "py/objfun.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/bc.h"
#include "py/stackctrl.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#else // don't print debugging info
#define DEBUG_PRINT (0)
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 2f39f3a52..bf0bbb0e6 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -28,8 +28,6 @@
#include <stdlib.h>
#include <assert.h>
-#include "py/nlr.h"
-#include "py/obj.h"
#include "py/runtime.h"
#include "py/bc.h"
#include "py/objgenerator.h"
diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c
index afd6fb22b..ec41c2c5b 100644
--- a/py/objgetitemiter.c
+++ b/py/objgetitemiter.c
@@ -26,7 +26,6 @@
#include <stdlib.h>
-#include "py/nlr.h"
#include "py/runtime.h"
// this is a wrapper object that turns something that has a __getitem__ method into an iterator
diff --git a/py/objint.c b/py/objint.c
index 29d889629..4f2e610a5 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -28,12 +28,10 @@
#include <assert.h>
#include <string.h>
-#include "py/nlr.h"
#include "py/parsenum.h"
#include "py/smallint.h"
#include "py/objint.h"
#include "py/objstr.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/binary.h"
@@ -314,23 +312,13 @@ int mp_obj_int_sign(mp_obj_t self_in) {
}
}
-// This must handle int and bool types, and must raise a
-// TypeError if the argument is not integral
-mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
- mp_int_t val = mp_obj_get_int(self_in);
- if (val < 0) {
- val = -val;
- }
- return MP_OBJ_NEW_SMALL_INT(val);
-}
-
// This is called for operations on SMALL_INT that are not handled by mp_unary_op
-mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
+mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
return MP_OBJ_NULL; // op not supported
}
// This is called for operations on SMALL_INT that are not handled by mp_binary_op
-mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in);
}
@@ -382,7 +370,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
// This dispatcher function is expected to be independent of the implementation of long int
// It handles the extra cases for integer-like arithmetic
-mp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
if (rhs_in == mp_const_false) {
// false acts as 0
return mp_binary_op(op, lhs_in, MP_OBJ_NEW_SMALL_INT(0));
diff --git a/py/objint.h b/py/objint.h
index 394c23714..4b95acde9 100644
--- a/py/objint.h
+++ b/py/objint.h
@@ -57,10 +57,9 @@ mp_int_t mp_obj_int_hash(mp_obj_t self_in);
mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf);
void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf);
int mp_obj_int_sign(mp_obj_t self_in);
-mp_obj_t mp_obj_int_abs(mp_obj_t self_in);
-mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in);
-mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
-mp_obj_t mp_obj_int_binary_op_extra_cases(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
+mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in);
+mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
+mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus);
#endif // MICROPY_INCLUDED_PY_OBJINT_H
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 02c005d2f..2e567c572 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -28,10 +28,8 @@
#include <stdlib.h>
#include <string.h>
-#include "py/nlr.h"
#include "py/smallint.h"
#include "py/objint.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#if MICROPY_PY_BUILTINS_FLOAT
@@ -94,31 +92,7 @@ int mp_obj_int_sign(mp_obj_t self_in) {
}
}
-// This must handle int and bool types, and must raise a
-// TypeError if the argument is not integral
-mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
- if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
- mp_obj_int_t *self = self_in;
- self = mp_obj_new_int_from_ll(self->val);
- if (self->val < 0) {
- // TODO could overflow long long
- self->val = -self->val;
- }
- return self;
- } else {
- mp_int_t val = mp_obj_get_int(self_in);
- if (val == MP_SMALL_INT_MIN) {
- return mp_obj_new_int_from_ll(-val);
- } else {
- if (val < 0) {
- val = -val;
- }
- return MP_OBJ_NEW_SMALL_INT(val);
- }
- }
-}
-
-mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
+mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
mp_obj_int_t *o = o_in;
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->val != 0);
@@ -130,11 +104,21 @@ mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
case MP_UNARY_OP_POSITIVE: return o_in;
case MP_UNARY_OP_NEGATIVE: return mp_obj_new_int_from_ll(-o->val);
case MP_UNARY_OP_INVERT: return mp_obj_new_int_from_ll(~o->val);
+ case MP_UNARY_OP_ABS: {
+ mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in);
+ if (self->val >= 0) {
+ return o_in;
+ }
+ self = mp_obj_new_int_from_ll(self->val);
+ // TODO could overflow long long
+ self->val = -self->val;
+ return MP_OBJ_FROM_PTR(self);
+ }
default: return MP_OBJ_NULL; // op not supported
}
}
-mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
long long lhs_val;
long long rhs_val;
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 0791a8af2..7b5cb0b9d 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -28,11 +28,9 @@
#include <stdio.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/parsenumbase.h"
#include "py/smallint.h"
#include "py/objint.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#if MICROPY_PY_BUILTINS_FLOAT
@@ -141,28 +139,7 @@ int mp_obj_int_sign(mp_obj_t self_in) {
}
}
-// This must handle int and bool types, and must raise a
-// TypeError if the argument is not integral
-mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
- if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
- mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_int_t *self2 = mp_obj_int_new_mpz();
- mpz_abs_inpl(&self2->mpz, &self->mpz);
- return MP_OBJ_FROM_PTR(self2);
- } else {
- mp_int_t val = mp_obj_get_int(self_in);
- if (val == MP_SMALL_INT_MIN) {
- return mp_obj_new_int_from_ll(-val);
- } else {
- if (val < 0) {
- val = -val;
- }
- return MP_OBJ_NEW_SMALL_INT(val);
- }
- }
-}
-
-mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
+mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) {
mp_obj_int_t *o = MP_OBJ_TO_PTR(o_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(!mpz_is_zero(&o->mpz));
@@ -170,11 +147,20 @@ mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
case MP_UNARY_OP_POSITIVE: return o_in;
case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_neg_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); }
case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_not_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); }
+ case MP_UNARY_OP_ABS: {
+ mp_obj_int_t *self = MP_OBJ_TO_PTR(o_in);
+ if (self->mpz.neg == 0) {
+ return o_in;
+ }
+ mp_obj_int_t *self2 = mp_obj_int_new_mpz();
+ mpz_abs_inpl(&self2->mpz, &self->mpz);
+ return MP_OBJ_FROM_PTR(self2);
+ }
default: return MP_OBJ_NULL; // op not supported
}
}
-mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
const mpz_t *zlhs;
const mpz_t *zrhs;
mpz_t z_int;
@@ -221,7 +207,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return mp_obj_new_float(flhs / frhs);
#endif
- } else if (op <= MP_BINARY_OP_INPLACE_POWER) {
+ } else if (op >= MP_BINARY_OP_INPLACE_OR) {
mp_obj_int_t *res = mp_obj_int_new_mpz();
switch (op) {
diff --git a/py/objlist.c b/py/objlist.c
index ba1c50677..bc22d9fc3 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -27,9 +27,7 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/objlist.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
@@ -87,28 +85,22 @@ STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_
}
}
-// Don't pass MP_BINARY_OP_NOT_EQUAL here
-STATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {
- mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
- if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) {
- return false;
- }
- mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
- mp_obj_list_t *another = MP_OBJ_TO_PTR(another_in);
-
- return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
-}
-
-STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) {
+STATIC mp_obj_t list_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len);
+ #if MICROPY_PY_SYS_GETSIZEOF
+ case MP_UNARY_OP_SIZEOF: {
+ size_t sz = sizeof(*self) + sizeof(mp_obj_t) * self->alloc;
+ return MP_OBJ_NEW_SMALL_INT(sz);
+ }
+ #endif
default: return MP_OBJ_NULL; // op not supported
}
}
-STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
+STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_list_t *o = MP_OBJ_TO_PTR(lhs);
switch (op) {
case MP_BINARY_OP_ADD: {
@@ -140,8 +132,18 @@ STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
case MP_BINARY_OP_LESS:
case MP_BINARY_OP_LESS_EQUAL:
case MP_BINARY_OP_MORE:
- case MP_BINARY_OP_MORE_EQUAL:
- return mp_obj_new_bool(list_cmp_helper(op, lhs, rhs));
+ case MP_BINARY_OP_MORE_EQUAL: {
+ if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
+ if (op == MP_BINARY_OP_EQUAL) {
+ return mp_const_false;
+ }
+ return MP_OBJ_NULL; // op not supported
+ }
+
+ mp_obj_list_t *another = MP_OBJ_TO_PTR(rhs);
+ bool res = mp_seq_cmp_objs(op, o->items, o->len, another->items, another->len);
+ return mp_obj_new_bool(res);
+ }
default:
return MP_OBJ_NULL; // op not supported
@@ -156,7 +158,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
- mp_not_implemented("");
+ mp_raise_NotImplementedError("");
}
mp_int_t len_adj = slice.start - slice.stop;
@@ -196,7 +198,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_get_array(value, &value_len, &value_items);
mp_bound_slice_t slice_out;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
- mp_not_implemented("");
+ mp_raise_NotImplementedError("");
}
mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start);
//printf("Len adj: %d\n", len_adj);
diff --git a/py/objmodule.c b/py/objmodule.c
index fc8507c27..f9363e379 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -27,8 +27,6 @@
#include <stdlib.h>
#include <assert.h>
-#include "py/mpstate.h"
-#include "py/nlr.h"
#include "py/objmodule.h"
#include "py/runtime.h"
#include "py/builtin.h"
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index fb9d9f02c..38daccdf2 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -27,7 +27,6 @@
#include <string.h>
-#include "py/nlr.h"
#include "py/objtuple.h"
#include "py/runtime.h"
#include "py/objstr.h"
diff --git a/py/objnone.c b/py/objnone.c
index cd7319bec..da1031835 100644
--- a/py/objnone.c
+++ b/py/objnone.c
@@ -26,9 +26,7 @@
#include <stdlib.h>
-#include "py/nlr.h"
#include "py/obj.h"
-#include "py/runtime0.h"
typedef struct _mp_obj_none_t {
mp_obj_base_t base;
diff --git a/py/objpolyiter.c b/py/objpolyiter.c
index 61bd1e0ac..01880bff9 100644
--- a/py/objpolyiter.c
+++ b/py/objpolyiter.c
@@ -26,7 +26,6 @@
#include <stdlib.h>
-#include "py/nlr.h"
#include "py/runtime.h"
// This is universal iterator type which calls "iternext" method stored in
diff --git a/py/objproperty.c b/py/objproperty.c
index 0934fad05..b66d24a11 100644
--- a/py/objproperty.c
+++ b/py/objproperty.c
@@ -27,7 +27,6 @@
#include <stdlib.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/runtime.h"
#if MICROPY_PY_BUILTINS_PROPERTY
diff --git a/py/objrange.c b/py/objrange.c
index 33b07a9d4..3874adb11 100644
--- a/py/objrange.c
+++ b/py/objrange.c
@@ -26,8 +26,6 @@
#include <stdlib.h>
-#include "py/nlr.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
/******************************************************************************/
@@ -130,7 +128,7 @@ STATIC mp_int_t range_len(mp_obj_range_t *self) {
return len;
}
-STATIC mp_obj_t range_unary_op(mp_uint_t op, mp_obj_t self_in) {
+STATIC mp_obj_t range_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t len = range_len(self);
switch (op) {
diff --git a/py/objreversed.c b/py/objreversed.c
index a596a2fde..e498b553d 100644
--- a/py/objreversed.c
+++ b/py/objreversed.c
@@ -27,7 +27,6 @@
#include <stdlib.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/runtime.h"
#if MICROPY_PY_BUILTINS_REVERSED
diff --git a/py/objset.c b/py/objset.c
index 376439b73..6ed15c791 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2013-2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,9 +28,7 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/runtime.h"
-#include "py/runtime0.h"
#include "py/builtin.h"
#if MICROPY_PY_BUILTINS_SET
@@ -57,23 +55,13 @@ STATIC bool is_set_or_frozenset(mp_obj_t o) {
;
}
+// This macro is shorthand for mp_check_self to verify the argument is a set.
+#define check_set(o) mp_check_self(MP_OBJ_IS_TYPE(o, &mp_type_set))
+
// This macro is shorthand for mp_check_self to verify the argument is a
// set or frozenset for methods that operate on both of these types.
#define check_set_or_frozenset(o) mp_check_self(is_set_or_frozenset(o))
-// This function is used to verify the argument for methods that modify
-// the set object, and raises an exception if the arg is a frozenset.
-STATIC void check_set(mp_obj_t o) {
- #if MICROPY_PY_BUILTINS_FROZENSET
- if (MP_OBJ_IS_TYPE(o, &mp_type_frozenset)) {
- // Mutable method called on frozenset; emulate CPython behavior, eg:
- // AttributeError: 'frozenset' object has no attribute 'add'
- mp_raise_msg(&mp_type_AttributeError, "'frozenset' has no such attribute");
- }
- #endif
- mp_check_self(MP_OBJ_IS_TYPE(o, &mp_type_set));
-}
-
STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
@@ -188,26 +176,16 @@ STATIC mp_obj_t set_clear(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear);
-STATIC mp_obj_t set_copy_as_mutable(mp_obj_t self_in) {
+STATIC mp_obj_t set_copy(mp_obj_t self_in) {
+ check_set_or_frozenset(self_in);
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
-
mp_obj_set_t *other = m_new_obj(mp_obj_set_t);
- other->base.type = &mp_type_set;
+ other->base.type = self->base.type;
mp_set_init(&other->set, self->set.alloc);
other->set.used = self->set.used;
memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t));
-
return MP_OBJ_FROM_PTR(other);
}
-
-STATIC mp_obj_t set_copy(mp_obj_t self_in) {
- check_set_or_frozenset(self_in);
-
- mp_obj_t other = set_copy_as_mutable(self_in);
- ((mp_obj_base_t*)MP_OBJ_TO_PTR(other))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_in))->type;
-
- return other;
-}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy);
STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) {
@@ -224,25 +202,23 @@ STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) {
check_set(args[0]);
self = args[0];
} else {
- check_set_or_frozenset(args[0]);
- self = set_copy_as_mutable(args[0]);
+ self = set_copy(args[0]);
}
-
for (size_t i = 1; i < n_args; i++) {
mp_obj_t other = args[i];
if (self == other) {
set_clear(self);
} else {
+ mp_set_t *self_set = &((mp_obj_set_t*)MP_OBJ_TO_PTR(self))->set;
mp_obj_t iter = mp_getiter(other, NULL);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
- set_discard(self, next);
+ mp_set_lookup(self_set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
}
}
}
- ((mp_obj_base_t*)MP_OBJ_TO_PTR(self))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]))->type;
return self;
}
@@ -333,16 +309,16 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
other = MP_OBJ_TO_PTR(set_make_new(&mp_type_set, 1, 0, &other_in));
cleanup_other = true;
}
- bool out = true;
+ mp_obj_t out = mp_const_true;
if (proper && self->set.used == other->set.used) {
- out = false;
+ out = mp_const_false;
} else {
mp_obj_iter_buf_t iter_buf;
mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self), &iter_buf);
mp_obj_t next;
while ((next = set_it_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {
- out = false;
+ out = mp_const_false;
break;
}
}
@@ -354,7 +330,7 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
if (cleanup_other) {
set_clear(MP_OBJ_FROM_PTR(other));
}
- return mp_obj_new_bool(out);
+ return out;
}
STATIC mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) {
return set_issubset_internal(self_in, other_in, false);
@@ -402,14 +378,14 @@ STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) {
check_set(self_in);
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) {
- nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
+ nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, item));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove);
STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) {
- check_set(self_in);
+ check_set_or_frozenset(self_in); // can be frozenset due to call from set_symmetric_difference
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_t iter = mp_getiter(other_in, NULL);
mp_obj_t next;
@@ -421,10 +397,8 @@ STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update);
STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) {
- check_set_or_frozenset(self_in);
- mp_obj_t self_out = set_copy_as_mutable(self_in);
+ mp_obj_t self_out = set_copy(self_in);
set_symmetric_difference_update(self_out, other_in);
- ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_out))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_in))->type;
return self_out;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference);
@@ -455,7 +429,7 @@ STATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union);
-STATIC mp_obj_t set_unary_op(mp_uint_t op, mp_obj_t self_in) {
+STATIC mp_obj_t set_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->set.used != 0);
@@ -480,13 +454,17 @@ STATIC mp_obj_t set_unary_op(mp_uint_t op, mp_obj_t self_in) {
}
}
-STATIC mp_obj_t set_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
+STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_t args[] = {lhs, rhs};
#if MICROPY_PY_BUILTINS_FROZENSET
bool update = MP_OBJ_IS_TYPE(lhs, &mp_type_set);
#else
bool update = true;
#endif
+ if (op != MP_BINARY_OP_IN && !is_set_or_frozenset(rhs)) {
+ // For all ops except containment the RHS must be a set/frozenset
+ return MP_OBJ_NULL;
+ }
switch (op) {
case MP_BINARY_OP_OR:
return set_union(lhs, rhs);
@@ -578,6 +556,19 @@ const mp_obj_type_t mp_type_set = {
};
#if MICROPY_PY_BUILTINS_FROZENSET
+STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&set_copy_obj) },
+ { MP_ROM_QSTR(MP_QSTR_difference), MP_ROM_PTR(&set_diff_obj) },
+ { MP_ROM_QSTR(MP_QSTR_intersection), MP_ROM_PTR(&set_intersect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_isdisjoint), MP_ROM_PTR(&set_isdisjoint_obj) },
+ { MP_ROM_QSTR(MP_QSTR_issubset), MP_ROM_PTR(&set_issubset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_issuperset), MP_ROM_PTR(&set_issuperset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_symmetric_difference), MP_ROM_PTR(&set_symmetric_difference_obj) },
+ { MP_ROM_QSTR(MP_QSTR_union), MP_ROM_PTR(&set_union_obj) },
+ { MP_ROM_QSTR(MP_QSTR___contains__), MP_ROM_PTR(&mp_op_contains_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table);
+
const mp_obj_type_t mp_type_frozenset = {
{ &mp_type_type },
.name = MP_QSTR_frozenset,
@@ -586,7 +577,7 @@ const mp_obj_type_t mp_type_frozenset = {
.unary_op = set_unary_op,
.binary_op = set_binary_op,
.getiter = set_getiter,
- .locals_dict = (mp_obj_dict_t*)&set_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&frozenset_locals_dict,
};
#endif
diff --git a/py/objsingleton.c b/py/objsingleton.c
index ea72ae38c..67535391e 100644
--- a/py/objsingleton.c
+++ b/py/objsingleton.c
@@ -27,9 +27,7 @@
#include <stdlib.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/obj.h"
-#include "py/runtime0.h"
/******************************************************************************/
/* singleton objects defined by Python */
diff --git a/py/objslice.c b/py/objslice.c
index 358c44d06..de996d831 100644
--- a/py/objslice.c
+++ b/py/objslice.c
@@ -27,9 +27,7 @@
#include <stdlib.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/obj.h"
-#include "py/runtime0.h"
/******************************************************************************/
/* slice object */
diff --git a/py/objstr.c b/py/objstr.c
index ddad7d3bd..51da7a418 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -28,11 +28,9 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/unicode.h"
#include "py/objstr.h"
#include "py/objlist.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
@@ -161,6 +159,11 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
if (str_hash == 0) {
str_hash = qstr_compute_hash(str_data, str_len);
}
+ #if MICROPY_PY_BUILTINS_STR_UNICODE_CHECK
+ if (!utf8_check(str_data, str_len)) {
+ mp_raise_msg(&mp_type_UnicodeError, NULL);
+ }
+ #endif
mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(type, NULL, str_len));
o->data = str_data;
o->hash = str_hash;
@@ -168,6 +171,11 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
} else {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
+ #if MICROPY_PY_BUILTINS_STR_UNICODE_CHECK
+ if (!utf8_check(bufinfo.buf, bufinfo.len)) {
+ mp_raise_msg(&mp_type_UnicodeError, NULL);
+ }
+ #endif
return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
}
}
@@ -280,7 +288,7 @@ const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle,
// Note: this function is used to check if an object is a str or bytes, which
// works because both those types use it as their binary_op method. Revisit
// MP_OBJ_IS_STR_OR_BYTES if this fact changes.
-mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// check for modulo
if (op == MP_BINARY_OP_MODULO) {
mp_obj_t *args = &rhs_in;
@@ -347,8 +355,9 @@ mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
rhs_data = bufinfo.buf;
rhs_len = bufinfo.len;
} else {
- // incompatible types
- return MP_OBJ_NULL; // op not supported
+ // LHS is str and RHS has an incompatible type
+ // (except if operation is EQUAL, but that's handled by mp_obj_equal)
+ bad_implicit_conversion(rhs_in);
}
switch (op) {
@@ -379,9 +388,10 @@ mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
case MP_BINARY_OP_MORE:
case MP_BINARY_OP_MORE_EQUAL:
return mp_obj_new_bool(mp_seq_cmp_bytes(op, lhs_data, lhs_len, rhs_data, rhs_len));
- }
- return MP_OBJ_NULL; // op not supported
+ default:
+ return MP_OBJ_NULL; // op not supported
+ }
}
#if !MICROPY_PY_BUILTINS_STR_UNICODE
@@ -403,7 +413,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self_len, index, &slice)) {
- mp_not_implemented("only slices with step=1 (aka None) are supported");
+ mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported");
}
return mp_obj_new_str_of_type(type, self_data + slice.start, slice.stop - slice.start);
}
@@ -617,7 +627,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) {
mp_int_t idx = splits;
if (sep == mp_const_none) {
- mp_not_implemented("rsplit(None,n)");
+ mp_raise_NotImplementedError("rsplit(None,n)");
} else {
size_t sep_len;
const char *sep_str = mp_obj_str_get_data(sep, &sep_len);
@@ -725,7 +735,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex);
STATIC mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
GET_STR_DATA_LEN(args[0], str, str_len);
- GET_STR_DATA_LEN(args[1], prefix, prefix_len);
+ size_t prefix_len;
+ const char *prefix = mp_obj_str_get_data(args[1], &prefix_len);
const byte *start = str;
if (n_args > 2) {
start = str_index_to_ptr(self_type, str, str_len, args[2], true);
@@ -739,9 +750,10 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
STATIC mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) {
GET_STR_DATA_LEN(args[0], str, str_len);
- GET_STR_DATA_LEN(args[1], suffix, suffix_len);
+ size_t suffix_len;
+ const char *suffix = mp_obj_str_get_data(args[1], &suffix_len);
if (n_args > 2) {
- mp_not_implemented("start/end indices");
+ mp_raise_NotImplementedError("start/end indices");
}
if (suffix_len > str_len) {
@@ -763,7 +775,7 @@ STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
chars_to_del = whitespace;
- chars_to_del_len = sizeof(whitespace);
+ chars_to_del_len = sizeof(whitespace) - 1;
} else {
if (mp_obj_get_type(args[1]) != self_type) {
bad_implicit_conversion(args[1]);
@@ -1043,7 +1055,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
arg = key_elem->value;
}
if (field_name < field_name_top) {
- mp_not_implemented("attributes not supported yet");
+ mp_raise_NotImplementedError("attributes not supported yet");
}
} else {
if (*arg_i < 0) {
@@ -1961,8 +1973,8 @@ const mp_obj_type_t mp_type_bytes = {
.locals_dict = (mp_obj_dict_t*)&str8_locals_dict,
};
-// the zero-length bytes
-const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, NULL};
+// The zero-length bytes object, with data that includes a null-terminating byte
+const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, (const byte*)""};
// Create a str/bytes object using the given data. New memory is allocated and
// the data is copied across.
diff --git a/py/objstr.h b/py/objstr.h
index 3aef8c68e..82501a763 100644
--- a/py/objstr.h
+++ b/py/objstr.h
@@ -67,7 +67,7 @@ mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len);
-mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
+mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,
diff --git a/py/objstringio.c b/py/objstringio.c
index 046d32580..5c50aa317 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -28,7 +28,6 @@
#include <stdio.h>
#include <string.h>
-#include "py/nlr.h"
#include "py/objstr.h"
#include "py/objstringio.h"
#include "py/runtime.h"
@@ -118,15 +117,28 @@ STATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg,
struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg;
mp_uint_t ref = 0;
switch (s->whence) {
- case 1: // SEEK_CUR
+ case MP_SEEK_CUR:
ref = o->pos;
break;
- case 2: // SEEK_END
+ case MP_SEEK_END:
ref = o->vstr->len;
break;
}
- o->pos = ref + s->offset;
- s->offset = o->pos;
+ mp_uint_t new_pos = ref + s->offset;
+
+ // For MP_SEEK_SET, offset is unsigned
+ if (s->whence != MP_SEEK_SET && s->offset < 0) {
+ if (new_pos > ref) {
+ // Negative offset from SEEK_CUR or SEEK_END went past 0.
+ // CPython sets position to 0, POSIX returns an EINVAL error
+ new_pos = 0;
+ }
+ } else if (new_pos < ref) {
+ // positive offset went beyond the limit of mp_uint_t
+ *errcode = MP_EINVAL; // replace with MP_EOVERFLOW when defined
+ return MP_STREAM_ERROR;
+ }
+ s->offset = o->pos = new_pos;
return 0;
}
case MP_STREAM_FLUSH:
diff --git a/py/objstrunicode.c b/py/objstrunicode.c
index 0cf791ff7..29f7695b7 100644
--- a/py/objstrunicode.c
+++ b/py/objstrunicode.c
@@ -28,10 +28,8 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/objstr.h"
#include "py/objlist.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#if MICROPY_PY_BUILTINS_STR_UNICODE
@@ -100,7 +98,7 @@ STATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
}
}
-STATIC mp_obj_t uni_unary_op(mp_uint_t op, mp_obj_t self_in) {
+STATIC mp_obj_t uni_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
GET_STR_DATA_LEN(self_in, str_data, str_len);
switch (op) {
case MP_UNARY_OP_BOOL:
@@ -188,7 +186,7 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_t ostart, ostop, ostep;
mp_obj_slice_get(index, &ostart, &ostop, &ostep);
if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
- mp_not_implemented("only slices with step=1 (aka None) are supported");
+ mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported");
}
const byte *pstart, *pstop;
diff --git a/py/objtuple.c b/py/objtuple.c
index 0b05755fb..34b7664eb 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -27,9 +27,7 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/objtuple.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
/******************************************************************************/
@@ -101,7 +99,7 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg
}
// Don't pass MP_BINARY_OP_NOT_EQUAL here
-STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {
+STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) {
// type check is done on getiter method to allow tuple, namedtuple, attrtuple
mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter);
mp_obj_type_t *another_type = mp_obj_get_type(another_in);
@@ -110,15 +108,18 @@ STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in
// Slow path for user subclasses
another_in = mp_instance_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple));
if (another_in == MP_OBJ_NULL) {
- return false;
+ if (op == MP_BINARY_OP_EQUAL) {
+ return mp_const_false;
+ }
+ return MP_OBJ_NULL;
}
}
mp_obj_tuple_t *another = MP_OBJ_TO_PTR(another_in);
- return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
+ return mp_obj_new_bool(mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len));
}
-mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) {
+mp_obj_t mp_obj_tuple_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);
@@ -135,7 +136,7 @@ mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) {
}
}
-mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
+mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_tuple_t *o = MP_OBJ_TO_PTR(lhs);
switch (op) {
case MP_BINARY_OP_ADD:
@@ -148,7 +149,8 @@ mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
return MP_OBJ_FROM_PTR(s);
}
- case MP_BINARY_OP_MULTIPLY: {
+ case MP_BINARY_OP_MULTIPLY:
+ case MP_BINARY_OP_INPLACE_MULTIPLY: {
mp_int_t n;
if (!mp_obj_get_int_maybe(rhs, &n)) {
return MP_OBJ_NULL; // op not supported
@@ -165,7 +167,7 @@ mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
case MP_BINARY_OP_LESS_EQUAL:
case MP_BINARY_OP_MORE:
case MP_BINARY_OP_MORE_EQUAL:
- return mp_obj_new_bool(tuple_cmp_helper(op, lhs, rhs));
+ return tuple_cmp_helper(op, lhs, rhs);
default:
return MP_OBJ_NULL; // op not supported
@@ -180,7 +182,7 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
- mp_not_implemented("only slices with step=1 (aka None) are supported");
+ mp_raise_NotImplementedError("only slices with step=1 (aka None) are supported");
}
mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(slice.stop - slice.start, NULL));
mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
diff --git a/py/objtuple.h b/py/objtuple.h
index 05c6490fe..74cde88d3 100644
--- a/py/objtuple.h
+++ b/py/objtuple.h
@@ -41,8 +41,8 @@ typedef struct _mp_rom_obj_tuple_t {
} mp_rom_obj_tuple_t;
void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind);
-mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in);
-mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
+mp_obj_t mp_obj_tuple_unary_op(mp_unary_op_t op, mp_obj_t self_in);
+mp_obj_t mp_obj_tuple_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value);
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf);
diff --git a/py/objtype.c b/py/objtype.c
index a258915f3..d7f409e30 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -30,12 +30,10 @@
#include <string.h>
#include <assert.h>
-#include "py/nlr.h"
#include "py/objtype.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
@@ -113,13 +111,15 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
assert(lookup->dest[0] == MP_OBJ_NULL);
assert(lookup->dest[1] == MP_OBJ_NULL);
for (;;) {
+ DEBUG_printf("mp_obj_class_lookup: Looking up %s in %s\n", qstr_str(lookup->attr), qstr_str(type->name));
// Optimize special method lookup for native types
// This avoids extra method_name => slot lookup. On the other hand,
// this should not be applied to class types, as will result in extra
// lookup either.
if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) {
if (*(void**)((char*)type + lookup->meth_offset) != NULL) {
- DEBUG_printf("mp_obj_class_lookup: matched special meth slot for %s\n", qstr_str(lookup->attr));
+ DEBUG_printf("mp_obj_class_lookup: Matched special meth slot (off=%d) for %s\n",
+ lookup->meth_offset, qstr_str(lookup->attr));
lookup->dest[0] = MP_OBJ_SENTINEL;
return;
}
@@ -150,7 +150,8 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
#if DEBUG_PRINT
printf("mp_obj_class_lookup: Returning: ");
mp_obj_print(lookup->dest[0], PRINT_REPR); printf(" ");
- mp_obj_print(lookup->dest[1], PRINT_REPR); printf("\n");
+ // Don't try to repr() lookup->dest[1], as we can be called recursively
+ printf("<%s @%p>\n", mp_obj_get_type_str(lookup->dest[1]), lookup->dest[1]);
#endif
return;
}
@@ -169,6 +170,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
// attribute not found, keep searching base classes
if (type->parent == NULL) {
+ DEBUG_printf("mp_obj_class_lookup: No more parents\n");
return;
} else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
const mp_obj_tuple_t *parent_tuple = type->parent;
@@ -251,9 +253,9 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size
mp_obj_instance_t *o = MP_OBJ_TO_PTR(mp_obj_new_instance(self, num_native_bases));
- // This executes only "__new__" part of obejection creation.
- // TODO: This won't work will for classes with native bases.
- // TODO: This is hack, should be resolved along the lines of
+ // This executes only "__new__" part of instance creation.
+ // TODO: This won't work well for classes with native bases.
+ // TODO: This is a hack, should be resolved along the lines of
// https://github.com/micropython/micropython/issues/606#issuecomment-43685883
if (n_args == 1 && *args == MP_OBJ_SENTINEL) {
return MP_OBJ_FROM_PTR(o);
@@ -330,7 +332,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size
return MP_OBJ_FROM_PTR(o);
}
-const qstr mp_unary_op_method_name[] = {
+const uint16_t mp_unary_op_method_name[] = {
[MP_UNARY_OP_BOOL] = MP_QSTR___bool__,
[MP_UNARY_OP_LEN] = MP_QSTR___len__,
[MP_UNARY_OP_HASH] = MP_QSTR___hash__,
@@ -339,11 +341,27 @@ const qstr mp_unary_op_method_name[] = {
[MP_UNARY_OP_NEGATIVE] = MP_QSTR___neg__,
[MP_UNARY_OP_INVERT] = MP_QSTR___invert__,
#endif
+ #if MICROPY_PY_SYS_GETSIZEOF
+ [MP_UNARY_OP_SIZEOF] = MP_QSTR_getsizeof,
+ #endif
[MP_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this, used to make sure array has full size
};
-STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) {
+STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
+
+ #if MICROPY_PY_SYS_GETSIZEOF
+ if (MP_UNLIKELY(op == MP_UNARY_OP_SIZEOF)) {
+ // TODO: This doesn't count inherited objects (self->subobj)
+ const mp_obj_type_t *native_base;
+ size_t num_native_bases = instance_count_native_bases(mp_obj_get_type(self_in), &native_base);
+
+ size_t sz = sizeof(*self) + sizeof(*self->subobj) * num_native_bases
+ + sizeof(*self->members.table) * self->members.alloc;
+ return MP_OBJ_NEW_SMALL_INT(sz);
+ }
+ #endif
+
qstr op_name = mp_unary_op_method_name[op];
/* Still try to lookup native slot
if (op_name == 0) {
@@ -388,7 +406,7 @@ STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) {
}
}
-const qstr mp_binary_op_method_name[] = {
+const uint16_t mp_binary_op_method_name[] = {
/*
MP_BINARY_OP_OR,
MP_BINARY_OP_XOR,
@@ -421,6 +439,13 @@ const qstr mp_binary_op_method_name[] = {
MP_BINARY_OP_INPLACE_TRUE_DIVIDE,
MP_BINARY_OP_INPLACE_MODULO,
MP_BINARY_OP_INPLACE_POWER,*/
+
+ #if MICROPY_PY_REVERSE_SPECIAL_METHODS
+ [MP_BINARY_OP_REVERSE_ADD] = MP_QSTR___radd__,
+ [MP_BINARY_OP_REVERSE_SUBTRACT] = MP_QSTR___rsub__,
+ [MP_BINARY_OP_REVERSE_MULTIPLY] = MP_QSTR___rmul__,
+ #endif
+
[MP_BINARY_OP_LESS] = MP_QSTR___lt__,
[MP_BINARY_OP_MORE] = MP_QSTR___gt__,
[MP_BINARY_OP_EQUAL] = MP_QSTR___eq__,
@@ -433,13 +458,14 @@ const qstr mp_binary_op_method_name[] = {
/*
MP_BINARY_OP_IS,
*/
- [MP_BINARY_OP_EXCEPTION_MATCH] = MP_QSTR_, // not implemented, used to make sure array has full size
+ [MP_BINARY_OP_LAST] = 0, // used to make sure array has full size, TODO: FIXME
};
-STATIC mp_obj_t instance_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
+STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// Note: For ducktyping, CPython does not look in the instance members or use
// __getattr__ or __getattribute__. It only looks in the class dictionary.
mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in);
+retry:;
qstr op_name = mp_binary_op_method_name[op];
/* Still try to lookup native slot
if (op_name == 0) {
@@ -455,14 +481,36 @@ STATIC mp_obj_t instance_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
.is_type = false,
};
mp_obj_class_lookup(&lookup, lhs->base.type);
+
+ mp_obj_t res;
if (dest[0] == MP_OBJ_SENTINEL) {
- return mp_binary_op(op, lhs->subobj[0], rhs_in);
+ res = mp_binary_op(op, lhs->subobj[0], rhs_in);
} else if (dest[0] != MP_OBJ_NULL) {
dest[2] = rhs_in;
- return mp_call_method_n_kw(1, 0, dest);
+ res = mp_call_method_n_kw(1, 0, dest);
} else {
+ // If this was an inplace method, fallback to normal method
+ // https://docs.python.org/3/reference/datamodel.html#object.__iadd__ :
+ // "If a specific method is not defined, the augmented assignment
+ // falls back to the normal methods."
+ if (op >= MP_BINARY_OP_INPLACE_OR && op <= MP_BINARY_OP_INPLACE_POWER) {
+ op -= MP_BINARY_OP_INPLACE_OR - MP_BINARY_OP_OR;
+ goto retry;
+ }
+ return MP_OBJ_NULL; // op not supported
+ }
+
+ #if MICROPY_PY_BUILTINS_NOTIMPLEMENTED
+ // NotImplemented means "try other fallbacks (like calling __rop__
+ // instead of __op__) and if nothing works, raise TypeError". As
+ // MicroPython doesn't implement any fallbacks, signal to raise
+ // TypeError right away.
+ if (res == mp_const_notimplemented) {
return MP_OBJ_NULL; // op not supported
}
+ #endif
+
+ return res;
}
STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
diff --git a/py/parse.c b/py/parse.c
index e399aac53..8c51b0349 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -31,11 +31,9 @@
#include <assert.h>
#include <string.h>
-#include "py/nlr.h"
#include "py/lexer.h"
#include "py/parse.h"
#include "py/parsenum.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/objint.h"
#include "py/objstr.h"
diff --git a/py/persistentcode.c b/py/persistentcode.c
index 2fa8c1df0..d8b17c7e6 100644
--- a/py/persistentcode.c
+++ b/py/persistentcode.c
@@ -99,7 +99,6 @@ STATIC void extract_prelude(const byte **ip, const byte **ip2, bytecode_prelude_
#if MICROPY_PERSISTENT_CODE_LOAD
#include "py/parsenum.h"
-#include "py/bc0.h"
STATIC int read_byte(mp_reader_t *reader) {
return reader->readbyte(reader->data);
@@ -374,7 +373,7 @@ void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) {
// here we define mp_raw_code_save_file depending on the port
// TODO abstract this away properly
-#if defined(__i386__) || defined(__x86_64__) || (defined(__arm__) && (defined(__unix__)))
+#if defined(__i386__) || defined(__x86_64__) || defined(__unix__)
#include <unistd.h>
#include <sys/stat.h>
diff --git a/py/py.mk b/py/py.mk
index 02f2df8e1..f5faad182 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -22,13 +22,13 @@ CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\"
ifeq ($(MICROPY_PY_USSL),1)
CFLAGS_MOD += -DMICROPY_PY_USSL=1
ifeq ($(MICROPY_SSL_AXTLS),1)
-CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I../lib/axtls/ssl -I../lib/axtls/crypto -I../lib/axtls/config
+CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I$(TOP)/lib/axtls/ssl -I$(TOP)/lib/axtls/crypto -I$(TOP)/lib/axtls/config
LDFLAGS_MOD += -Lbuild -laxtls
else ifeq ($(MICROPY_SSL_MBEDTLS),1)
# Can be overridden by ports which have "builtin" mbedTLS
-MICROPY_SSL_MBEDTLS_INCLUDE ?= ../lib/mbedtls/include
+MICROPY_SSL_MBEDTLS_INCLUDE ?= $(TOP)/lib/mbedtls/include
CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(MICROPY_SSL_MBEDTLS_INCLUDE)
-LDFLAGS_MOD += -L../lib/mbedtls/library -lmbedx509 -lmbedtls -lmbedcrypto
+LDFLAGS_MOD += -L$(TOP)/lib/mbedtls/library -lmbedx509 -lmbedtls -lmbedcrypto
endif
endif
@@ -38,7 +38,7 @@ endif
ifeq ($(MICROPY_PY_LWIP),1)
LWIP_DIR = lib/lwip/src
-INC += -I../lib/lwip/src/include -I../lib/lwip/src/include/ipv4 -I../extmod/lwip-include
+INC += -I$(TOP)/lib/lwip/src/include -I$(TOP)/lib/lwip/src/include/ipv4 -I$(TOP)/extmod/lwip-include
CFLAGS_MOD += -DMICROPY_PY_LWIP=1
SRC_MOD += extmod/modlwip.c lib/netutils/netutils.c
SRC_MOD += $(addprefix $(LWIP_DIR)/,\
@@ -74,8 +74,8 @@ endif
ifeq ($(MICROPY_PY_BTREE),1)
BTREE_DIR = lib/berkeley-db-1.xx
-BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ -Dvirt_fd_t=mp_obj_t "-DVIRT_FD_T_HEADER=<py/obj.h>"
-INC += -I../$(BTREE_DIR)/PORT/include
+BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ -Dvirt_fd_t=mp_obj_t "-DVIRT_FD_T_HEADER=<py/obj.h>" $(BTREE_DEFS_EXTRA)
+INC += -I$(TOP)/$(BTREE_DIR)/PORT/include
SRC_MOD += extmod/modbtree.c
SRC_MOD += $(addprefix $(BTREE_DIR)/,\
btree/bt_close.c \
diff --git a/py/qstr.c b/py/qstr.c
index fdb38f1de..95c9b6835 100644
--- a/py/qstr.c
+++ b/py/qstr.c
@@ -36,7 +36,7 @@
// ultimately we will replace this with a static hash table of some kind
// also probably need to include the length in the string data, to allow null bytes in the string
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
diff --git a/py/qstrdefs.h b/py/qstrdefs.h
index 9375b9101..4ded5be08 100644
--- a/py/qstrdefs.h
+++ b/py/qstrdefs.h
@@ -51,11 +51,3 @@ Q(<genexpr>)
Q(<string>)
Q(<stdin>)
Q(utf-8)
-
-// The following qstrings not referenced from anywhere in the sources
-Q(__locals__)
-Q(BufferError)
-Q(FileExistsError)
-Q(FileNotFoundError)
-Q(FloatingPointError)
-Q(UnboundLocalError)
diff --git a/py/runtime.c b/py/runtime.c
index 6a0db007e..069548deb 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -28,8 +28,6 @@
#include <string.h>
#include <assert.h>
-#include "py/mpstate.h"
-#include "py/nlr.h"
#include "py/parsenum.h"
#include "py/compile.h"
#include "py/objstr.h"
@@ -38,13 +36,12 @@
#include "py/objmodule.h"
#include "py/objgenerator.h"
#include "py/smallint.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/stackctrl.h"
#include "py/gc.h"
-#if 0 // print debugging info
+#if MICROPY_DEBUG_VERBOSE // print debugging info
#define DEBUG_PRINT (1)
#define DEBUG_printf DEBUG_printf
#define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
@@ -209,7 +206,7 @@ void mp_delete_global(qstr qst) {
mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst));
}
-mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
+mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg) {
DEBUG_OP_printf("unary " UINT_FMT " %p\n", op, arg);
if (op == MP_UNARY_OP_NOT) {
@@ -231,6 +228,15 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
} else {
return MP_OBJ_NEW_SMALL_INT(-val);
}
+ case MP_UNARY_OP_ABS:
+ if (val >= 0) {
+ return arg;
+ } else if (val == MP_SMALL_INT_MIN) {
+ // check for overflow
+ return mp_obj_new_int(-val);
+ } else {
+ return MP_OBJ_NEW_SMALL_INT(-val);
+ }
default:
assert(op == MP_UNARY_OP_INVERT);
return MP_OBJ_NEW_SMALL_INT(~val);
@@ -261,7 +267,7 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
}
}
-mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
+mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
DEBUG_OP_printf("binary " UINT_FMT " %p %p\n", op, lhs, rhs);
// TODO correctly distinguish inplace operators for mutable objects
@@ -555,7 +561,20 @@ generic_binary_op:
}
}
- // TODO implement dispatch for reverse binary ops
+#if MICROPY_PY_REVERSE_SPECIAL_METHODS
+ if (op >= MP_BINARY_OP_OR && op <= MP_BINARY_OP_REVERSE_POWER) {
+ mp_obj_t t = rhs;
+ rhs = lhs;
+ lhs = t;
+ if (op <= MP_BINARY_OP_POWER) {
+ op += MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
+ goto generic_binary_op;
+ }
+
+ // Convert __rop__ back to __op__ for error message
+ op -= MP_BINARY_OP_REVERSE_OR - MP_BINARY_OP_OR;
+ }
+#endif
unsupported_op:
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
@@ -1408,7 +1427,7 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i
#endif // MICROPY_ENABLE_COMPILER
-NORETURN void *m_malloc_fail(size_t num_bytes) {
+NORETURN void m_malloc_fail(size_t num_bytes) {
DEBUG_printf("memory allocation failed, allocating %u bytes\n", (uint)num_bytes);
#if MICROPY_ENABLE_GC
if (gc_is_locked()) {
@@ -1439,6 +1458,6 @@ NORETURN void mp_raise_OSError(int errno_) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_)));
}
-NORETURN void mp_not_implemented(const char *msg) {
+NORETURN void mp_raise_NotImplementedError(const char *msg) {
mp_raise_msg(&mp_type_NotImplementedError, msg);
}
diff --git a/py/runtime.h b/py/runtime.h
index fe492885b..d410b5614 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -27,7 +27,6 @@
#define MICROPY_INCLUDED_PY_RUNTIME_H
#include "py/mpstate.h"
-#include "py/obj.h"
typedef enum {
MP_VM_RETURN_NORMAL,
@@ -57,9 +56,9 @@ typedef struct _mp_arg_t {
mp_arg_val_t defval;
} mp_arg_t;
-// defined in objtype.c
-extern const qstr mp_unary_op_method_name[];
-extern const qstr mp_binary_op_method_name[];
+// Tables mapping operator enums to qstrs, defined in objtype.c
+extern const uint16_t mp_unary_op_method_name[];
+extern const uint16_t mp_binary_op_method_name[];
void mp_init(void);
void mp_deinit(void);
@@ -96,8 +95,8 @@ void mp_store_global(qstr qst, mp_obj_t obj);
void mp_delete_name(qstr qst);
void mp_delete_global(qstr qst);
-mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg);
-mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
+mp_obj_t mp_unary_op(mp_unary_op_t op, mp_obj_t arg);
+mp_obj_t mp_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t mp_call_function_0(mp_obj_t fun);
mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);
@@ -149,8 +148,8 @@ NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg);
//NORETURN void nlr_raise_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...);
NORETURN void mp_raise_ValueError(const char *msg);
NORETURN void mp_raise_TypeError(const char *msg);
+NORETURN void mp_raise_NotImplementedError(const char *msg);
NORETURN void mp_raise_OSError(int errno_);
-NORETURN void mp_not_implemented(const char *msg); // Raise NotImplementedError with given message
NORETURN void mp_exc_recursion_depth(void);
#if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
@@ -175,7 +174,7 @@ void mp_native_raise(mp_obj_t o);
#if MICROPY_WARNINGS
void mp_warning(const char *msg, ...);
#else
-#define mp_warning(msg, ...)
+#define mp_warning(...)
#endif
#endif // MICROPY_INCLUDED_PY_RUNTIME_H
diff --git a/py/runtime0.h b/py/runtime0.h
index d22c2fabe..f54f62d2c 100644
--- a/py/runtime0.h
+++ b/py/runtime0.h
@@ -43,60 +43,93 @@
#define MP_NATIVE_TYPE_PTR32 (0x07)
typedef enum {
- MP_UNARY_OP_BOOL, // __bool__
- MP_UNARY_OP_LEN, // __len__
- MP_UNARY_OP_HASH, // __hash__; must return a small int
+ // These ops may appear in the bytecode. Changing this group
+ // in any way requires changing the bytecode version.
MP_UNARY_OP_POSITIVE,
MP_UNARY_OP_NEGATIVE,
MP_UNARY_OP_INVERT,
MP_UNARY_OP_NOT,
+
+ // Following ops cannot appear in the bytecode
+ MP_UNARY_OP_NON_BYTECODE,
+
+ MP_UNARY_OP_BOOL = MP_UNARY_OP_NON_BYTECODE, // __bool__
+ MP_UNARY_OP_LEN, // __len__
+ MP_UNARY_OP_HASH, // __hash__; must return a small int
+ MP_UNARY_OP_ABS, // __abs__
+ MP_UNARY_OP_SIZEOF, // for sys.getsizeof()
} mp_unary_op_t;
+// Note: the first 35 of these are used in bytecode and changing
+// them requires changing the bytecode version.
typedef enum {
- MP_BINARY_OP_OR,
- MP_BINARY_OP_XOR,
- MP_BINARY_OP_AND,
- MP_BINARY_OP_LSHIFT,
- MP_BINARY_OP_RSHIFT,
+ // Relational operations, should return a bool
+ MP_BINARY_OP_LESS,
+ MP_BINARY_OP_MORE,
+ MP_BINARY_OP_EQUAL,
+ MP_BINARY_OP_LESS_EQUAL,
+ MP_BINARY_OP_MORE_EQUAL,
+ MP_BINARY_OP_NOT_EQUAL,
- MP_BINARY_OP_ADD,
- MP_BINARY_OP_SUBTRACT,
- MP_BINARY_OP_MULTIPLY,
- MP_BINARY_OP_FLOOR_DIVIDE,
- MP_BINARY_OP_TRUE_DIVIDE,
+ MP_BINARY_OP_IN,
+ MP_BINARY_OP_IS,
+ MP_BINARY_OP_EXCEPTION_MATCH,
+ // these are not supported by the runtime and must be synthesised by the emitter
+ MP_BINARY_OP_NOT_IN,
+ MP_BINARY_OP_IS_NOT,
- MP_BINARY_OP_MODULO,
- MP_BINARY_OP_POWER,
- MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime
+ // Arithmetic operations
MP_BINARY_OP_INPLACE_OR,
MP_BINARY_OP_INPLACE_XOR,
-
MP_BINARY_OP_INPLACE_AND,
MP_BINARY_OP_INPLACE_LSHIFT,
MP_BINARY_OP_INPLACE_RSHIFT,
MP_BINARY_OP_INPLACE_ADD,
- MP_BINARY_OP_INPLACE_SUBTRACT,
+ MP_BINARY_OP_INPLACE_SUBTRACT,
MP_BINARY_OP_INPLACE_MULTIPLY,
MP_BINARY_OP_INPLACE_FLOOR_DIVIDE,
MP_BINARY_OP_INPLACE_TRUE_DIVIDE,
MP_BINARY_OP_INPLACE_MODULO,
MP_BINARY_OP_INPLACE_POWER,
- // these should return a bool
- MP_BINARY_OP_LESS,
- MP_BINARY_OP_MORE,
- MP_BINARY_OP_EQUAL,
- MP_BINARY_OP_LESS_EQUAL,
- MP_BINARY_OP_MORE_EQUAL,
+ MP_BINARY_OP_OR,
+ MP_BINARY_OP_XOR,
+ MP_BINARY_OP_AND,
+ MP_BINARY_OP_LSHIFT,
+ MP_BINARY_OP_RSHIFT,
+ MP_BINARY_OP_ADD,
- MP_BINARY_OP_NOT_EQUAL,
- MP_BINARY_OP_IN,
- MP_BINARY_OP_IS,
- MP_BINARY_OP_EXCEPTION_MATCH,
- // these are not supported by the runtime and must be synthesised by the emitter
- MP_BINARY_OP_NOT_IN,
- MP_BINARY_OP_IS_NOT,
+ MP_BINARY_OP_SUBTRACT,
+ MP_BINARY_OP_MULTIPLY,
+ MP_BINARY_OP_FLOOR_DIVIDE,
+ MP_BINARY_OP_TRUE_DIVIDE,
+ MP_BINARY_OP_MODULO,
+ MP_BINARY_OP_POWER,
+
+ // Operations below this line don't appear in bytecode, they
+ // just identify special methods.
+
+ // MP_BINARY_OP_REVERSE_* must follow immediately after MP_BINARY_OP_*
+#if MICROPY_PY_REVERSE_SPECIAL_METHODS
+ MP_BINARY_OP_REVERSE_OR,
+ MP_BINARY_OP_REVERSE_XOR,
+ MP_BINARY_OP_REVERSE_AND,
+ MP_BINARY_OP_REVERSE_LSHIFT,
+ MP_BINARY_OP_REVERSE_RSHIFT,
+ MP_BINARY_OP_REVERSE_ADD,
+
+ MP_BINARY_OP_REVERSE_SUBTRACT,
+ MP_BINARY_OP_REVERSE_MULTIPLY,
+ MP_BINARY_OP_REVERSE_FLOOR_DIVIDE,
+ MP_BINARY_OP_REVERSE_TRUE_DIVIDE,
+ MP_BINARY_OP_REVERSE_MODULO,
+ MP_BINARY_OP_REVERSE_POWER,
+#endif
+
+ MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime
+
+ MP_BINARY_OP_LAST,
} mp_binary_op_t;
typedef enum {
diff --git a/py/runtime_utils.c b/py/runtime_utils.c
index 56a918064..a5c5403ba 100644
--- a/py/runtime_utils.c
+++ b/py/runtime_utils.c
@@ -26,8 +26,6 @@
*/
#include "py/runtime.h"
-#include "py/obj.h"
-#include "py/nlr.h"
void mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg) {
nlr_buf_t nlr;
diff --git a/py/sequence.c b/py/sequence.c
index 0752ee109..c66fde98f 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -27,9 +27,6 @@
#include <string.h>
-#include "py/nlr.h"
-#include "py/obj.h"
-#include "py/runtime0.h"
#include "py/runtime.h"
// Helpers for sequence types
diff --git a/py/showbc.c b/py/showbc.c
index bb2b084ed..728d8d983 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -539,7 +539,7 @@ const byte *mp_bytecode_print_str(const byte *ip) {
printf("LOAD_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI);
} else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
printf("STORE_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI);
- } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 7) {
+ } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NON_BYTECODE) {
printf("UNARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI);
} else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI;
diff --git a/py/stackctrl.c b/py/stackctrl.c
index 0bcd82f4f..7cd35fee2 100644
--- a/py/stackctrl.c
+++ b/py/stackctrl.c
@@ -24,9 +24,6 @@
* THE SOFTWARE.
*/
-#include "py/mpstate.h"
-#include "py/nlr.h"
-#include "py/obj.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
diff --git a/py/stream.c b/py/stream.c
index 5d1868153..453dee769 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -28,7 +28,6 @@
#include <string.h>
#include <unistd.h>
-#include "py/nlr.h"
#include "py/objstr.h"
#include "py/stream.h"
#include "py/runtime.h"
@@ -141,9 +140,6 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl
mp_uint_t last_buf_offset = 0;
while (more_bytes > 0) {
char *p = vstr_add_len(&vstr, more_bytes);
- if (p == NULL) {
- mp_raise_msg(&mp_type_MemoryError, "out of memory");
- }
int error;
mp_uint_t out_sz = mp_stream_read_exactly(args[0], p, more_bytes, &error);
if (error != 0) {
@@ -380,10 +376,6 @@ STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args)
while (max_size == -1 || max_size-- != 0) {
char *p = vstr_add_len(&vstr, 1);
- if (p == NULL) {
- mp_raise_msg(&mp_type_MemoryError, "out of memory");
- }
-
int error;
mp_uint_t out_sz = stream_p->read(args[0], p, 1, &error);
if (out_sz == MP_STREAM_ERROR) {
@@ -448,11 +440,16 @@ STATIC mp_obj_t stream_seek(size_t n_args, const mp_obj_t *args) {
struct mp_stream_seek_t seek_s;
// TODO: Could be uint64
seek_s.offset = mp_obj_get_int(args[1]);
- seek_s.whence = 0;
+ seek_s.whence = SEEK_SET;
if (n_args == 3) {
seek_s.whence = mp_obj_get_int(args[2]);
}
+ // In POSIX, it's error to seek before end of stream, we enforce it here.
+ if (seek_s.whence == SEEK_SET && seek_s.offset < 0) {
+ mp_raise_OSError(MP_EINVAL);
+ }
+
int error;
mp_uint_t res = stream_p->ioctl(args[0], MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error);
if (res == MP_STREAM_ERROR) {
diff --git a/py/stream.h b/py/stream.h
index 401ae313c..fbe3d7d85 100644
--- a/py/stream.h
+++ b/py/stream.h
@@ -50,10 +50,18 @@
// Argument structure for MP_STREAM_SEEK
struct mp_stream_seek_t {
+ // If whence == MP_SEEK_SET, offset should be treated as unsigned.
+ // This allows dealing with full-width stream sizes (16, 32, 64,
+ // etc. bits). For other seek types, should be treated as signed.
mp_off_t offset;
int whence;
};
+// seek ioctl "whence" values
+#define MP_SEEK_SET (0)
+#define MP_SEEK_CUR (1)
+#define MP_SEEK_END (2)
+
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj);
diff --git a/py/unicode.c b/py/unicode.c
index eddb007d5..140b7ba71 100644
--- a/py/unicode.c
+++ b/py/unicode.c
@@ -182,3 +182,31 @@ mp_uint_t unichar_xdigit_value(unichar c) {
}
return n;
}
+
+bool utf8_check(const byte *p, size_t len) {
+ uint8_t need = 0;
+ const byte *end = p + len;
+ for (; p < end; p++) {
+ byte c = *p;
+ if (need) {
+ if (c >= 0x80) {
+ need--;
+ } else {
+ // mismatch
+ return 0;
+ }
+ } else {
+ if (c >= 0xc0) {
+ if (c >= 0xf8) {
+ // mismatch
+ return 0;
+ }
+ need = (0xe5 >> ((c >> 3) & 0x6)) & 3;
+ } else if (c >= 0x80) {
+ // mismatch
+ return 0;
+ }
+ }
+ }
+ return need == 0; // no pending fragments allowed
+}
diff --git a/py/unicode.h b/py/unicode.h
index 19487a65a..c1fb51789 100644
--- a/py/unicode.h
+++ b/py/unicode.h
@@ -30,5 +30,6 @@
#include "py/misc.h"
mp_uint_t utf8_ptr_to_index(const byte *s, const byte *ptr);
+bool utf8_check(const byte *p, size_t len);
#endif // MICROPY_INCLUDED_PY_UNICODE_H
diff --git a/py/vm.c b/py/vm.c
index c7fc83d04..564200037 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -29,8 +29,6 @@
#include <string.h>
#include <assert.h>
-#include "py/mpstate.h"
-#include "py/nlr.h"
#include "py/emitglue.h"
#include "py/objtype.h"
#include "py/runtime.h"
@@ -1124,7 +1122,7 @@ unwind_return:
}
}
if (obj == MP_OBJ_NULL) {
- obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "No active exception to reraise");
+ obj = mp_obj_new_exception_msg(&mp_type_RuntimeError, "no active exception to reraise");
RAISE(obj);
}
} else {
diff --git a/py/vmentrytable.h b/py/vmentrytable.h
index 352a6dc31..e634e2b41 100644
--- a/py/vmentrytable.h
+++ b/py/vmentrytable.h
@@ -109,7 +109,7 @@ static const void *const entry_table[256] = {
[MP_BC_LOAD_CONST_SMALL_INT_MULTI ... MP_BC_LOAD_CONST_SMALL_INT_MULTI + 63] = &&entry_MP_BC_LOAD_CONST_SMALL_INT_MULTI,
[MP_BC_LOAD_FAST_MULTI ... MP_BC_LOAD_FAST_MULTI + 15] = &&entry_MP_BC_LOAD_FAST_MULTI,
[MP_BC_STORE_FAST_MULTI ... MP_BC_STORE_FAST_MULTI + 15] = &&entry_MP_BC_STORE_FAST_MULTI,
- [MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + 6] = &&entry_MP_BC_UNARY_OP_MULTI,
+ [MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NON_BYTECODE - 1] = &&entry_MP_BC_UNARY_OP_MULTI,
[MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + 35] = &&entry_MP_BC_BINARY_OP_MULTI,
};
diff --git a/py/vstr.c b/py/vstr.c
index 8a00f6c6f..869b27805 100644
--- a/py/vstr.c
+++ b/py/vstr.c
@@ -30,7 +30,7 @@
#include <assert.h>
#include "py/mpconfig.h"
-#include "py/misc.h"
+#include "py/runtime.h"
#include "py/mpprint.h"
// returned value is always at least 1 greater than argument
@@ -92,7 +92,9 @@ void vstr_free(vstr_t *vstr) {
// Extend vstr strictly by requested size, return pointer to newly added chunk.
char *vstr_extend(vstr_t *vstr, size_t size) {
if (vstr->fixed_buf) {
- return NULL;
+ // We can't reallocate, and the caller is expecting the space to
+ // be there, so the only safe option is to raise an exception.
+ mp_raise_msg(&mp_type_RuntimeError, NULL);
}
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size);
char *p = new_buf + vstr->alloc;
@@ -101,17 +103,18 @@ char *vstr_extend(vstr_t *vstr, size_t size) {
return p;
}
-STATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) {
+STATIC void vstr_ensure_extra(vstr_t *vstr, size_t size) {
if (vstr->len + size > vstr->alloc) {
if (vstr->fixed_buf) {
- return false;
+ // We can't reallocate, and the caller is expecting the space to
+ // be there, so the only safe option is to raise an exception.
+ mp_raise_msg(&mp_type_RuntimeError, NULL);
}
size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16);
char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc);
vstr->alloc = new_alloc;
vstr->buf = new_buf;
}
- return true;
}
void vstr_hint_size(vstr_t *vstr, size_t size) {
@@ -119,9 +122,7 @@ void vstr_hint_size(vstr_t *vstr, size_t size) {
}
char *vstr_add_len(vstr_t *vstr, size_t len) {
- if (!vstr_ensure_extra(vstr, len)) {
- return NULL;
- }
+ vstr_ensure_extra(vstr, len);
char *buf = vstr->buf + vstr->len;
vstr->len += len;
return buf;
@@ -131,9 +132,7 @@ char *vstr_add_len(vstr_t *vstr, size_t len) {
char *vstr_null_terminated_str(vstr_t *vstr) {
// If there's no more room, add single byte
if (vstr->alloc == vstr->len) {
- if (vstr_extend(vstr, 1) == NULL) {
- return NULL;
- }
+ vstr_extend(vstr, 1);
}
vstr->buf[vstr->len] = '\0';
return vstr->buf;
@@ -141,9 +140,6 @@ char *vstr_null_terminated_str(vstr_t *vstr) {
void vstr_add_byte(vstr_t *vstr, byte b) {
byte *buf = (byte*)vstr_add_len(vstr, 1);
- if (buf == NULL) {
- return;
- }
buf[0] = b;
}
@@ -153,31 +149,19 @@ void vstr_add_char(vstr_t *vstr, unichar c) {
// Is it worth just calling vstr_add_len(vstr, 4)?
if (c < 0x80) {
byte *buf = (byte*)vstr_add_len(vstr, 1);
- if (buf == NULL) {
- return;
- }
*buf = (byte)c;
} else if (c < 0x800) {
byte *buf = (byte*)vstr_add_len(vstr, 2);
- if (buf == NULL) {
- return;
- }
buf[0] = (c >> 6) | 0xC0;
buf[1] = (c & 0x3F) | 0x80;
} else if (c < 0x10000) {
byte *buf = (byte*)vstr_add_len(vstr, 3);
- if (buf == NULL) {
- return;
- }
buf[0] = (c >> 12) | 0xE0;
buf[1] = ((c >> 6) & 0x3F) | 0x80;
buf[2] = (c & 0x3F) | 0x80;
} else {
assert(c < 0x110000);
byte *buf = (byte*)vstr_add_len(vstr, 4);
- if (buf == NULL) {
- return;
- }
buf[0] = (c >> 18) | 0xF0;
buf[1] = ((c >> 12) & 0x3F) | 0x80;
buf[2] = ((c >> 6) & 0x3F) | 0x80;
@@ -193,16 +177,7 @@ void vstr_add_str(vstr_t *vstr, const char *str) {
}
void vstr_add_strn(vstr_t *vstr, const char *str, size_t len) {
- if (!vstr_ensure_extra(vstr, len)) {
- // if buf is fixed, we got here because there isn't enough room left
- // so just try to copy as much as we can, with room for a possible null byte
- if (vstr->fixed_buf && vstr->len < vstr->alloc) {
- len = vstr->alloc - vstr->len;
- goto copy;
- }
- return;
- }
-copy:
+ vstr_ensure_extra(vstr, len);
memmove(vstr->buf + vstr->len, str, len);
vstr->len += len;
}
@@ -214,9 +189,7 @@ STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len
}
if (byte_len > 0) {
// ensure room for the new bytes
- if (!vstr_ensure_extra(vstr, byte_len)) {
- return NULL;
- }
+ vstr_ensure_extra(vstr, byte_len);
// copy up the string to make room for the new bytes
memmove(vstr->buf + byte_pos + byte_len, vstr->buf + byte_pos, l - byte_pos);
// increase the length
@@ -227,17 +200,13 @@ STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len
void vstr_ins_byte(vstr_t *vstr, size_t byte_pos, byte b) {
char *s = vstr_ins_blank_bytes(vstr, byte_pos, 1);
- if (s != NULL) {
- *s = b;
- }
+ *s = b;
}
void vstr_ins_char(vstr_t *vstr, size_t char_pos, unichar chr) {
// TODO UNICODE
char *s = vstr_ins_blank_bytes(vstr, char_pos, 1);
- if (s != NULL) {
- *s = chr;
- }
+ *s = chr;
}
void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) {
diff --git a/py/warning.c b/py/warning.c
index 46b31ecca..12d0f9c99 100644
--- a/py/warning.c
+++ b/py/warning.c
@@ -35,9 +35,9 @@
void mp_warning(const char *msg, ...) {
va_list args;
va_start(args, msg);
- mp_print_str(&mp_plat_print, "Warning: ");
- mp_vprintf(&mp_plat_print, msg, args);
- mp_print_str(&mp_plat_print, "\n");
+ mp_print_str(MICROPY_ERROR_PRINTER, "Warning: ");
+ mp_vprintf(MICROPY_ERROR_PRINTER, msg, args);
+ mp_print_str(MICROPY_ERROR_PRINTER, "\n");
va_end(args);
}