diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 1ce44ac8af..a5884b6ad9 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -46,6 +46,7 @@ #define MICROPY_PY_BUILTINS_SLICE (1) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY_BUILTINS_MIN_MAX (1) #define MICROPY_PY___FILE__ (1) diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index cdf06450c6..8caecf7594 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -49,6 +49,7 @@ #define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_COLLECTIONS (1) #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) #define MICROPY_PY_MATH (0) diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 053a3bbab2..e806c201f1 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -99,6 +99,7 @@ #define MICROPY_PY_ALL_SPECIAL_METHODS (0) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) +#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_PY_BUILTINS_SLICE_ATTRS (0) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_MAXSIZE (1) diff --git a/py/binary.c b/py/binary.c index 62cb384f18..bb334ed3db 100644 --- a/py/binary.c +++ b/py/binary.c @@ -57,8 +57,10 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) { size = 4; break; case 'q': case 'Q': size = 8; break; +#if MICROPY_NONSTANDARD_TYPECODES case 'P': case 'O': case 'S': size = sizeof(void*); break; +#endif case 'f': size = sizeof(float); break; case 'd': @@ -89,9 +91,11 @@ size_t mp_binary_get_size(char struct_type, char val_type, mp_uint_t *palign) { case 'q': case 'Q': align = alignof(long long); size = sizeof(long long); break; +#if MICROPY_NONSTANDARD_TYPECODES case 'P': case 'O': case 'S': align = alignof(void*); size = sizeof(void*); break; +#endif case 'f': align = alignof(float); size = sizeof(float); break; @@ -148,12 +152,14 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) { case 'd': return mp_obj_new_float(((double*)p)[index]); #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of objects case 'O': return ((mp_obj_t*)p)[index]; // Extension to CPython: array of pointers case 'P': return mp_obj_new_int((mp_int_t)(uintptr_t)((void**)p)[index]); +#endif } return MP_OBJ_NEW_SMALL_INT(val); } @@ -202,11 +208,13 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) { long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p); - if (val_type == 'O') { + if (MICROPY_NONSTANDARD_TYPECODES && (val_type == 'O')) { return (mp_obj_t)(mp_uint_t)val; +#if MICROPY_NONSTANDARD_TYPECODES } else if (val_type == 'S') { const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val; return mp_obj_new_str(s_val, strlen(s_val), false); +#endif #if MICROPY_PY_BUILTINS_FLOAT } else if (val_type == 'f') { union { uint32_t i; float f; } fpu = {val}; @@ -267,9 +275,11 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte ** mp_uint_t val; switch (val_type) { +#if MICROPY_NONSTANDARD_TYPECODES case 'O': val = (mp_uint_t)val_in; break; +#endif #if MICROPY_PY_BUILTINS_FLOAT case 'f': { union { uint32_t i; float f; } fp_sp; @@ -324,10 +334,12 @@ void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t v ((double*)p)[index] = mp_obj_get_float(val_in); break; #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of objects case 'O': ((mp_obj_t*)p)[index] = val_in; break; +#endif default: #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) { @@ -384,9 +396,11 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, m ((double*)p)[index] = val; break; #endif +#if MICROPY_NONSTANDARD_TYPECODES // Extension to CPython: array of pointers case 'P': ((void**)p)[index] = (void*)(uintptr_t)val; break; +#endif } } diff --git a/py/mpconfig.h b/py/mpconfig.h index 252ab7f371..765ae1e8f0 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -888,6 +888,12 @@ typedef double mp_float_t; #define MICROPY_PY_ARRAY_SLICE_ASSIGN (0) #endif +// Whether to support nonstandard typecodes "O", "P" and "S" +// in array and struct modules. +#ifndef MICROPY_NONSTANDARD_TYPECODES +#define MICROPY_NONSTANDARD_TYPECODES (1) +#endif + // Whether to support attrtuple type (MicroPython extension) // It provides space-efficient tuples with attribute access #ifndef MICROPY_PY_ATTRTUPLE diff --git a/py/objarray.c b/py/objarray.c index eb053bd8a9..c4c547e19f 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -470,9 +470,11 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value } else { mp_seq_replace_slice_no_grow(dest_items, o->len, slice.start, slice.stop, src_items, src_len, item_sz); +#if MICROPY_NONSTANDARD_TYPECODES // Clear "freed" elements at the end of list // TODO: This is actually only needed for typecode=='O' mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz); +#endif // TODO: alloc policy after shrinking } o->len += len_adj; diff --git a/shared-module/struct/__init__.c b/shared-module/struct/__init__.c index e944f77387..eac41c9c31 100644 --- a/shared-module/struct/__init__.c +++ b/shared-module/struct/__init__.c @@ -33,9 +33,11 @@ #include "py/parsenum.h" void struct_validate_format(char fmt) { +#if MICROPY_NONSTANDARD_TYPECODES if( fmt == 'S' || fmt == 'O') { mp_raise_RuntimeError("'S' and 'O' are not supported format types"); } +#endif } char get_fmt_type(const char **fmt) { diff --git a/tests/basics/array_micropython.py b/tests/basics/array_micropython.py index e26ad7ae96..b92c5a9b93 100644 --- a/tests/basics/array_micropython.py +++ b/tests/basics/array_micropython.py @@ -5,6 +5,12 @@ except ImportError: print("SKIP") raise SystemExit +try: + array.array('O') +except ValueError: + print("SKIP") + raise SystemExit + # arrays of objects a = array.array('O') a.append(1) diff --git a/tests/basics/struct_micropython.py b/tests/basics/struct_micropython.py index f203a4666f..e721530714 100644 --- a/tests/basics/struct_micropython.py +++ b/tests/basics/struct_micropython.py @@ -9,6 +9,12 @@ except: print("SKIP") raise SystemExit +try: + struct.pack('O', None) +except ValueError: + print("SKIP") + raise SystemExit + class A(): pass