summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2017-08-14 16:25:17 +1000
committerDamien George <damien.p.george@gmail.com>2017-08-14 16:25:17 +1000
commit76b564ca4701460a2ad72ef26076c2e339ada506 (patch)
treed054854ace1a9b1fd2832a47e5d4cbe4724f6d48 /py
parenta7f5c64d2157356ff4457d32c662403cea0ddcb7 (diff)
parent5a1d63fc14dae788f705403a43c2d8639b7dd9cd (diff)
Merge tag 'v1.8.6' into parse-bytecode
ESP8266 port uses SDK 2.0, has more heap, has support for 512k devices This release brings some code size reductions to the core as well as more tests and improved coverage which is now at 94.3%. The time.ticks_diff(a, b) function has changed: the order of the arguments has been swapped so that it behaves like "a - b", and it can now return a negative number if "a" came before "b" (modulo the period of the ticks functions). For the ESP8266 port the Espressif SDK has been updated to 2.0.0, the heap has been increased from 28k to 36k, and there is support for 512k devices via "make 512k". upip is included by default as frozen bytecode. The network module now allows access-point reconnection without WiFi credentials, and exposes configuration for the station DHCP hostname. The DS18B20 driver now handles negative temperatures, and NeoPixel and APA102 drivers handle 4 bytes-per-pixel LEDs. For the CC3200 port there is now support for loading of precompiled .mpy files and threading now works properly with interrupts. A detailed list of changes follows. py core: - py.mk: automatically add frozen.c to source list if FROZEN_DIR is defined - be more specific with MP_DECLARE_CONST_FUN_OBJ macros - specialise builtin funcs to use separate type for fixed arg count - {modbuiltins,obj}: use MP_PYTHON_PRINTER where possible - modbuiltins: add builtin "slice", pointing to existing slice type - add "delattr" builtin, conditional on MICROPY_CPYTHON_COMPAT - sequence: fix reverse slicing of lists - fix null pointer dereference in mpz.c, fix missing va_end in warning.c - remove asserts that are always true in emitbc.c - fix wrong assumption that m_renew will not move if shrinking - change config default so m_malloc0 uses memset if GC not enabled - add MICROPY_FLOAT_CONST macro for defining float constants - move frozen bytecode Makefile rules from ports to common mk files - strip leading dirs from frozen mpy files, so any path can be used extmod: - vfs_fat_file: check fatfs f_sync() and f_close() returns for errors - vfs_fat_file: make file.close() a no-op if file already closed - utime_mphal: ticks_diff(): switch arg order, return signed value - utime_mphal: add MP_THREAD_GIL_EXIT/ENTER warppers for sleep functions - utime_mphal: implement ticks_add(), add to all maintained ports - utime_mphal: allow ticks functions period be configurable by a port lib: - utils/pyhelp.c: use mp_printf() instead of printf() - utils/pyexec: add mp_hal_set_interrupt_char() prototype - libm: move Thumb-specific sqrtf function to separate file drivers: - add "from micropython import const" when const is used tools: - upgrade upip to 1.1.4: fix error on unix when installing to non-existing absolute path - pip-micropython: remove deprecated wrapper tool - check_code_size.sh: code size validation script for CI - replace upip tarball with just source file, to make its inclusion as frozen modules in multiple ports less magic tests: - extmod/vfs_fat: improve VFS test coverage - basics/builtin_slice: add test for "slice" builtin name - basics: add test for builtin "delattr" - extmod/vfs_fat_fsusermount: improve fsusermount test coverage - extmod/vfs_fat_oldproto: test old block device protocol - basics/gc1: garbage collector threshold() coverage - extmod/uhashlib_sha1: coverage for SHA1 algorithm - extmod/uhashlib_sha256: rename sha256.py test - btree1: fix out of memory error running on esp8266 - extmod/ticks_diff: test for new semantics of ticks_diff() - extmod/framebuf1: test framebuffer pixel clear, and text function minimal port: - Makefile: split rule for firmware.bin generation unix port: - Makefile: remove references to deprecated pip-micropython - modtime: use ticks_diff() implementation from extmod/utime_mphal.c - mphalport.h: add warning of mp_hal_delay_ms() implementation - modtime: switch ticks/sleep_ms/us() to utime_mphal - fix symbol references for x86 Mac - replace upip tarball with just source file windows port: - enable utime_mphal following unix, define mp_hal_ticks_* - fix utime_mphal compilation for msvc - implement mp_hal_ticks_cpu in terms of QueryPerformanceCounter qemu-arm port: - exclude ticks_diff test for qemu-arm port - exclude extmod/vfs_fat_fileio.py test - exclude new vfs_fat tests - enable software floating point support, and float tests stmhal port: - modutime: refactor to use extmod's version of ticks_cpu - refactor pin usage to use mp_hal_pin API - led: refactor LED to use mp_hal_pin_output() init function - Makefile: use standard rules for frozen module generation - modutime: consistently convert to MP_ROM_QSTR/MP_ROM_PTR - enable SD power save (disable CLK on idle) cc3200 port: - use mp_raise_XXX helper functions to reduce code size - mods/pybspi: allow "write" arg of read/readinto to be positional - enable loading of precompiled .mpy files - fix thread mutex's so threading works with interrupts teensy port: - update to provide new mp_hal_pin_XXX functions following stmhal esp8266 port: - Makefile: use latest esptool.py flash size auto-detection - esp_init_data: auto-initialize system params with vendor SDK 2.0.0 - esp8266.ld: move help.o to iROM - esp8266.ld: move modmachine.o to iROM - esp8266.ld: move main.o to iROM - add MP_FASTCODE modifier to put a function to iRAM - main: mark nlr_jump_fail() as MP_FASTCODE - modules/webrepl: enforce only one concurrent WebREPL connection - etshal.h: add few more ESP8266 vendor lib prototypes - modesp: add flash_user_start() function - add support for building firmware version for 512K modules - scripts: make neopixel/apa102 handle 4bpp LEDs with common code - modutime: consistently convert to MP_ROM_QSTR/MP_ROM_PTR - modnetwork: config(): fix copy-paste error in setting "mac" - scripts/port_diag: add descriptions for esf_buf types - modnetwork.c: allows AP reconnection without WiFi credentials - main: bump heap size to 36K - etshal.h: add prototypes for SPIRead/SPIWrite/SPIEraseSector - etshal.h: adjust size of MD5_CTX structure - modules: fix negative temperature in ds18x20 driver - rename "machine" module implementation to use contemporary naming - rework webrepl_setup to run over wired REPL - espneopixel.c: solve glitching LED issues with cpu at 80MHz - include upip as a standard frozen bytecode module - update docs for esptool 1.2.1/SDK 2.0 (--flash_size=detect) - modnetwork.c: expose configuration for station DHCP hostname zephyr port: - implement utime module - use board/SoC values for startup banner based on Zephyr config - initial implementation of machine.Pin - zephyr_getchar: update for recent Zephyr refactor of console hooks - support time -> utime module "weaklink" - README: update for the current featureset, add more info - mpconfigport.h: move less important params to the bottom - Makefile: allow to adjust heap size from make command line - Makefile: update comments to the current state of affairs - Makefile: allow to override Zephyr config from make command line - Makefile: add minimal port - Makefile: add -fomit-frame-pointer to reduce code size - mphalport.h: update for new "unified" kernal API (sleep functions) docs: - machine.SPI: bring up to date with Hardware API, make vendor-neutral - machine.SPI: improve descriptions of xfer methods - library/builtins: add docs for delattr and slice - library/network: reword intro paragraph - library/network: typo fixes, consistent acronym capitalization - library/index: update TOCs so builtins sorted before modules - utime: document ticks_cpu() in more detail - utime: describe new semantics of ticks_diff() (signed ring arithmetics) - utime: add docs for ticks_add(), improvements for other ticks_*() - esp8266: update for new WebREPL setup procedure - */quickref.rst: use new semantics of ticks_diff() - library/machine.Pin: update Pin docs to align with new HW API travis: - integrate tools/check_code_size.sh - minimal: Use CROSS=1, for binary size check examples: - http_server_simplistic: add "not suitable for real use" note - hwapi: example showing best practices for HW API usage in apps - hwapi: add hwconfig for DragonBoard 410c
Diffstat (limited to 'py')
-rw-r--r--py/builtin.h97
-rw-r--r--py/emitbc.c5
-rw-r--r--py/mkenv.mk2
-rw-r--r--py/mkrules.mk17
-rw-r--r--py/modbuiltins.c22
-rw-r--r--py/modmath.c9
-rw-r--r--py/mpconfig.h15
-rw-r--r--py/mpprint.h6
-rw-r--r--py/mpz.c5
-rw-r--r--py/nlrx86.S34
-rw-r--r--py/obj.c6
-rw-r--r--py/obj.h63
-rw-r--r--py/objfun.c86
-rw-r--r--py/objstr.h54
-rw-r--r--py/parse.c5
-rw-r--r--py/parsenum.c2
-rw-r--r--py/py.mk12
-rw-r--r--py/qstr.c2
-rw-r--r--py/runtime.c8
-rw-r--r--py/sequence.c49
-rw-r--r--py/stream.c2
-rw-r--r--py/stream.h24
-rw-r--r--py/warning.c1
23 files changed, 337 insertions, 189 deletions
diff --git a/py/builtin.h b/py/builtin.h
index cd1be3ab8..4477fd246 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -32,56 +32,56 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin___build_class___obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin___import___obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin___repl_print___obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_abs_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bin_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_compile_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_eval_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_exec_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_execfile_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_getattr_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_setattr_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_globals_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hasattr_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hex_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_id_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_isinstance_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_issubclass_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_iter_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_len_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_list_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_locals_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_max_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_min_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_next_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_oct_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_ord_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_pow_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_print_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_repr_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_round_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sorted_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_abs_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_all_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_any_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_bin_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_callable_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_chr_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj);
+MP_DECLARE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj);
+MP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_globals_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hash_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hex_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_id_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_iter_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_len_obj);
+MP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_locals_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_max_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_min_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_next_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_oct_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_ord_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_print_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_repr_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj);
// Defined by a port, but declared here for simplicity
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_help_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_input_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_open_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_namedtuple_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_op_contains_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_op_getitem_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_op_setitem_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_op_delitem_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_op_contains_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_op_getitem_obj);
+MP_DECLARE_CONST_FUN_OBJ_3(mp_op_setitem_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_op_delitem_obj);
extern const mp_obj_module_t mp_module___main__;
extern const mp_obj_module_t mp_module_builtins;
@@ -116,7 +116,4 @@ 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;
-// extmod functions
-MP_DECLARE_CONST_FUN_OBJ(pyb_mount_obj);
-
#endif // __MICROPY_INCLUDED_PY_BUILTIN_H__
diff --git a/py/emitbc.c b/py/emitbc.c
index d6f2bf333..e11c9ae94 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -183,7 +183,6 @@ STATIC void emit_write_bytecode_byte(emit_t *emit, byte b1) {
}
STATIC void emit_write_bytecode_byte_byte(emit_t* emit, byte b1, byte b2) {
- assert((b2 & (~0xff)) == 0);
byte *c = emit_get_cur_to_write_bytecode(emit, 2);
c[0] = b1;
c[1] = b2;
@@ -550,7 +549,6 @@ void mp_emit_bc_load_null(emit_t *emit) {
void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
(void)qst;
- assert(local_num >= 0);
emit_bc_pre(emit, 1);
if (local_num <= 15) {
emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num);
@@ -608,7 +606,6 @@ void mp_emit_bc_load_subscr(emit_t *emit) {
void mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
(void)qst;
- assert(local_num >= 0);
emit_bc_pre(emit, -1);
if (local_num <= 15) {
emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num);
@@ -927,7 +924,7 @@ void mp_emit_bc_return_value(emit_t *emit) {
}
void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) {
- assert(0 <= n_args && n_args <= 2);
+ assert(n_args <= 2);
emit_bc_pre(emit, -n_args);
emit_write_bytecode_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);
}
diff --git a/py/mkenv.mk b/py/mkenv.mk
index e7262907c..14e23e074 100644
--- a/py/mkenv.mk
+++ b/py/mkenv.mk
@@ -59,6 +59,8 @@ LD += -m32
endif
MAKE_FROZEN = ../tools/make-frozen.py
+MPY_CROSS = ../mpy-cross/mpy-cross
+MPY_TOOL = ../tools/mpy-tool.py
all:
.PHONY: all
diff --git a/py/mkrules.mk b/py/mkrules.mk
index 26e4aeab3..ea647e86f 100644
--- a/py/mkrules.mk
+++ b/py/mkrules.mk
@@ -106,6 +106,23 @@ $(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DE
$(Q)$(MAKE_FROZEN) $(FROZEN_DIR) > $@
endif
+ifneq ($(FROZEN_MPY_DIR),)
+# make a list of all the .py files that need compiling and freezing
+FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' -printf '%P\n')
+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
+ @$(ECHO) "MPY $<"
+ $(Q)$(MKDIR) -p $(dir $@)
+ $(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^
+
+# to build frozen_mpy.c from all .mpy files
+$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
+ @$(ECHO) "Creating $@"
+ $(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@
+endif
+
ifneq ($(PROG),)
# Build a standalone executable (unix does this)
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 57e52efa5..cbdcc9aae 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -430,13 +430,8 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print);
STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
if (o != mp_const_none) {
- #if MICROPY_PY_IO
- mp_obj_print_helper(&mp_sys_stdout_print, o, PRINT_REPR);
- mp_print_str(&mp_sys_stdout_print, "\n");
- #else
- mp_obj_print_helper(&mp_plat_print, o, PRINT_REPR);
- mp_print_str(&mp_plat_print, "\n");
- #endif
+ mp_obj_print_helper(MP_PYTHON_PRINTER, o, PRINT_REPR);
+ mp_print_str(MP_PYTHON_PRINTER, "\n");
#if MICROPY_CAN_OVERRIDE_BUILTINS
// Set "_" special variable
mp_obj_t dest[2] = {MP_OBJ_SENTINEL, o};
@@ -547,6 +542,13 @@ STATIC mp_obj_t mp_builtin_setattr(mp_obj_t base, mp_obj_t attr, mp_obj_t value)
}
MP_DEFINE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj, mp_builtin_setattr);
+#if MICROPY_CPYTHON_COMPAT
+STATIC mp_obj_t mp_builtin_delattr(mp_obj_t base, mp_obj_t attr) {
+ return mp_builtin_setattr(base, attr, MP_OBJ_NULL);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj, mp_builtin_delattr);
+#endif
+
STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) {
qstr attr = mp_obj_str_get_qstr(attr_in);
@@ -622,6 +624,9 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
#if MICROPY_PY_BUILTINS_SET
{ MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mp_type_set) },
#endif
+ #if MICROPY_PY_BUILTINS_SLICE
+ { MP_ROM_QSTR(MP_QSTR_slice), MP_ROM_PTR(&mp_type_slice) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_str), MP_ROM_PTR(&mp_type_str) },
{ MP_ROM_QSTR(MP_QSTR_super), MP_ROM_PTR(&mp_type_super) },
{ MP_ROM_QSTR(MP_QSTR_tuple), MP_ROM_PTR(&mp_type_tuple) },
@@ -647,6 +652,9 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mp_builtin_compile_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_chr), MP_ROM_PTR(&mp_builtin_chr_obj) },
+ #if MICROPY_CPYTHON_COMPAT
+ { MP_ROM_QSTR(MP_QSTR_delattr), MP_ROM_PTR(&mp_builtin_delattr_obj) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_dir), MP_ROM_PTR(&mp_builtin_dir_obj) },
{ MP_ROM_QSTR(MP_QSTR_divmod), MP_ROM_PTR(&mp_builtin_divmod_obj) },
#if MICROPY_PY_BUILTINS_EVAL_EXEC
diff --git a/py/modmath.c b/py/modmath.c
index 0c70f34cd..7c51eab03 100644
--- a/py/modmath.c
+++ b/py/modmath.c
@@ -32,9 +32,8 @@
#include <math.h>
// M_PI is not part of the math.h standard and may not be defined
-#ifndef M_PI
-#define M_PI (3.14159265358979323846)
-#endif
+// 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
///
@@ -204,13 +203,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf);
/// \function 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) * M_PI / 180.0);
+ 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)
STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) {
- return mp_obj_new_float(mp_obj_get_float(x_obj) * 180.0 / M_PI);
+ return mp_obj_new_float(mp_obj_get_float(x_obj) * (MICROPY_FLOAT_CONST(180.0) / MP_PI));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees);
diff --git a/py/mpconfig.h b/py/mpconfig.h
index dcdaffe0f..3945a1a5a 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -110,10 +110,11 @@
// Be conservative and always clear to zero newly (re)allocated memory in the GC.
// This helps eliminate stray pointers that hold on to memory that's no longer
// used. It decreases performance due to unnecessary memory clearing.
+// A memory manager which always clears memory can set this to 0.
// TODO Do analysis to understand why some memory is not properly cleared and
// find a more efficient way to clear it.
#ifndef MICROPY_GC_CONSERVATIVE_CLEAR
-#define MICROPY_GC_CONSERVATIVE_CLEAR (1)
+#define MICROPY_GC_CONSERVATIVE_CLEAR (MICROPY_ENABLE_GC)
#endif
// Support automatic GC when reaching allocation threshold,
@@ -504,10 +505,12 @@ typedef long long mp_longint_impl_t;
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
#define MICROPY_PY_BUILTINS_FLOAT (1)
+#define MICROPY_FLOAT_CONST(x) x##F
#define MICROPY_FLOAT_C_FUN(fun) fun##f
typedef float mp_float_t;
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
#define MICROPY_PY_BUILTINS_FLOAT (1)
+#define MICROPY_FLOAT_CONST(x) x
#define MICROPY_FLOAT_C_FUN(fun) fun
typedef double mp_float_t;
#else
@@ -866,6 +869,16 @@ typedef double mp_float_t;
#define MICROPY_PY_UTIME_MP_HAL (0)
#endif
+// Period of values returned by utime.ticks_ms(), ticks_us(), ticks_cpu()
+// functions. Should be power of two. All functions above use the same
+// period, so if underlying hardware/API has different periods, the
+// minimum of them should be used. The value below is the maximum value
+// this parameter can take (corresponding to 30 bit tick values on 32-bit
+// system).
+#ifndef MICROPY_PY_UTIME_TICKS_PERIOD
+#define MICROPY_PY_UTIME_TICKS_PERIOD (MP_SMALL_INT_POSITIVE_MASK + 1)
+#endif
+
// Whether to provide "_thread" module
#ifndef MICROPY_PY_THREAD
#define MICROPY_PY_THREAD (0)
diff --git a/py/mpprint.h b/py/mpprint.h
index 6e47409ec..f9204e322 100644
--- a/py/mpprint.h
+++ b/py/mpprint.h
@@ -39,6 +39,12 @@
#define PF_FLAG_ADD_PERCENT (0x100)
#define PF_FLAG_SHOW_OCTAL_LETTER (0x200)
+#if MICROPY_PY_IO
+# define MP_PYTHON_PRINTER &mp_sys_stdout_print
+#else
+# define MP_PYTHON_PRINTER &mp_plat_print
+#endif
+
typedef void (*mp_print_strn_t)(void *data, const char *str, size_t len);
typedef struct _mp_print_t {
diff --git a/py/mpz.c b/py/mpz.c
index cceb079cd..1dd177b8e 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -1652,7 +1652,10 @@ char *mpz_as_str(const mpz_t *i, mp_uint_t base) {
// assumes enough space as calculated by mp_int_format_size
// returns length of string, not including null byte
mp_uint_t mpz_as_str_inpl(const mpz_t *i, mp_uint_t base, const char *prefix, char base_char, char comma, char *str) {
- if (str == NULL || base < 2 || base > 32) {
+ if (str == NULL) {
+ return 0;
+ }
+ if (base < 2 || base > 32) {
str[0] = 0;
return 0;
}
diff --git a/py/nlrx86.S b/py/nlrx86.S
index 8a96af81c..8c538ba17 100644
--- a/py/nlrx86.S
+++ b/py/nlrx86.S
@@ -37,9 +37,18 @@
#if defined(_WIN32) || defined(__CYGWIN__)
#define NLR_OS_WINDOWS
+#endif
+
+#if defined(__APPLE__) && defined(__MACH__)
+#define NLR_OS_MAC
+#endif
+
+#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
#define NLR_TOP (_mp_state_ctx + NLR_TOP_OFFSET)
+#define MP_THREAD_GET_STATE _mp_thread_get_state
#else
#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
+#define MP_THREAD_GET_STATE mp_thread_get_state
#endif
// offset of nlr_top within mp_state_thread_t structure
@@ -55,6 +64,9 @@
.globl _nlr_push
.def _nlr_push; .scl 2; .type 32; .endef
_nlr_push:
+#elif defined(NLR_OS_MAC)
+ .globl _nlr_push
+_nlr_push:
#else
.globl nlr_push
.type nlr_push, @function
@@ -75,7 +87,7 @@ nlr_push:
mov %edx, NLR_TOP # stor new nlr_buf (to make linked list)
#else
// to check: stack is aligned to 16-byte boundary before this call
- call mp_thread_get_state # get mp_state_thread ptr into eax
+ call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
mov 4(%esp), %edx # load nlr_buf argument into edx (edx clobbered by call)
mov NLR_TOP_TH_OFF(%eax), %ecx # get thread.nlr_top (last nlr_buf)
mov %ecx, (%edx) # store it
@@ -84,7 +96,7 @@ nlr_push:
xor %eax, %eax # return 0, normal return
ret # return
-#if !defined(NLR_OS_WINDOWS)
+#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
.size nlr_push, .-nlr_push
#endif
@@ -95,6 +107,9 @@ nlr_push:
.globl _nlr_pop
.def _nlr_pop; .scl 2; .type 32; .endef
_nlr_pop:
+#elif defined(NLR_OS_MAC)
+ .globl _nlr_pop
+_nlr_pop:
#else
.globl nlr_pop
.type nlr_pop, @function
@@ -106,14 +121,14 @@ nlr_pop:
mov (%eax), %eax # load prev nlr_buf
mov %eax, NLR_TOP # store nlr_top (to unlink list)
#else
- call mp_thread_get_state # get mp_state_thread ptr into eax
+ call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
mov NLR_TOP_TH_OFF(%eax), %ecx # get thread.nlr_top (last nlr_buf)
mov (%ecx), %ecx # load prev nlr_buf
mov %ecx, NLR_TOP_TH_OFF(%eax) # store prev nlr_buf (to unlink list)
#endif
ret # return
-#if !defined(NLR_OS_WINDOWS)
+#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
.size nlr_pop, .-nlr_pop
#endif
@@ -124,6 +139,9 @@ nlr_pop:
.globl _nlr_jump
.def _nlr_jump; .scl 2; .type 32; .endef
_nlr_jump:
+#elif defined(NLR_OS_MAC)
+ .globl _nlr_jump
+_nlr_jump:
#else
.globl nlr_jump
.type nlr_jump, @function
@@ -133,7 +151,7 @@ nlr_jump:
#if !MICROPY_PY_THREAD
mov NLR_TOP, %edx # load nlr_top
test %edx, %edx # check for nlr_top being NULL
-#if defined(NLR_OS_WINDOWS)
+#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
je _nlr_jump_fail # fail if nlr_top is NULL
#else
je nlr_jump_fail # fail if nlr_top is NULL
@@ -143,10 +161,10 @@ nlr_jump:
mov (%edx), %eax # load prev nlr_top
mov %eax, NLR_TOP # store nlr_top (to unlink list)
#else
- call mp_thread_get_state # get mp_state_thread ptr into eax
+ call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
mov NLR_TOP_TH_OFF(%eax), %edx # get thread.nlr_top (last nlr_buf)
test %edx, %edx # check for nlr_top being NULL
-#if defined(NLR_OS_WINDOWS)
+#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
je _nlr_jump_fail # fail if nlr_top is NULL
#else
je nlr_jump_fail # fail if nlr_top is NULL
@@ -167,7 +185,7 @@ nlr_jump:
xor %eax, %eax # clear return register
inc %al # increase to make 1, non-local return
ret # return
-#if !defined(NLR_OS_WINDOWS)
+#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
.size nlr_jump, .-nlr_jump
#endif
diff --git a/py/obj.c b/py/obj.c
index 72b7a216b..5601a73fe 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -76,11 +76,7 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
}
void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
-#if MICROPY_PY_IO
- mp_obj_print_helper(&mp_sys_stdout_print, o_in, kind);
-#else
- mp_obj_print_helper(&mp_plat_print, o_in, kind);
-#endif
+ mp_obj_print_helper(MP_PYTHON_PRINTER, o_in, kind);
}
// helper function to print an exception with traceback
diff --git a/py/obj.h b/py/obj.h
index 72d79ce14..61db65a9a 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -270,29 +270,35 @@ static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o)
// These macros are used to declare and define constant function objects
// You can put "static" in front of the definitions to make them local
-#define MP_DECLARE_CONST_FUN_OBJ(obj_name) extern const mp_obj_fun_builtin_t obj_name
+#define MP_DECLARE_CONST_FUN_OBJ_0(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name
+#define MP_DECLARE_CONST_FUN_OBJ_1(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name
+#define MP_DECLARE_CONST_FUN_OBJ_2(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name
+#define MP_DECLARE_CONST_FUN_OBJ_3(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name
+#define MP_DECLARE_CONST_FUN_OBJ_VAR(obj_name) extern const mp_obj_fun_builtin_var_t obj_name
+#define MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name) extern const mp_obj_fun_builtin_var_t obj_name
+#define MP_DECLARE_CONST_FUN_OBJ_KW(obj_name) extern const mp_obj_fun_builtin_var_t obj_name
#define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) \
- const mp_obj_fun_builtin_t obj_name = \
- {{&mp_type_fun_builtin}, false, 0, 0, .fun._0 = fun_name}
+ const mp_obj_fun_builtin_fixed_t obj_name = \
+ {{&mp_type_fun_builtin_0}, .fun._0 = fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) \
- const mp_obj_fun_builtin_t obj_name = \
- {{&mp_type_fun_builtin}, false, 1, 1, .fun._1 = fun_name}
+ const mp_obj_fun_builtin_fixed_t obj_name = \
+ {{&mp_type_fun_builtin_1}, .fun._1 = fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) \
- const mp_obj_fun_builtin_t obj_name = \
- {{&mp_type_fun_builtin}, false, 2, 2, .fun._2 = fun_name}
+ const mp_obj_fun_builtin_fixed_t obj_name = \
+ {{&mp_type_fun_builtin_2}, .fun._2 = fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) \
- const mp_obj_fun_builtin_t obj_name = \
- {{&mp_type_fun_builtin}, false, 3, 3, .fun._3 = fun_name}
+ const mp_obj_fun_builtin_fixed_t obj_name = \
+ {{&mp_type_fun_builtin_3}, .fun._3 = fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) \
- const mp_obj_fun_builtin_t obj_name = \
- {{&mp_type_fun_builtin}, false, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.var = fun_name}
+ const mp_obj_fun_builtin_var_t obj_name = \
+ {{&mp_type_fun_builtin_var}, false, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.var = fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) \
- const mp_obj_fun_builtin_t obj_name = \
- {{&mp_type_fun_builtin}, false, n_args_min, n_args_max, .fun.var = fun_name}
+ const mp_obj_fun_builtin_var_t obj_name = \
+ {{&mp_type_fun_builtin_var}, false, n_args_min, n_args_max, .fun.var = fun_name}
#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) \
- const mp_obj_fun_builtin_t obj_name = \
- {{&mp_type_fun_builtin}, true, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.kw = fun_name}
+ const mp_obj_fun_builtin_var_t obj_name = \
+ {{&mp_type_fun_builtin_var}, true, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.kw = fun_name}
// These macros are used to define constant map/dict objects
// You can put "static" in front of the definition to make it local
@@ -530,7 +536,11 @@ extern const mp_obj_type_t mp_type_zip;
extern const mp_obj_type_t mp_type_array;
extern const mp_obj_type_t mp_type_super;
extern const mp_obj_type_t mp_type_gen_instance;
-extern const mp_obj_type_t mp_type_fun_builtin;
+extern const mp_obj_type_t mp_type_fun_builtin_0;
+extern const mp_obj_type_t mp_type_fun_builtin_1;
+extern const mp_obj_type_t mp_type_fun_builtin_2;
+extern const mp_obj_type_t mp_type_fun_builtin_3;
+extern const mp_obj_type_t mp_type_fun_builtin_var;
extern const mp_obj_type_t mp_type_fun_bc;
extern const mp_obj_type_t mp_type_module;
extern const mp_obj_type_t mp_type_staticmethod;
@@ -740,27 +750,34 @@ void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step);
// functions
-#define MP_OBJ_FUN_ARGS_MAX (0xffff) // to set maximum value in n_args_max below
-typedef struct _mp_obj_fun_builtin_t { // use this to make const objects that go in ROM
+
+typedef struct _mp_obj_fun_builtin_fixed_t {
mp_obj_base_t base;
- bool is_kw : 1;
- mp_uint_t n_args_min : 15; // inclusive
- mp_uint_t n_args_max : 16; // inclusive
union {
mp_fun_0_t _0;
mp_fun_1_t _1;
mp_fun_2_t _2;
mp_fun_3_t _3;
+ } fun;
+} mp_obj_fun_builtin_fixed_t;
+
+#define MP_OBJ_FUN_ARGS_MAX (0xffff) // to set maximum value in n_args_max below
+typedef struct _mp_obj_fun_builtin_var_t {
+ mp_obj_base_t base;
+ bool is_kw : 1;
+ mp_uint_t n_args_min : 15; // inclusive
+ mp_uint_t n_args_max : 16; // inclusive
+ union {
mp_fun_var_t var;
mp_fun_kw_t kw;
} fun;
-} mp_obj_fun_builtin_t;
+} mp_obj_fun_builtin_var_t;
qstr mp_obj_fun_get_name(mp_const_obj_t fun);
qstr mp_obj_code_get_name(const byte *code_info);
mp_obj_t mp_identity(mp_obj_t self);
-MP_DECLARE_CONST_FUN_OBJ(mp_identity_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_identity_obj);
// module
typedef struct _mp_obj_module_t {
diff --git a/py/objfun.c b/py/objfun.c
index 405f38127..6b8fe6d38 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -50,11 +50,66 @@
/******************************************************************************/
/* builtin functions */
-// mp_obj_fun_builtin_t defined in obj.h
+STATIC mp_obj_t fun_builtin_0_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ (void)args;
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_0));
+ mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_arg_check_num(n_args, n_kw, 0, 0, false);
+ return self->fun._0();
+}
-STATIC mp_obj_t fun_builtin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin));
- mp_obj_fun_builtin_t *self = MP_OBJ_TO_PTR(self_in);
+const mp_obj_type_t mp_type_fun_builtin_0 = {
+ { &mp_type_type },
+ .name = MP_QSTR_function,
+ .call = fun_builtin_0_call,
+ .unary_op = mp_generic_unary_op,
+};
+
+STATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_1));
+ mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_arg_check_num(n_args, n_kw, 1, 1, false);
+ return self->fun._1(args[0]);
+}
+
+const mp_obj_type_t mp_type_fun_builtin_1 = {
+ { &mp_type_type },
+ .name = MP_QSTR_function,
+ .call = fun_builtin_1_call,
+ .unary_op = mp_generic_unary_op,
+};
+
+STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_2));
+ mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_arg_check_num(n_args, n_kw, 2, 2, false);
+ return self->fun._2(args[0], args[1]);
+}
+
+const mp_obj_type_t mp_type_fun_builtin_2 = {
+ { &mp_type_type },
+ .name = MP_QSTR_function,
+ .call = fun_builtin_2_call,
+ .unary_op = mp_generic_unary_op,
+};
+
+STATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_3));
+ mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_arg_check_num(n_args, n_kw, 3, 3, false);
+ return self->fun._3(args[0], args[1], args[2]);
+}
+
+const mp_obj_type_t mp_type_fun_builtin_3 = {
+ { &mp_type_type },
+ .name = MP_QSTR_function,
+ .call = fun_builtin_3_call,
+ .unary_op = mp_generic_unary_op,
+};
+
+STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_var));
+ mp_obj_fun_builtin_var_t *self = MP_OBJ_TO_PTR(self_in);
// check number of arguments
mp_arg_check_num(n_args, n_kw, self->n_args_min, self->n_args_max, self->is_kw);
@@ -68,25 +123,6 @@ STATIC mp_obj_t fun_builtin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c
return self->fun.kw(n_args, args, &kw_args);
- } else if (self->n_args_min <= 3 && self->n_args_min == self->n_args_max) {
- // function requires a fixed number of arguments
-
- // dispatch function call
- switch (self->n_args_min) {
- case 0:
- return self->fun._0();
-
- case 1:
- return self->fun._1(args[0]);
-
- case 2:
- return self->fun._2(args[0], args[1]);
-
- case 3:
- default:
- return self->fun._3(args[0], args[1], args[2]);
- }
-
} else {
// function takes a variable number of arguments, but no keywords
@@ -94,10 +130,10 @@ STATIC mp_obj_t fun_builtin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c
}
}
-const mp_obj_type_t mp_type_fun_builtin = {
+const mp_obj_type_t mp_type_fun_builtin_var = {
{ &mp_type_type },
.name = MP_QSTR_function,
- .call = fun_builtin_call,
+ .call = fun_builtin_var_call,
.unary_op = mp_generic_unary_op,
};
diff --git a/py/objstr.h b/py/objstr.h
index e14568dac..ad2777afb 100644
--- a/py/objstr.h
+++ b/py/objstr.h
@@ -74,32 +74,32 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s
mp_obj_t index, bool is_slice);
const byte *find_subbytes(const byte *haystack, mp_uint_t hlen, const byte *needle, mp_uint_t nlen, mp_int_t direction);
-MP_DECLARE_CONST_FUN_OBJ(str_encode_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_find_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_rfind_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_index_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_rindex_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_join_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_split_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_splitlines_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_rsplit_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_startswith_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_endswith_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_strip_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_lstrip_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_rstrip_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_format_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_replace_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_count_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_partition_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_rpartition_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_center_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_lower_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_upper_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_isspace_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_isalpha_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_isdigit_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_isupper_obj);
-MP_DECLARE_CONST_FUN_OBJ(str_islower_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(str_join_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(str_splitlines_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj);
+MP_DECLARE_CONST_FUN_OBJ_KW(str_format_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(str_partition_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(str_rpartition_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(str_center_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(str_lower_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(str_upper_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(str_isspace_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(str_isalpha_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(str_isdigit_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(str_isupper_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(str_islower_obj);
#endif // __MICROPY_INCLUDED_PY_OBJSTR_H__
diff --git a/py/parse.c b/py/parse.c
index 5920828fe..397d46d9f 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -1010,9 +1010,10 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
// truncate final chunk and link into chain of chunks
if (parser.cur_chunk != NULL) {
- (void)m_renew(byte, parser.cur_chunk,
+ (void)m_renew_maybe(byte, parser.cur_chunk,
sizeof(mp_parse_chunk_t) + parser.cur_chunk->alloc,
- sizeof(mp_parse_chunk_t) + parser.cur_chunk->union_.used);
+ sizeof(mp_parse_chunk_t) + parser.cur_chunk->union_.used,
+ false);
parser.cur_chunk->alloc = parser.cur_chunk->union_.used;
parser.cur_chunk->union_.next = parser.tree.chunk;
parser.tree.chunk = parser.cur_chunk;
diff --git a/py/parsenum.c b/py/parsenum.c
index 1010ad305..b1c449c9b 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -227,7 +227,7 @@ mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool
} else {
if (in == PARSE_DEC_IN_FRAC) {
dec_val += dig * frac_mult;
- frac_mult *= 0.1;
+ frac_mult *= MICROPY_FLOAT_CONST(0.1);
} else {
dec_val = 10 * dec_val + dig;
}
diff --git a/py/py.mk b/py/py.mk
index ec476af0e..8cdccb9b4 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -230,13 +230,23 @@ PY_O_BASENAME = \
../extmod/vfs_fat_lexer.o \
../extmod/vfs_fat_misc.o \
../extmod/utime_mphal.o \
- ../extmod/moduos_dupterm.o \
+ ../extmod/uos_dupterm.o \
../lib/embed/abort_.o \
../lib/utils/printf.o \
# prepend the build destination prefix to the py object files
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
+# object file for frozen files
+ifneq ($(FROZEN_DIR),)
+PY_O += $(BUILD)/$(BUILD)/frozen.o
+endif
+
+# object file for frozen bytecode (frozen .mpy files)
+ifneq ($(FROZEN_MPY_DIR),)
+PY_O += $(BUILD)/$(BUILD)/frozen_mpy.o
+endif
+
# Sources that may contain qstrings
SRC_QSTR_IGNORE = nlr% emitnx% emitnthumb% emitnarm%
SRC_QSTR = $(SRC_MOD) $(addprefix py/,$(filter-out $(SRC_QSTR_IGNORE),$(PY_O_BASENAME:.o=.c)) emitnative.c)
diff --git a/py/qstr.c b/py/qstr.c
index 28df06ca3..5aa161064 100644
--- a/py/qstr.c
+++ b/py/qstr.c
@@ -199,7 +199,7 @@ qstr qstr_from_strn(const char *str, size_t len) {
byte *new_p = m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_alloc) + n_bytes, false);
if (new_p == NULL) {
// could not grow existing memory; shrink it to fit previous
- (void)m_renew(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_used));
+ (void)m_renew_maybe(byte, MP_STATE_VM(qstr_last_chunk), MP_STATE_VM(qstr_last_alloc), MP_STATE_VM(qstr_last_used), false);
MP_STATE_VM(qstr_last_chunk) = NULL;
} else {
// could grow existing memory
diff --git a/py/runtime.c b/py/runtime.c
index 6eda77ee9..c25557464 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -972,7 +972,13 @@ void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t
|| ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type->name == MP_QSTR_generator))) {
// only functions, closures and generators objects can be bound to self
#if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
- if (self == MP_OBJ_NULL && mp_obj_get_type(member) == &mp_type_fun_builtin) {
+ const mp_obj_type_t *m_type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type;
+ if (self == MP_OBJ_NULL
+ && (m_type == &mp_type_fun_builtin_0
+ || m_type == &mp_type_fun_builtin_1
+ || m_type == &mp_type_fun_builtin_2
+ || m_type == &mp_type_fun_builtin_3
+ || m_type == &mp_type_fun_builtin_var)) {
// we extracted a builtin method without a first argument, so we must
// wrap this function in a type checker
dest[0] = mp_obj_new_checked_fun(type, member);
diff --git a/py/sequence.c b/py/sequence.c
index 0acdd25be..bc2cfc077 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -53,15 +53,35 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice
mp_int_t start, stop;
mp_obj_slice_get(slice, &ostart, &ostop, &ostep);
+ if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
+ indexes->step = mp_obj_get_int(ostep);
+ if (indexes->step == 0) {
+ mp_raise_ValueError("slice step cannot be zero");
+ }
+ } else {
+ indexes->step = 1;
+ }
+
if (ostart == mp_const_none) {
- start = 0;
+ if (indexes->step > 0) {
+ start = 0;
+ } else {
+ start = len - 1;
+ }
} else {
start = mp_obj_get_int(ostart);
}
if (ostop == mp_const_none) {
- stop = len;
+ if (indexes->step > 0) {
+ stop = len;
+ } else {
+ stop = 0;
+ }
} else {
stop = mp_obj_get_int(ostop);
+ if (stop >= 0 && indexes->step < 0) {
+ stop += 1;
+ }
}
// Unlike subscription, out-of-bounds slice indexes are never error
@@ -70,29 +90,31 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice
if (start < 0) {
start = 0;
}
- } else if ((mp_uint_t)start > len) {
+ } else if (indexes->step > 0 && (mp_uint_t)start > len) {
start = len;
+ } else if (indexes->step < 0 && (mp_uint_t)start > len - 1) {
+ start = len - 1;
}
if (stop < 0) {
stop = len + stop;
+ if (indexes->step < 0) {
+ stop += 1;
+ }
} else if ((mp_uint_t)stop > len) {
stop = len;
}
// CPython returns empty sequence in such case, or point for assignment is at start
- if (start > stop) {
+ if (indexes->step > 0 && start > stop) {
stop = start;
+ } else if (indexes->step < 0 && start < stop) {
+ stop = start + 1;
}
indexes->start = start;
indexes->stop = stop;
- if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
- indexes->step = mp_obj_get_int(ostep);
- return false;
- }
- indexes->step = 1;
- return true;
+ return indexes->step == 1;
}
#endif
@@ -106,10 +128,9 @@ mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice
mp_obj_t res = mp_obj_new_list(0, NULL);
if (step < 0) {
- stop--;
- while (start <= stop) {
- mp_obj_list_append(res, seq[stop]);
- stop += step;
+ while (start >= stop) {
+ mp_obj_list_append(res, seq[start]);
+ start += step;
}
} else {
while (start < stop) {
diff --git a/py/stream.c b/py/stream.c
index cc8a63ac2..dadfcf5d6 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -391,7 +391,7 @@ STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args)
if (mp_is_nonblocking_error(error)) {
if (vstr.len == 1) {
// We just incremented it, but otherwise we read nothing
- // and immediately got EAGAIN. This is case is not well
+ // and immediately got EAGAIN. This case is not well
// specified in
// https://docs.python.org/3/library/io.html#io.IOBase.readline
// unlike similar case for read(). But we follow the latter's
diff --git a/py/stream.h b/py/stream.h
index 33d85e823..4cdea11eb 100644
--- a/py/stream.h
+++ b/py/stream.h
@@ -48,18 +48,18 @@ struct mp_stream_seek_t {
int whence;
};
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_read_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_read1_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_readinto_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_readall_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_unbuffered_readline_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_unbuffered_readlines_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_write_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_write1_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_seek_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_tell_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_flush_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_stream_ioctl_obj);
+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);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_readall_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj);
+MP_DECLARE_CONST_FUN_OBJ_2(mp_stream_write1_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_tell_obj);
+MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_flush_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj);
// these are for mp_get_stream_raise and can be or'd together
#define MP_STREAM_OP_READ (1)
diff --git a/py/warning.c b/py/warning.c
index eae145bd3..4cdf3b3f1 100644
--- a/py/warning.c
+++ b/py/warning.c
@@ -38,6 +38,7 @@ void mp_warning(const char *msg, ...) {
mp_print_str(&mp_plat_print, "Warning: ");
mp_vprintf(&mp_plat_print, msg, args);
mp_print_str(&mp_plat_print, "\n");
+ va_end(args);
}
void mp_emitter_warning(pass_kind_t pass, const char *msg) {