diff options
author | Damien George <damien.p.george@gmail.com> | 2017-08-14 12:21:43 +1000 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2017-08-14 12:21:43 +1000 |
commit | 1db008349cc970fd83b85574492badbf0460ad51 (patch) | |
tree | 76ca40810fd44eec799ff01e3c3a753c494bae9e /py | |
parent | bb254ba0ea89ce60dd6deab94991b2651c00dff3 (diff) | |
parent | 3611dcc260cef08eaa497cea4e3ca17977848b6c (diff) | |
download | micropython-1db008349cc970fd83b85574492badbf0460ad51.tar.gz micropython-1db008349cc970fd83b85574492badbf0460ad51.zip |
Merge tag 'v1.8.4' into parse-bytecode
Support for stream decompression in uzlib, and more ESP8266 features
This release includes some bug fixes, code clean-up, updates to the docs,
more tests, and various feature additions. The uzlib module now supports
efficient stream decompression in the form of the uzlib.DecompIO class.
Freezing of bytecode now supports floats for the ESP8266 port, as well as
complex numbers for all ports. The stmhal port has ADC working on L4
microcontrollers, fixed initialisation for DAC, and addition of the
machine.WDT class and machine.reset_cause function.
For the ESP8266 port Pin(16) now works as an input pin and the hardware
SPI peripheral is exposed as machine.SPI(1). The os.umount function is
implemented and the port supports mounting of externally connected SD
cards. The machine.WDT class is added, wlan.scan() is fixed to return all
access points, and there is support for DS18S20 devices.
py core:
- runtime: factor out exception raising helpers
- runtime: define mp_check_self(pred) helper macro
- objdict: get rid of asserts (remove/replace with mp_check_self())
- get rid of assert() in method argument checking functions
- objtuple: in tuple_cmp_helper, use mp_check_self instead of raising
- objstr: use mp_raise_{Type,Value}Error instead of mp_raise_msg
- obj.h: for obj reprs A,B,C use void* explicitly for mp_obj_t typedef
- mpconfigport.h: remove typedef of machine_ptr_t, it's no longer needed
- sequence: allow to use bignums as indices in slice objects
- stream.c: use mp_obj_get_type in mp_get_stream_raise
- gc: add MICROPY_GC_CONSERVATIVE_CLEAR option to always zero memory
- compile: don't compile assert statements when optimisations enabled
- modstruct: use more compact mp_raise_ValueError function
- emitglue: use more compact mp_raise_ValueError function
- rename struct mp_code_state to mp_code_state_t
- mkrules.mk: allow to override name of libmicropython.a
- mpprint: fail an assertion with unsupported format specifiers
- makeqstrdata.py: compute the qstr hash from bytes, not characters
- if str/bytes hash is 0 then explicitly compute it
- emitglue.c: provide mp_raw_code_load_file for any unix architecture
- add MICROPY_USE_INTERNAL_PRINTF option, defaults to enabled
extmod:
- modwebrepl: set_password(): raise exception for too long password
- uzlib/: update uzlib to v2.0: new API supporting stream decompression
- moduzlib: refactor to new stream-compatible uzlib 2.0 API
- uzlib/: update uzlib to v2.0.1: fixes for pedantic compiler warnings
- uzlib/: update uzlib to v2.0.2: consistently use stdint types
- modbtree: do CHECK_ERROR after __bt_seq()
- modubinascii: implement binascii.crc32
- modubinascii: make crc32() support configurable
- modframebuf: fix pixel accessor to return a 1-bit result
- add machine_spi with generic SPI C-protocol and helper methods
- modframebuf: fix fill and scroll when height not divisible by 8
- moduzlib: implement zlib stream decompressor class, DecompIO
- moduzlib: use mperrno.h for error constants
- modframebuf: include font from stmhal directory explicitly
- moduzlib: support wbits arg to DecompIO
- framebuf: add the xstep!=0 case to scroll() method
lib:
- utils/stdout_helpers: fix function signature to match py/mphal.h
- berkeley-db-1.xx: update to upstream, fixes MacOSX build
- utils/pyexec: qstr_pool_info() requires size_t* parameters
drivers:
- sdcard: port the SDCard driver to new machine API, with backwards
compatibility for pyboard
tools:
- mpy-tool.py: support freezing float literals with obj-repr C
- mpy-tool.py: store qstr config values in global config object
- mpy-tool.py: compute the hash value for str/bytes objects
- mpy-tool.py: support freezing of complex numbers
tests:
- rename zlibd_decompress.py -> uzlib_decompress.py
- basics: add more tuple tests to improve coverage testing
- basics: add more list tests to improve coverage testing
- misc/non_compliant: add tests to improve coverage testing
- basics: add test for break from within try within a for-loop
- basics: add a test file for overriding special methods
- basics/special_methods: enable tests for extra special methods
- uzlib_decompress: actually test raw DEFLATE stream
- run-tests: disable thread/thread_lock4.py on Travis
- run-tests: disable thread/stress_heap.py when running on Travis
- cmdline: add test for -O option to check optimisation value
- extmod/vfs_fat_ramdisk: add tests for VFS.umount()
- run-tests: disable thread_gc1.py test on Travis
- unix/extra_coverage: add test for str/bytes with invalid hash
- extmod: add test for uzlib.DecompIO
- extmod: add a test for framebuf module, tested by coverage build
- extmod/uzlib_decompio: add zlib bitstream testcases
- extmod/framebuf1: add tests for scrolling in the x-direction
- run-tests: disable thread/stress_recurse.py test on Travis
unix port:
- mpconfigport.h: don't include stdio.h on MacOS
- when find'ing frozen files don't use extra slash, do follow symlinks
qemu-arm port:
- enable MICROPY_PY_ALL_SPECIAL_METHODS
stmhal port:
- boards: update STM32L476 pin defs to include ADC channels
- adc.c: get ADC working on STM32L4 MCUs
- fix timer capture/compare interrupt handling for TIM1 and TIM8
- remove obsolete code for special handling of TIM3 irq settings
- make ADC channel 16 available on L4 MCUs
- update pin print to print new constants
- modusocket: set self->nic to MP_OBJ_NULL after socket close
- update boot.py files to use VCP instead of CDC
- spi: factor out SPI transfer code to a single function
- spi: support new machine SPI methods in legacy SPI object
- add machine.WDT class
- set STM32F7DISC CPU Frequency to 216 MHz
- dac: fix DAC (re-)initialisation by resetting DMA
- wdt: implement keyword args to WDT constructor
- modmachine: implement machine.reset_cause() function, and consts
- machine.POWER_ON is renamed to machine.PWRON_RESET
- when find'ing frozen files don't use extra slash, do follow symlinks
cc3200 port:
- add machine.PWRON_RESET constant (machine.POWER_ON is now deprecated)
teensy port:
- fix execution of frozen boot.py and main.py
esp8266 port:
- fix reading of pin object for GPIO16; Pin(16) now works as an input
- PULL_UP is not supported on Pin(16), so raise an exception in this case
- enable support for all special methods
- modpybhspi: add a HSPI module for hardware SPI support
- modmachinespi: add a factory method for SoftSPI/HSPI
- esp_mphal: no longer disable watchdog on startup
- modpybrtc: use 64-bit arithmetic when computing alarm expiry
- hspi: enable duplex operation of hardware SPI
- modous: add os.umount method to unmount a filesystem
- modmachinewdt: implement machine.WDT class
- modules: split onewire.py into OneWire and DS18X20 driver
- modules/onewire: change onewire.read() to onewire.readinto()
- modules/ds18x20.py: add support for DS18S20 devices
- modpybspi: use generic SPI helper methods to implement SPI
- modpybhspi: simplify HSPI driver by using 1 function for xfers
- modmachinewdt: add .deinit() method
- modmachine: add WDT_RESET and SOFT_RESET constants
- modmachine: don't expose internal SoftSPI and HSPI classes
- modmachine: simplify SPI class implementation multiplexing
- espneopixel: disable IRQs during eps.neopixel_write
- modnetwork: fix wlan.scan() method so it returns all networks
- modmachine: map PWR_ON_RESET to vendor's REASON_DEFAULT_RST
- machine.PWR_ON_RESET is renamed to machine.PWRON_RESET
- when find'ing frozen files don't use extra slash, do follow symlinks
docs:
- esp8266/tutorial/pins: fix typo in commands for pin input mode
- esp8266/intro: add command to install esptool.py 1.0.1 via pip
- library/machine.WDT: add note that WDT is only available on WiPy
- esp8266/quickref: fix and update the SPI docs
- esp8266: update quickref and tutorial for OneWire/DS18X20 driver
- pyboard: update USB mouse tutorial to use VCP instead of CDC
- pyboard: update USB mouse tutorial to use pyb.USB_HID()
- library: add reference for pyb.usb_mode and pyb.USB_HID
- pyboard/quickref: add links to pinouts for other pyboard variants
- pyboard/quickref: add section on "delay and timing" for utime mod
- esp8266/quickref: add internal links to docs for some modules
- esp8266/quickref: update information on SPI classes
- esp8266/quickref: further improvements for SPI subsections
- library/machine.WDT: add that WDT is available on pyboard
- reference/isr_rules.rst: two minor additions to docs for using ISR
misc:
- add *.pyc to .gitignore, because Python 2 doesn't use __pycache__
- build mpy-cross as part of the Travis process
Diffstat (limited to 'py')
-rw-r--r-- | py/bc.c | 2 | ||||
-rw-r--r-- | py/bc.h | 14 | ||||
-rw-r--r-- | py/compile.c | 5 | ||||
-rw-r--r-- | py/emitglue.c | 11 | ||||
-rw-r--r-- | py/emitnative.c | 6 | ||||
-rw-r--r-- | py/gc.c | 10 | ||||
-rw-r--r-- | py/makeqstrdata.py | 19 | ||||
-rw-r--r-- | py/malloc.c | 3 | ||||
-rw-r--r-- | py/mkrules.mk | 5 | ||||
-rw-r--r-- | py/modbuiltins.c | 3 | ||||
-rw-r--r-- | py/modstruct.c | 10 | ||||
-rw-r--r-- | py/mpconfig.h | 23 | ||||
-rw-r--r-- | py/mpprint.c | 4 | ||||
-rw-r--r-- | py/obj.h | 10 | ||||
-rw-r--r-- | py/objdict.c | 32 | ||||
-rw-r--r-- | py/objfilter.c | 2 | ||||
-rw-r--r-- | py/objfun.c | 14 | ||||
-rw-r--r-- | py/objgenerator.c | 4 | ||||
-rw-r--r-- | py/objlist.c | 32 | ||||
-rw-r--r-- | py/objmap.c | 2 | ||||
-rw-r--r-- | py/objproperty.c | 2 | ||||
-rw-r--r-- | py/objreversed.c | 2 | ||||
-rw-r--r-- | py/objset.c | 6 | ||||
-rw-r--r-- | py/objstr.c | 104 | ||||
-rw-r--r-- | py/objstr.h | 1 | ||||
-rw-r--r-- | py/objtuple.c | 10 | ||||
-rw-r--r-- | py/objzip.c | 2 | ||||
-rw-r--r-- | py/py.mk | 2 | ||||
-rw-r--r-- | py/runtime.c | 18 | ||||
-rw-r--r-- | py/runtime.h | 17 | ||||
-rw-r--r-- | py/sequence.c | 6 | ||||
-rw-r--r-- | py/stream.c | 6 | ||||
-rw-r--r-- | py/vm.c | 10 |
33 files changed, 224 insertions, 173 deletions
@@ -89,7 +89,7 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) { // - code_state->ip should contain the offset in bytes from the start of // the bytecode chunk to just after n_state and n_exc_stack // - code_state->n_state should be set to the state size (locals plus stack) -void mp_setup_code_state(mp_code_state *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { +void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { // This function is pretty complicated. It's main aim is to be efficient in speed and RAM // usage for the common case of positional only args. size_t n_state = code_state->n_state; @@ -60,7 +60,7 @@ // constN : obj // Exception stack entry -typedef struct _mp_exc_stack { +typedef struct _mp_exc_stack_t { const byte *handler; // bit 0 is saved currently_in_except_block value // bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY @@ -69,7 +69,7 @@ typedef struct _mp_exc_stack { mp_obj_base_t *prev_exc; } mp_exc_stack_t; -typedef struct _mp_code_state { +typedef struct _mp_code_state_t { const byte *code_info; const byte *ip; const mp_uint_t *const_table; @@ -78,21 +78,21 @@ typedef struct _mp_code_state { mp_exc_stack_t *exc_sp; mp_obj_dict_t *old_globals; #if MICROPY_STACKLESS - struct _mp_code_state *prev; + struct _mp_code_state_t *prev; #endif size_t n_state; // Variable-length mp_obj_t state[0]; // Variable-length, never accessed by name, only as (void*)(state + n_state) //mp_exc_stack_t exc_state[0]; -} mp_code_state; +} mp_code_state_t; mp_uint_t mp_decode_uint(const byte **ptr); -mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc); -mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args); +mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc); +mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args); struct _mp_obj_fun_bc_t; -void mp_setup_code_state(mp_code_state *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args); +void mp_setup_code_state(mp_code_state_t *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args); void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table); void mp_bytecode_print2(const byte *code, mp_uint_t len); const byte *mp_bytecode_print_str(const byte *ip); diff --git a/py/compile.c b/py/compile.c index df6dab063c..c8b4e5470d 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1200,6 +1200,11 @@ STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) } STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { + // with optimisations enabled we don't compile assertions + if (MP_STATE_VM(mp_optimise_value) != 0) { + return; + } + uint l_end = comp_next_label(comp); c_if_cond(comp, pns->nodes[0], true, l_end); EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython diff --git a/py/emitglue.c b/py/emitglue.c index 59bca781ef..f544ae2944 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -349,12 +349,10 @@ mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) { byte header[4]; read_bytes(reader, header, sizeof(header)); if (strncmp((char*)header, "M\x00", 2) != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "invalid .mpy file")); + mp_raise_ValueError("invalid .mpy file"); } if (header[2] != MPY_FEATURE_FLAGS || header[3] > mp_small_int_bits()) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "incompatible .mpy file")); + mp_raise_ValueError("incompatible .mpy file"); } return load_raw_code(reader); } @@ -382,7 +380,7 @@ mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) { // here we define mp_raw_code_load_file depending on the port // TODO abstract this away properly -#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || (defined(__arm__) && (defined(__unix__))) +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || defined(__unix__) // unix file reader #include <sys/stat.h> @@ -560,8 +558,7 @@ STATIC void save_bytecode_qstrs(mp_print_t *print, const byte *ip, const byte *i STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc) { if (rc->kind != MP_CODE_BYTECODE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "can only save bytecode")); + mp_raise_ValueError("can only save bytecode"); } // save bytecode diff --git a/py/emitnative.c b/py/emitnative.c index 9adaabc11c..2cf4711feb 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -628,7 +628,7 @@ STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg); STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num); STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num); -#define STATE_START (sizeof(mp_code_state) / sizeof(mp_uint_t)) +#define STATE_START (sizeof(mp_code_state_t) / sizeof(mp_uint_t)) STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope); @@ -775,10 +775,10 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // set code_state.ip (offset from start of this function to prelude info) // XXX this encoding may change size - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state, ip) / sizeof(mp_uint_t), REG_ARG_1); + ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(mp_uint_t), REG_ARG_1); // set code_state.n_state - ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state, n_state) / sizeof(mp_uint_t), REG_ARG_1); + ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state_t, n_state) / sizeof(mp_uint_t), REG_ARG_1); // put address of code_state into first arg ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1); @@ -480,12 +480,17 @@ found: GC_EXIT(); + #if MICROPY_GC_CONSERVATIVE_CLEAR + // be conservative and zero out all the newly allocated blocks + memset((byte*)ret_ptr, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK); + #else // zero out the additional bytes of the newly allocated blocks // This is needed because the blocks may have previously held pointers // to the heap and will not be set to something else if the caller // doesn't actually use the entire block. As such they will continue // to point to the heap and may prevent other blocks from being reclaimed. memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes); + #endif #if MICROPY_ENABLE_FINALISER if (has_finaliser) { @@ -713,8 +718,13 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { GC_EXIT(); + #if MICROPY_GC_CONSERVATIVE_CLEAR + // be conservative and zero out all the newly allocated blocks + memset((byte*)ptr_in + n_blocks * BYTES_PER_BLOCK, 0, (new_blocks - n_blocks) * BYTES_PER_BLOCK); + #else // zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc) memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes); + #endif #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(); diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 8a3136b1f1..7249769f47 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -14,11 +14,13 @@ import sys # - codepoint2name lives in a different module import platform if platform.python_version_tuple()[0] == '2': - ord_bytes = ord + bytes_cons = lambda val, enc=None: bytearray(val) from htmlentitydefs import codepoint2name elif platform.python_version_tuple()[0] == '3': - ord_bytes = lambda x:x + bytes_cons = bytes from html.entities import codepoint2name +# end compatibility code + codepoint2name[ord('-')] = 'hyphen'; # add some custom names to map characters that aren't in HTML @@ -52,8 +54,8 @@ codepoint2name[ord('~')] = 'tilde' # this must match the equivalent function in qstr.c def compute_hash(qstr, bytes_hash): hash = 5381 - for char in qstr: - hash = (hash * 33) ^ ord(char) + for b in qstr: + hash = (hash * 33) ^ b # Make sure that valid hash is never zero, zero means "hash not computed" return (hash & ((1 << (8 * bytes_hash)) - 1)) or 1 @@ -115,16 +117,15 @@ def parse_input_headers(infiles): return qcfgs, qstrs def make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr): - qhash = compute_hash(qstr, cfg_bytes_hash) + qbytes = bytes_cons(qstr, 'utf8') + qlen = len(qbytes) + qhash = compute_hash(qbytes, cfg_bytes_hash) if all(32 <= ord(c) <= 126 and c != '\\' and c != '"' for c in qstr): # qstr is all printable ASCII so render it as-is (for easier debugging) - qlen = len(qstr) qdata = qstr else: # qstr contains non-printable codes so render entire thing as hex pairs - qbytes = qstr.encode('utf8') - qlen = len(qbytes) - qdata = ''.join(('\\x%02x' % ord_bytes(b)) for b in qbytes) + qdata = ''.join(('\\x%02x' % b) for b in qbytes) if qlen >= (1 << (8 * cfg_bytes_len)): print('qstr is too long:', qstr) assert False diff --git a/py/malloc.c b/py/malloc.c index b0493d9341..f48cb8da4f 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -117,7 +117,10 @@ void *m_malloc0(size_t num_bytes) { if (ptr == NULL && num_bytes != 0) { return 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 memset(ptr, 0, num_bytes); + #endif return ptr; } diff --git a/py/mkrules.mk b/py/mkrules.mk index 3cf0e30584..a3a408dc89 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -123,8 +123,9 @@ clean-prog: .PHONY: clean-prog endif -lib: $(OBJ) - $(AR) rcs libmicropython.a $^ +LIBMICROPYTHON = libmicropython.a +lib $(LIBMICROPYTHON): $(OBJ) + $(AR) rcs $(LIBMICROPYTHON) $^ clean: $(RM) -rf $(BUILD) $(CLEAN_EXTRA) diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 87446f7fae..ac3d3041f5 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -376,7 +376,6 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord); STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) { - assert(2 <= n_args && n_args <= 3); switch (n_args) { case 2: return mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]); default: return mp_binary_op(MP_BINARY_OP_MODULO, mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]), args[2]); // TODO optimise... @@ -492,7 +491,6 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj, 1, 2, mp_builtin_round); STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) { - assert(1 <= n_args && n_args <= 2); mp_obj_t value; switch (n_args) { case 1: value = MP_OBJ_NEW_SMALL_INT(0); break; @@ -508,7 +506,6 @@ STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum); STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - assert(n_args >= 1); if (n_args > 1) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "must use keyword argument for key function")); diff --git a/py/modstruct.c b/py/modstruct.c index 2016add17e..be0d0110de 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -114,7 +114,7 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { mp_uint_t align; size_t sz = mp_binary_get_size(fmt_type, *fmt, &align); if (sz == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "unsupported format")); + mp_raise_ValueError("unsupported format"); } while (cnt--) { // Apply alignment @@ -149,7 +149,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { // negative offsets are relative to the end of the buffer offset = bufinfo.len + offset; if (offset < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small")); + mp_raise_ValueError("buffer too small"); } } p += offset; @@ -164,7 +164,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { sz = get_fmt_num(&fmt); } if (p + sz > end_p) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small")); + mp_raise_ValueError("buffer too small"); } mp_obj_t item; if (*fmt == 's') { @@ -197,7 +197,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, byte* end_p, siz sz = get_fmt_num(&fmt); } if (p + sz > end_p) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small")); + mp_raise_ValueError("buffer too small"); } if (*fmt == 's') { @@ -240,7 +240,7 @@ STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) { // negative offsets are relative to the end of the buffer offset = (mp_int_t)bufinfo.len + offset; if (offset < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small")); + mp_raise_ValueError("buffer too small"); } } byte *p = (byte *)bufinfo.buf; diff --git a/py/mpconfig.h b/py/mpconfig.h index 3808df7430..e33a41f7a0 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -107,6 +107,15 @@ #define MICROPY_ALLOC_GC_STACK_SIZE (64) #endif +// 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. +// 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) +#endif + // Support automatic GC when reaching allocation threshold, // configurable by gc.threshold(). #ifndef MICROPY_GC_ALLOC_THRESHOLD @@ -572,6 +581,11 @@ typedef double mp_float_t; #define MICROPY_USE_INTERNAL_ERRNO (0) #endif +// Whether to use internally defined *printf() functions (otherwise external ones) +#ifndef MICROPY_USE_INTERNAL_PRINTF +#define MICROPY_USE_INTERNAL_PRINTF (1) +#endif + // Support for user-space VFS mount (selected ports) #ifndef MICROPY_FSUSERMOUNT #define MICROPY_FSUSERMOUNT (0) @@ -887,6 +901,11 @@ typedef double mp_float_t; #define MICROPY_PY_UBINASCII (0) #endif +// Depends on MICROPY_PY_UZLIB +#ifndef MICROPY_PY_UBINASCII_CRC32 +#define MICROPY_PY_UBINASCII_CRC32 (0) +#endif + #ifndef MICROPY_PY_URANDOM #define MICROPY_PY_URANDOM (0) #endif @@ -909,6 +928,10 @@ typedef double mp_float_t; #define MICROPY_PY_MACHINE_I2C (0) #endif +#ifndef MICROPY_PY_MACHINE_SPI +#define MICROPY_PY_MACHINE_SPI (0) +#endif + #ifndef MICROPY_PY_USSL #define MICROPY_PY_USSL (0) #endif diff --git a/py/mpprint.c b/py/mpprint.c index cb49b1227a..97ea33ad2a 100644 --- a/py/mpprint.c +++ b/py/mpprint.c @@ -537,10 +537,12 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { chrs += mp_print_int(print, arg_value, *fmt == 'd', 10, 'a', flags, fill, width); break; } - // fall through to default case to print unknown format char + assert(!"unsupported fmt char"); } #endif default: + // if it's not %% then it's an unsupported format character + assert(*fmt == '%' || !"unsupported fmt char"); print->print_strn(print->data, fmt, 1); chrs += 1; break; @@ -31,15 +31,15 @@ #include "py/qstr.h" #include "py/mpprint.h" -// All Micro Python objects are at least this type -// The bit-size must be at least pointer size - +// This is the definition of the opaque MicroPython object type. +// All concrete objects have an encoding within this type and the +// particular encoding is specified by MICROPY_OBJ_REPR. #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D typedef uint64_t mp_obj_t; typedef uint64_t mp_const_obj_t; #else -typedef machine_ptr_t mp_obj_t; -typedef machine_const_ptr_t mp_const_obj_t; +typedef void *mp_obj_t; +typedef const void *mp_const_obj_t; #endif // This mp_obj_type_t struct is a concrete MicroPython object which holds info diff --git a/py/objdict.c b/py/objdict.c index 91d5b75e2b..7a74557dc1 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -223,7 +223,7 @@ STATIC mp_obj_t dict_getiter(mp_obj_t self_in) { /* dict methods */ STATIC mp_obj_t dict_clear(mp_obj_t self_in) { - assert(MP_OBJ_IS_DICT_TYPE(self_in)); + mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_clear(&self->map); @@ -233,7 +233,7 @@ STATIC mp_obj_t dict_clear(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear); STATIC mp_obj_t dict_copy(mp_obj_t self_in) { - assert(MP_OBJ_IS_DICT_TYPE(self_in)); + mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t other_out = mp_obj_new_dict(self->map.alloc); mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out); @@ -249,7 +249,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy); // this is a classmethod STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) { - assert(2 <= n_args && n_args <= 3); mp_obj_t iter = mp_getiter(args[1]); mp_obj_t len = mp_obj_len_maybe(iter); mp_obj_t value = mp_const_none; @@ -303,8 +302,7 @@ STATIC mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp } STATIC mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) { - assert(2 <= n_args && n_args <= 3); - assert(MP_OBJ_IS_DICT_TYPE(args[0])); + mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); return dict_get_helper(&self->map, @@ -315,8 +313,7 @@ STATIC mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get); STATIC mp_obj_t dict_pop(size_t n_args, const mp_obj_t *args) { - assert(2 <= n_args && n_args <= 3); - assert(MP_OBJ_IS_DICT_TYPE(args[0])); + mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); return dict_get_helper(&self->map, @@ -328,8 +325,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop); STATIC mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) { - assert(2 <= n_args && n_args <= 3); - assert(MP_OBJ_IS_DICT_TYPE(args[0])); + mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); return dict_get_helper(&self->map, @@ -341,7 +337,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { - assert(MP_OBJ_IS_DICT_TYPE(self_in)); + mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); @@ -359,7 +355,7 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem); STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - assert(MP_OBJ_IS_DICT_TYPE(args[0])); + mp_check_self(MP_OBJ_IS_DICT_TYPE(args[0])); mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]); mp_arg_check_num(n_args, kwargs->used, 1, 2, true); @@ -438,7 +434,7 @@ typedef struct _mp_obj_dict_view_t { } mp_obj_dict_view_t; STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type)); mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur); @@ -467,7 +463,7 @@ STATIC const mp_obj_type_t dict_view_it_type = { }; STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) { - assert(MP_OBJ_IS_TYPE(view_in, &dict_view_type)); + mp_check_self(MP_OBJ_IS_TYPE(view_in, &dict_view_type)); mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in); mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t); o->base.type = &dict_view_it_type; @@ -479,7 +475,7 @@ STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) { STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; - assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &dict_view_type)); mp_obj_dict_view_t *self = MP_OBJ_TO_PTR(self_in); bool first = true; mp_print_str(print, mp_dict_view_names[self->kind]); @@ -525,7 +521,7 @@ STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) { } STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) { - assert(MP_OBJ_IS_DICT_TYPE(self_in)); + mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); return mp_obj_new_dict_view(self_in, kind); } @@ -612,21 +608,21 @@ mp_uint_t mp_obj_dict_len(mp_obj_t self_in) { } mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) { - assert(MP_OBJ_IS_DICT_TYPE(self_in)); + mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; return self_in; } mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) { - assert(MP_OBJ_IS_DICT_TYPE(self_in)); + mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); dict_get_helper(&self->map, key, MP_OBJ_NULL, MP_MAP_LOOKUP_REMOVE_IF_FOUND); return self_in; } mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) { - assert(MP_OBJ_IS_DICT_TYPE(self_in)); + mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in)); mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); return &self->map; } diff --git a/py/objfilter.c b/py/objfilter.c index e288102d38..a5c85b2cef 100644 --- a/py/objfilter.c +++ b/py/objfilter.c @@ -44,7 +44,7 @@ STATIC mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t } STATIC mp_obj_t filter_iternext(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_filter)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_filter)); mp_obj_filter_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t next; while ((next = mp_iternext(self->iter)) != MP_OBJ_STOP_ITERATION) { diff --git a/py/objfun.c b/py/objfun.c index 293d06427d..3fd25fb224 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -165,7 +165,7 @@ STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) { #define VM_DETECT_STACK_OVERFLOW (0) #if MICROPY_STACKLESS -mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { MP_STACK_CHECK(); mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); @@ -178,8 +178,8 @@ mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, // allocate state for locals and stack size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); - mp_code_state *code_state; - code_state = m_new_obj_var_maybe(mp_code_state, byte, state_size); + mp_code_state_t *code_state; + code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); if (!code_state) { return NULL; } @@ -220,12 +220,12 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const // allocate state for locals and stack mp_uint_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t); - mp_code_state *code_state = NULL; + mp_code_state_t *code_state = NULL; if (state_size > VM_MAX_STATE_ON_STACK) { - code_state = m_new_obj_var_maybe(mp_code_state, byte, state_size); + code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); } if (code_state == NULL) { - code_state = alloca(sizeof(mp_code_state) + state_size); + code_state = alloca(sizeof(mp_code_state_t) + state_size); state_size = 0; // indicate that we allocated using alloca } @@ -287,7 +287,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const // free the state if it was allocated on the heap if (state_size != 0) { - m_del_var(mp_code_state, byte, state_size, code_state); + m_del_var(mp_code_state_t, byte, state_size, code_state); } if (vm_return_kind == MP_VM_RETURN_NORMAL) { diff --git a/py/objgenerator.c b/py/objgenerator.c index 2480b0a4b8..8c32a36496 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -46,7 +46,7 @@ typedef struct _mp_obj_gen_wrap_t { typedef struct _mp_obj_gen_instance_t { mp_obj_base_t base; mp_obj_dict_t *globals; - mp_code_state code_state; + mp_code_state_t code_state; } mp_obj_gen_instance_t; STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { @@ -96,7 +96,7 @@ STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_pri } mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance)); mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); if (self->code_state.ip == 0) { // Trying to resume already stopped generator diff --git a/py/objlist.c b/py/objlist.c index df6b1bc99a..b5e8b99651 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -89,7 +89,7 @@ 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) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) { return false; } @@ -156,7 +156,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)) { - assert(0); + mp_not_implemented(""); } mp_int_t len_adj = slice.start - slice.stop; @@ -192,11 +192,11 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { #if MICROPY_PY_BUILTINS_SLICE if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); - assert(MP_OBJ_IS_TYPE(value, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(value, &mp_type_list)); mp_obj_list_t *slice = MP_OBJ_TO_PTR(value); mp_bound_slice_t slice_out; if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) { - assert(0); + mp_not_implemented(""); } mp_int_t len_adj = slice->len - (slice_out.stop - slice_out.start); //printf("Len adj: %d\n", len_adj); @@ -230,7 +230,7 @@ STATIC mp_obj_t list_getiter(mp_obj_t o_in) { } mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); if (self->len >= self->alloc) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2); @@ -242,7 +242,7 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { } STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) { mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_list_t *arg = MP_OBJ_TO_PTR(arg_in); @@ -263,8 +263,7 @@ STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { } STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { - assert(1 <= n_args && n_args <= 2); - assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]); if (self->len == 0) { nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list")); @@ -324,7 +323,7 @@ mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args); - assert(MP_OBJ_IS_TYPE(pos_args[0], &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(pos_args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(pos_args[0]); if (self->len > 1) { @@ -337,7 +336,7 @@ mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ } STATIC mp_obj_t list_clear(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); self->len = 0; self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC); @@ -347,26 +346,25 @@ STATIC mp_obj_t list_clear(mp_obj_t self_in) { } STATIC mp_obj_t list_copy(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_list(self->len, self->items); } STATIC mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); return mp_seq_count_obj(self->items, self->len, value); } STATIC mp_obj_t list_index(size_t n_args, const mp_obj_t *args) { - assert(2 <= n_args && n_args <= 4); - assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]); return mp_seq_index_obj(self->items, self->len, n_args, args); } STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); // insert has its own strange index logic mp_int_t index = MP_OBJ_SMALL_INT_VALUE(idx); @@ -391,7 +389,7 @@ STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) { } mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_t args[] = {self_in, value}; args[1] = list_index(2, args); list_pop(2, args); @@ -400,7 +398,7 @@ mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) { } STATIC mp_obj_t list_reverse(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t len = self->len; diff --git a/py/objmap.c b/py/objmap.c index 526bc05600..ed0291435d 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -49,7 +49,7 @@ STATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ } STATIC mp_obj_t map_iternext(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_map)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_map)); mp_obj_map_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters); diff --git a/py/objproperty.c b/py/objproperty.c index 618f517e74..8189935d20 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -100,7 +100,7 @@ const mp_obj_type_t mp_type_property = { }; const mp_obj_t *mp_obj_property_get(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_property)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_property)); mp_obj_property_t *self = MP_OBJ_TO_PTR(self_in); return self->proxy; } diff --git a/py/objreversed.c b/py/objreversed.c index 1e54bb522a..4343c19780 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -57,7 +57,7 @@ STATIC mp_obj_t reversed_make_new(const mp_obj_type_t *type, size_t n_args, size } STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_reversed)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_reversed)); mp_obj_reversed_t *self = MP_OBJ_TO_PTR(self_in); // "raise" stop iteration if we are at the end (the start) of the sequence diff --git a/py/objset.c b/py/objset.c index 8730918c15..fb89c07f3d 100644 --- a/py/objset.c +++ b/py/objset.c @@ -224,8 +224,6 @@ STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard); STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) { - assert(n_args > 0); - mp_obj_t self; if (update) { check_set(args[0]); @@ -443,8 +441,6 @@ STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) { } STATIC mp_obj_t set_update(size_t n_args, const mp_obj_t *args) { - assert(n_args > 0); - for (mp_uint_t i = 1; i < n_args; i++) { set_update_int(MP_OBJ_TO_PTR(args[0]), args[i]); } @@ -587,7 +583,7 @@ mp_obj_t mp_obj_new_set(mp_uint_t n_args, mp_obj_t *items) { } void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_set)); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } diff --git a/py/objstr.c b/py/objstr.c index a6ee617c03..406ccf290a 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -158,6 +158,9 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) { GET_STR_DATA_LEN(args[0], str_data, str_len); GET_STR_HASH(args[0], str_hash); + if (str_hash == 0) { + str_hash = qstr_compute_hash(str_data, str_len); + } 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; @@ -191,6 +194,9 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size } GET_STR_DATA_LEN(args[0], str_data, str_len); GET_STR_HASH(args[0], str_hash); + if (str_hash == 0) { + str_hash = qstr_compute_hash(str_data, str_len); + } mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len)); o->data = str_data; o->hash = str_hash; @@ -231,7 +237,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size mp_int_t val = mp_obj_get_int(item); #if MICROPY_CPYTHON_COMPAT if (val < 0 || val > 255) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bytes value out of range")); + mp_raise_ValueError("bytes value out of range"); } #endif vstr_add_byte(&vstr, val); @@ -240,7 +246,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); wrong_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "wrong number of arguments")); + mp_raise_TypeError("wrong number of arguments"); } // like strstr but with specified length and allows \0 bytes @@ -412,7 +418,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { - assert(MP_OBJ_IS_STR_OR_BYTES(self_in)); + mp_check_self(MP_OBJ_IS_STR_OR_BYTES(self_in)); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); // get separation string @@ -436,8 +442,8 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { mp_uint_t required_len = 0; for (mp_uint_t i = 0; i < seq_len; i++) { if (mp_obj_get_type(seq_items[i]) != self_type) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "join expects a list of str/bytes objects consistent with self object")); + mp_raise_TypeError( + "join expects a list of str/bytes objects consistent with self object"); } if (i > 0) { required_len += sep_len; @@ -511,7 +517,7 @@ mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) { const char *sep_str = mp_obj_str_get_data(sep, &sep_len); if (sep_len == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator")); + mp_raise_ValueError("empty separator"); } for (;;) { @@ -609,7 +615,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { const char *sep_str = mp_obj_str_get_data(sep, &sep_len); if (sep_len == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator")); + mp_raise_ValueError("empty separator"); } const byte *beg = s; @@ -648,8 +654,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t str_finder(mp_uint_t n_args, const mp_obj_t *args, mp_int_t direction, bool is_index) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - assert(2 <= n_args && n_args <= 4); - assert(MP_OBJ_IS_STR_OR_BYTES(args[0])); + mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0])); // check argument type if (mp_obj_get_type(args[1]) != self_type) { @@ -672,7 +677,7 @@ STATIC mp_obj_t str_finder(mp_uint_t n_args, const mp_obj_t *args, mp_int_t dire if (p == NULL) { // not found if (is_index) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "substring not found")); + mp_raise_ValueError("substring not found"); } else { return MP_OBJ_NEW_SMALL_INT(-1); } @@ -734,8 +739,7 @@ STATIC mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) { enum { LSTRIP, RSTRIP, STRIP }; STATIC mp_obj_t str_uni_strip(int type, mp_uint_t n_args, const mp_obj_t *args) { - assert(1 <= n_args && n_args <= 2); - assert(MP_OBJ_IS_STR_OR_BYTES(args[0])); + mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0])); const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); const byte *chars_to_del; @@ -878,7 +882,7 @@ STATIC mp_obj_t arg_as_int(mp_obj_t arg) { } STATIC NORETURN void terse_str_format_value_error(void) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad format string")); + mp_raise_ValueError("bad format string"); } STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { @@ -896,8 +900,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "single '}' encountered in format string")); + mp_raise_ValueError("single '}' encountered in format string"); } } if (*str != '{') { @@ -936,12 +939,11 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "bad conversion specifier")); + mp_raise_ValueError("bad conversion specifier"); } else { if (str >= top) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "end of format while looking for conversion specifier")); + mp_raise_ValueError( + "end of format while looking for conversion specifier"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unknown conversion specifier %c", *str)); @@ -975,16 +977,14 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "unmatched '{' in format")); + mp_raise_ValueError("unmatched '{' in format"); } } if (*str != '}') { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "expected ':' after format specifier")); + mp_raise_ValueError("expected ':' after format specifier"); } } @@ -997,13 +997,13 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "can't switch from automatic field numbering to manual field specification")); + mp_raise_ValueError( + "can't switch from automatic field numbering to manual field specification"); } } field_name = str_to_int(field_name, field_name_top, &index); if ((uint)index >= n_args - 1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range")); + mp_raise_msg(&mp_type_IndexError, "tuple index out of range"); } arg = args[index + 1]; *arg_i = -1; @@ -1026,12 +1026,12 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "can't switch from manual field specification to automatic field numbering")); + mp_raise_ValueError( + "can't switch from manual field specification to automatic field numbering"); } } if ((uint)*arg_i >= n_args - 1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range")); + mp_raise_msg(&mp_type_IndexError, "tuple index out of range"); } arg = args[(*arg_i) + 1]; (*arg_i)++; @@ -1120,8 +1120,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "invalid format specifier")); + mp_raise_ValueError("invalid format specifier"); } } vstr_clear(&format_spec_vstr); @@ -1142,16 +1141,15 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "sign not allowed in string format specifier")); + mp_raise_ValueError("sign not allowed in string format specifier"); } } if (type == 'c') { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "sign not allowed with integer format specifier 'c'")); + mp_raise_ValueError( + "sign not allowed with integer format specifier 'c'"); } } } else { @@ -1295,8 +1293,8 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "'=' alignment not allowed in string format specifier")); + mp_raise_ValueError( + "'=' alignment not allowed in string format specifier"); } } @@ -1331,7 +1329,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { - assert(MP_OBJ_IS_STR_OR_BYTES(args[0])); + mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0])); GET_STR_DATA_LEN(args[0], str, len); int arg_i = 0; @@ -1340,7 +1338,7 @@ mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs } STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_obj_t *args, mp_obj_t dict) { - assert(MP_OBJ_IS_STR_OR_BYTES(pattern)); + mp_check_self(MP_OBJ_IS_STR_OR_BYTES(pattern)); GET_STR_DATA_LEN(pattern, str, len); const byte *start_str = str; @@ -1372,8 +1370,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "incomplete format key")); + mp_raise_ValueError("incomplete format key"); } } ++str; @@ -1431,8 +1428,7 @@ incomplete_format: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { terse_str_format_value_error(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "incomplete format")); + mp_raise_ValueError("incomplete format"); } } @@ -1440,7 +1436,7 @@ incomplete_format: if (arg == MP_OBJ_NULL) { if ((uint)arg_i >= n_args) { not_enough_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "not enough arguments for format string")); + mp_raise_TypeError("not enough arguments for format string"); } arg = args[arg_i++]; } @@ -1450,16 +1446,14 @@ not_enough_args: mp_uint_t slen; const char *s = mp_obj_str_get_data(arg, &slen); if (slen != 1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "%%c requires int or char")); + mp_raise_TypeError("%%c requires int or char"); } mp_print_strn(&print, s, 1, flags, ' ', width); } else if (arg_looks_integer(arg)) { char ch = mp_obj_get_int(arg); mp_print_strn(&print, &ch, 1, flags, ' ', width); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "integer required")); + mp_raise_TypeError("integer required"); } break; @@ -1529,7 +1523,7 @@ not_enough_args: } if ((uint)arg_i != n_args) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "not all arguments converted during string formatting")); + mp_raise_TypeError("not all arguments converted during string formatting"); } return mp_obj_new_str_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr); @@ -1538,7 +1532,7 @@ not_enough_args: // The implementation is optimized, returning the original string if there's // nothing to replace. STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { - assert(MP_OBJ_IS_STR_OR_BYTES(args[0])); + mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0])); mp_int_t max_rep = -1; if (n_args == 4) { @@ -1644,8 +1638,7 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - assert(2 <= n_args && n_args <= 4); - assert(MP_OBJ_IS_STR_OR_BYTES(args[0])); + mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0])); // check argument type if (mp_obj_get_type(args[1]) != self_type) { @@ -1685,7 +1678,7 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { #if MICROPY_PY_BUILTINS_STR_PARTITION STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, mp_int_t direction) { - assert(MP_OBJ_IS_STR_OR_BYTES(self_in)); + mp_check_self(MP_OBJ_IS_STR_OR_BYTES(self_in)); mp_obj_type_t *self_type = mp_obj_get_type(self_in); if (self_type != mp_obj_get_type(arg)) { bad_implicit_conversion(arg); @@ -1695,7 +1688,7 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, mp_int_t directi GET_STR_DATA_LEN(arg, sep, sep_len); if (sep_len == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator")); + mp_raise_ValueError("empty separator"); } mp_obj_t result[3]; @@ -2061,8 +2054,7 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) { STATIC void bad_implicit_conversion(mp_obj_t self_in) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "can't convert to str implicitly")); + mp_raise_TypeError("can't convert to str implicitly"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert '%s' object to str implicitly", diff --git a/py/objstr.h b/py/objstr.h index 07929156cb..e14568dac4 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -39,6 +39,7 @@ typedef struct _mp_obj_str_t { #define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str} // use this macro to extract the string hash +// warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data #define GET_STR_HASH(str_obj_in, str_hash) \ mp_uint_t str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) \ { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->hash; } diff --git a/py/objtuple.c b/py/objtuple.c index c21390a603..c547da9406 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -104,10 +104,8 @@ 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) { - mp_obj_type_t *self_type = mp_obj_get_type(self_in); - if (self_type->getiter != mp_obj_tuple_getiter) { - assert(0); - } + // 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); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); if (another_type->getiter != mp_obj_tuple_getiter) { @@ -202,14 +200,14 @@ mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in) { } STATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); return mp_seq_count_obj(self->items, self->len, value); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count); STATIC mp_obj_t tuple_index(size_t n_args, const mp_obj_t *args) { - assert(MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)); + mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(args[0]); return mp_seq_index_obj(self->items, self->len, n_args, args); } diff --git a/py/objzip.c b/py/objzip.c index d4cd614a4c..6edefc3611 100644 --- a/py/objzip.c +++ b/py/objzip.c @@ -49,7 +49,7 @@ STATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ } STATIC mp_obj_t zip_iternext(mp_obj_t self_in) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_zip)); + mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_zip)); mp_obj_zip_t *self = MP_OBJ_TO_PTR(self_in); if (self->n_iters == 0) { return MP_OBJ_STOP_ITERATION; @@ -208,6 +208,7 @@ PY_O_BASENAME = \ ../extmod/machine_pinbase.o \ ../extmod/machine_pulse.o \ ../extmod/machine_i2c.o \ + ../extmod/machine_spi.o \ ../extmod/modussl_axtls.o \ ../extmod/modurandom.o \ ../extmod/modwebsocket.o \ @@ -222,6 +223,7 @@ PY_O_BASENAME = \ ../extmod/vfs_fat_misc.o \ ../extmod/moduos_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)) diff --git a/py/runtime.c b/py/runtime.c index f88c92be63..48e815f0fa 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -217,6 +217,10 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) { } else if (op == MP_UNARY_OP_HASH && MP_OBJ_IS_STR_OR_BYTES(arg)) { // fast path for hashing str/bytes GET_STR_HASH(arg, h); + if (h == 0) { + GET_STR_DATA_LEN(arg, data, len); + h = qstr_compute_hash(data, len); + } return MP_OBJ_NEW_SMALL_INT(h); } else { mp_obj_type_t *type = mp_obj_get_type(arg); @@ -1390,6 +1394,18 @@ void *m_malloc_fail(size_t num_bytes) { } } +NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg) { + nlr_raise(mp_obj_new_exception_msg(exc_type, msg)); +} + +NORETURN void mp_raise_ValueError(const char *msg) { + mp_raise_msg(&mp_type_ValueError, msg); +} + +NORETURN void mp_raise_TypeError(const char *msg) { + mp_raise_msg(&mp_type_TypeError, msg); +} + NORETURN void mp_not_implemented(const char *msg) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, msg)); + mp_raise_msg(&mp_type_NotImplementedError, msg); } diff --git a/py/runtime.h b/py/runtime.h index 3e325a31b3..06e68924b2 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -133,10 +133,23 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level); mp_obj_t mp_import_from(mp_obj_t module, qstr name); void mp_import_all(mp_obj_t module); -// Raise NotImplementedError with given message -NORETURN void mp_not_implemented(const char *msg); +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_not_implemented(const char *msg); // Raise NotImplementedError with given message NORETURN void mp_exc_recursion_depth(void); +#if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG +#undef mp_check_self +#define mp_check_self(pred) +#else +// A port may define to raise TypeError for example +#ifndef mp_check_self +#define mp_check_self(pred) assert(pred) +#endif +#endif + // helper functions for native/viper code mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type); mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type); diff --git a/py/sequence.c b/py/sequence.c index 6f715ff795..239f1b2cc5 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -56,12 +56,12 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice if (ostart == mp_const_none) { start = 0; } else { - start = MP_OBJ_SMALL_INT_VALUE(ostart); + start = mp_obj_get_int(ostart); } if (ostop == mp_const_none) { stop = len; } else { - stop = MP_OBJ_SMALL_INT_VALUE(ostop); + stop = mp_obj_get_int(ostop); } // Unlike subscription, out-of-bounds slice indexes are never error @@ -88,7 +88,7 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice indexes->stop = stop; if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) { - indexes->step = MP_OBJ_SMALL_INT_VALUE(ostep); + indexes->step = mp_obj_get_int(ostep); return false; } indexes->step = 1; diff --git a/py/stream.c b/py/stream.c index 473eb96904..eef9080b7b 100644 --- a/py/stream.c +++ b/py/stream.c @@ -94,8 +94,8 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { - mp_obj_base_t *o = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - const mp_stream_p_t *stream_p = o->type->protocol; + mp_obj_type_t *type = mp_obj_get_type(self_in); + const mp_stream_p_t *stream_p = type->protocol; if (stream_p == NULL || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) @@ -167,7 +167,7 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl // TODO what if we have read only half a non-ASCII char? vstr_cut_tail_bytes(&vstr, more_bytes - out_sz); if (out_sz == 0) { - break; + break; } } @@ -127,7 +127,7 @@ typedef enum { // MP_VM_RETURN_NORMAL, sp valid, return value in *sp // MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp // MP_VM_RETURN_EXCEPTION, exception in fastn[0] -mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc) { +mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) { #define SELECTIVE_EXC_IP (0) #if SELECTIVE_EXC_IP #define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */ @@ -904,7 +904,7 @@ unwind_jump:; code_state->ip = ip; code_state->sp = sp; code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block); - mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1); + mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1); if (new_state) { new_state->prev = code_state; code_state = new_state; @@ -940,7 +940,7 @@ unwind_jump:; mp_call_args_t out_args; mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args); - mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun, + mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args); m_del(mp_obj_t, out_args.args, out_args.n_alloc); if (new_state) { @@ -976,7 +976,7 @@ unwind_jump:; mp_uint_t n_kw = (unum >> 8) & 0xff; int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1; - mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust); + mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust); if (new_state) { new_state->prev = code_state; code_state = new_state; @@ -1011,7 +1011,7 @@ unwind_jump:; mp_call_args_t out_args; mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args); - mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun, + mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun, out_args.n_args, out_args.n_kw, out_args.args); m_del(mp_obj_t, out_args.args, out_args.n_alloc); if (new_state) { |