mirror of
https://github.com/micropython/micropython.git
synced 2025-12-26 23:00:16 +01:00
Compare commits
164 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dce8876dbe | ||
|
|
ac736f15c9 | ||
|
|
122c9db3db | ||
|
|
a1760a56ff | ||
|
|
b82f34edde | ||
|
|
2cf381081a | ||
|
|
564e46452d | ||
|
|
58c9586c34 | ||
|
|
2097c8b1e1 | ||
|
|
8215847b4d | ||
|
|
42b6419056 | ||
|
|
594699bc88 | ||
|
|
90ba80dc36 | ||
|
|
5fa5ca40e6 | ||
|
|
539681fffd | ||
|
|
0182385ab0 | ||
|
|
4e0eeebdc2 | ||
|
|
381618269a | ||
|
|
54eb4e723e | ||
|
|
40f3c02682 | ||
|
|
065aba5875 | ||
|
|
e4e55047b3 | ||
|
|
5e6419cb11 | ||
|
|
e70b5dbe58 | ||
|
|
92a47b4dae | ||
|
|
9cd96cf25d | ||
|
|
f83debc716 | ||
|
|
7a37f647a5 | ||
|
|
5fc580475f | ||
|
|
f0b29729aa | ||
|
|
f065344d3b | ||
|
|
aa47f3968b | ||
|
|
2fe841d2fa | ||
|
|
caa7334141 | ||
|
|
e95b6b5e07 | ||
|
|
0d81c133b3 | ||
|
|
5d44e6a92c | ||
|
|
4039a26679 | ||
|
|
b601d9574a | ||
|
|
5813efd634 | ||
|
|
bb35f425f9 | ||
|
|
c10a4405cd | ||
|
|
a23475979b | ||
|
|
ec6fa8732b | ||
|
|
8139494e54 | ||
|
|
9e215fa4c2 | ||
|
|
a62da515af | ||
|
|
5478ed18ea | ||
|
|
b1b840554d | ||
|
|
635b60e299 | ||
|
|
8546ce1e28 | ||
|
|
41736f8201 | ||
|
|
e04a44e2f6 | ||
|
|
b3a50f0f3e | ||
|
|
8993fb6cf0 | ||
|
|
7e4ec3bf4f | ||
|
|
81df1e6c98 | ||
|
|
cb78f862cb | ||
|
|
0a1ea40273 | ||
|
|
8a96ebea75 | ||
|
|
64c58403ef | ||
|
|
a75e382a9b | ||
|
|
3c8ce38d20 | ||
|
|
3659af97c5 | ||
|
|
ed07d035d5 | ||
|
|
f5f6c3b792 | ||
|
|
ce81312d8a | ||
|
|
63143c94ce | ||
|
|
ea2c936c7e | ||
|
|
26fda6dc8e | ||
|
|
00c904b47a | ||
|
|
1044c3dfe6 | ||
|
|
b1949e4c09 | ||
|
|
5048df0b7c | ||
|
|
46d31e9ca9 | ||
|
|
ded0fc77f7 | ||
|
|
17994d1bd3 | ||
|
|
79b7fe2ee5 | ||
|
|
cdc020da4b | ||
|
|
e7f2b4c875 | ||
|
|
86d3898e70 | ||
|
|
d215ee1dc1 | ||
|
|
9731912ccb | ||
|
|
165eb69b86 | ||
|
|
42a52516fe | ||
|
|
2ba2299d28 | ||
|
|
1e3781bc35 | ||
|
|
9a1a4beb56 | ||
|
|
64b468d873 | ||
|
|
83865347db | ||
|
|
c88987c1af | ||
|
|
12bc13eeb8 | ||
|
|
16ac4962ae | ||
|
|
7a8ab5a730 | ||
|
|
23668698cb | ||
|
|
91b576d147 | ||
|
|
f170735b73 | ||
|
|
f3de62e6c2 | ||
|
|
8e01291c18 | ||
|
|
7a2f166949 | ||
|
|
39b6e27944 | ||
|
|
5aa740c3e2 | ||
|
|
e973acde81 | ||
|
|
939c2e7f44 | ||
|
|
3c9b24bebe | ||
|
|
141df2d350 | ||
|
|
780e54cdc3 | ||
|
|
cd590cbfaa | ||
|
|
ff5932a8d8 | ||
|
|
949a49c9da | ||
|
|
69d0a1c540 | ||
|
|
de5ce6d461 | ||
|
|
8abcf666cb | ||
|
|
a96cc824bd | ||
|
|
59c675a64c | ||
|
|
89b38d96c9 | ||
|
|
5c8db48541 | ||
|
|
4c4b9d15ab | ||
|
|
0fc7efb663 | ||
|
|
17a49431d4 | ||
|
|
7cd46a12ae | ||
|
|
7e56e55252 | ||
|
|
eecf3e90c6 | ||
|
|
2099b6897f | ||
|
|
f605172d2b | ||
|
|
3b6f7b95eb | ||
|
|
7efbd325bb | ||
|
|
09e3f8f0d1 | ||
|
|
b6af4c8104 | ||
|
|
74c710187c | ||
|
|
59ced651b5 | ||
|
|
17db096505 | ||
|
|
e53d2197e4 | ||
|
|
f6932d6506 | ||
|
|
bf3366a48b | ||
|
|
fe81eea967 | ||
|
|
b0851e5949 | ||
|
|
c3cabf4e33 | ||
|
|
afc67c6dc5 | ||
|
|
9acb5e4cf0 | ||
|
|
def10cecd1 | ||
|
|
720f55cc4b | ||
|
|
bcb3ab451b | ||
|
|
535b88133c | ||
|
|
bbcea3f62b | ||
|
|
4f1b7fec9f | ||
|
|
2547928148 | ||
|
|
c0711cbefa | ||
|
|
e79c6696c5 | ||
|
|
34ab8dd6dd | ||
|
|
0294661da5 | ||
|
|
812025bd83 | ||
|
|
5f6f47a688 | ||
|
|
00db5c81e1 | ||
|
|
34e7b67d3c | ||
|
|
e3cfc0d33d | ||
|
|
7ddbd1bee7 | ||
|
|
b0bb458810 | ||
|
|
2ec38a17d4 | ||
|
|
e9036c295c | ||
|
|
c037694957 | ||
|
|
63b2237323 | ||
|
|
e22cddbe2a | ||
|
|
f33385f56d |
@@ -20,4 +20,4 @@ script:
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.3 ./run-tests)
|
||||
|
||||
after_failure:
|
||||
- (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff $testbase.exp $testbase.out; done)
|
||||
- (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done)
|
||||
|
||||
@@ -13,7 +13,7 @@ INC += -I$(PY_SRC)
|
||||
INC += -I$(BUILD)
|
||||
|
||||
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
|
||||
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M4) $(COPT)
|
||||
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
|
||||
|
||||
#Debugging/Optimization
|
||||
ifeq ($(DEBUG), 1)
|
||||
@@ -22,7 +22,7 @@ else
|
||||
CFLAGS += -Os -DNDEBUG
|
||||
endif
|
||||
|
||||
LDFLAGS = --nostdlib -T stm32f405.ld
|
||||
LDFLAGS = -nostdlib -T stm32f405.ld -Map=$@.map --cref
|
||||
LIBS =
|
||||
|
||||
SRC_C = \
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
#define MICROPY_HELPER_REPL (0)
|
||||
#define MICROPY_HELPER_LEXER_UNIX (0)
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (0)
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
|
||||
#define MICROPY_PY_BUILTINS_FROZENSET (0)
|
||||
#define MICROPY_PY_BUILTINS_SET (0)
|
||||
#define MICROPY_PY_BUILTINS_SLICE (0)
|
||||
#define MICROPY_PY_BUILTINS_PROPERTY (0)
|
||||
#define MICROPY_PY_ARRAY (0)
|
||||
#define MICROPY_PY_COLLECTIONS (0)
|
||||
#define MICROPY_PY_MATH (0)
|
||||
#define MICROPY_PY_CMATH (0)
|
||||
@@ -26,6 +28,8 @@
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||
|
||||
//#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
#define BYTES_PER_WORD (4)
|
||||
@@ -33,8 +37,8 @@
|
||||
#define UINT_FMT "%lu"
|
||||
#define INT_FMT "%ld"
|
||||
|
||||
typedef int32_t machine_int_t; // must be pointer size
|
||||
typedef uint32_t machine_uint_t; // must be pointer size
|
||||
typedef int32_t mp_int_t; // must be pointer size
|
||||
typedef uint32_t mp_uint_t; // must be pointer size
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
|
||||
|
||||
633
extmod/moductypes.c
Normal file
633
extmod/moductypes.c
Normal file
@@ -0,0 +1,633 @@
|
||||
#include <stdio.h>
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "nlr.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
#include "objtuple.h"
|
||||
#include "binary.h"
|
||||
|
||||
#if MICROPY_PY_UCTYPES
|
||||
|
||||
/// \module uctypes - Access data structures in memory
|
||||
///
|
||||
/// The module allows to define layout of raw data structure (using terms
|
||||
/// of C language), and then access memory buffers using this definition.
|
||||
/// The module also provides convenience functions to access memory buffers
|
||||
/// contained in Python objects or wrap memory buffers in Python objects.
|
||||
/// \constant UINT8_1 - uint8_t value type
|
||||
|
||||
/// \class struct - C-like structure
|
||||
///
|
||||
/// Encapsulalation of in-memory data structure. This class doesn't define
|
||||
/// any methods, only attribute access (for structure fields) and
|
||||
/// indexing (for pointer and array fields).
|
||||
///
|
||||
/// Usage:
|
||||
///
|
||||
/// # Define layout of a structure with 2 fields
|
||||
/// # 0 and 4 are byte offsets of fields from the beginning of struct
|
||||
/// # they are logically ORed with field type
|
||||
/// FOO_STRUCT = {"a": 0 | uctypes.UINT32, "b": 4 | uctypes.UINT8}
|
||||
///
|
||||
/// # Example memory buffer to access (contained in bytes object)
|
||||
/// buf = b"\x64\0\0\0\0x14"
|
||||
///
|
||||
/// # Create structure object referring to address of
|
||||
/// # the data in the buffer above
|
||||
/// s = uctypes.struct(FOO_STRUCT, uctypes.addressof(buf))
|
||||
///
|
||||
/// # Access fields
|
||||
/// print(s.a, s.b)
|
||||
/// # Result:
|
||||
/// # 100, 20
|
||||
|
||||
#define LAYOUT_LITTLE_ENDIAN (0)
|
||||
#define LAYOUT_BIG_ENDIAN (1)
|
||||
#define LAYOUT_NATIVE (2)
|
||||
|
||||
#define VAL_TYPE_BITS 4
|
||||
#define BITF_LEN_BITS 5
|
||||
#define BITF_OFF_BITS 5
|
||||
#define OFFSET_BITS 17
|
||||
#if VAL_TYPE_BITS + BITF_LEN_BITS + BITF_OFF_BITS + OFFSET_BITS != 31
|
||||
#error Invalid encoding field length
|
||||
#endif
|
||||
|
||||
enum {
|
||||
UINT8, INT8, UINT16, INT16,
|
||||
UINT32, INT32, UINT64, INT64,
|
||||
|
||||
BFUINT8, BFINT8, BFUINT16, BFINT16,
|
||||
BFUINT32, BFINT32,
|
||||
|
||||
FLOAT32, FLOAT64,
|
||||
};
|
||||
|
||||
#define AGG_TYPE_BITS 2
|
||||
|
||||
enum {
|
||||
STRUCT, PTR, ARRAY, BITFIELD,
|
||||
};
|
||||
|
||||
// Here we need to set sign bit right
|
||||
#define TYPE2SMALLINT(x, nbits) ((((int)x) << (32 - nbits)) >> 1)
|
||||
#define GET_TYPE(x, nbits) (((x) >> (31 - nbits)) & ((1 << nbits) - 1));
|
||||
// Bit 0 is "is_signed"
|
||||
#define GET_SCALAR_SIZE(val_type) (1 << ((val_type) >> 1))
|
||||
#define VALUE_MASK(type_nbits) ~((int)0x80000000 >> type_nbits)
|
||||
|
||||
STATIC const mp_obj_type_t uctypes_struct_type;
|
||||
|
||||
typedef struct _mp_obj_uctypes_struct_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t desc;
|
||||
byte *addr;
|
||||
uint32_t flags;
|
||||
} mp_obj_uctypes_struct_t;
|
||||
|
||||
STATIC NORETURN void syntax_error() {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "syntax error in uctypes descriptor"));
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||
if (n_args < 2 || n_args > 3) {
|
||||
syntax_error();
|
||||
}
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = type_in;
|
||||
o->desc = args[0];
|
||||
o->addr = (void*)mp_obj_get_int(args[1]);
|
||||
o->flags = LAYOUT_NATIVE;
|
||||
if (n_args == 3) {
|
||||
o->flags = mp_obj_get_int(args[2]);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
mp_obj_uctypes_struct_t *self = self_in;
|
||||
const char *typen = "unk";
|
||||
if (MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
|
||||
typen = "STRUCT";
|
||||
} else if (MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
|
||||
mp_obj_tuple_t *t = (mp_obj_tuple_t*)self->desc;
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
|
||||
switch (agg_type) {
|
||||
case PTR: typen = "PTR"; break;
|
||||
case ARRAY: typen = "ARRAY"; break;
|
||||
}
|
||||
} else {
|
||||
typen = "ERROR";
|
||||
}
|
||||
print(env, "<struct %s %p>", typen, self->addr);
|
||||
}
|
||||
|
||||
static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
|
||||
if (val_type == FLOAT32) {
|
||||
return 4;
|
||||
} else {
|
||||
return GET_SCALAR_SIZE(val_type & 7);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size) {
|
||||
mp_obj_dict_t *d = desc_in;
|
||||
mp_uint_t total_size = 0;
|
||||
|
||||
if (!MP_OBJ_IS_TYPE(desc_in, &mp_type_dict)) {
|
||||
syntax_error();
|
||||
}
|
||||
|
||||
for (mp_uint_t i = 0; i < d->map.alloc; i++) {
|
||||
if (MP_MAP_SLOT_IS_FILLED(&d->map, i)) {
|
||||
mp_obj_t v = d->map.table[i].value;
|
||||
if (MP_OBJ_IS_SMALL_INT(v)) {
|
||||
mp_uint_t offset = MP_OBJ_SMALL_INT_VALUE(v);
|
||||
mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS);
|
||||
offset &= VALUE_MASK(VAL_TYPE_BITS);
|
||||
mp_uint_t s = uctypes_struct_scalar_size(val_type);
|
||||
if (s > *max_field_size) {
|
||||
*max_field_size = s;
|
||||
}
|
||||
if (offset + s > total_size) {
|
||||
total_size = offset + s;
|
||||
}
|
||||
} else {
|
||||
if (!MP_OBJ_IS_TYPE(v, &mp_type_tuple)) {
|
||||
syntax_error();
|
||||
}
|
||||
mp_obj_tuple_t *t = (mp_obj_tuple_t*)v;
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
|
||||
offset &= VALUE_MASK(AGG_TYPE_BITS);
|
||||
|
||||
switch (agg_type) {
|
||||
case STRUCT: {
|
||||
mp_uint_t s = uctypes_struct_size(t->items[1], max_field_size);
|
||||
if (offset + s > total_size) {
|
||||
total_size = offset + s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTR: {
|
||||
if (offset + sizeof(void*) > total_size) {
|
||||
total_size = offset + sizeof(void*);
|
||||
}
|
||||
if (sizeof(void*) > *max_field_size) {
|
||||
*max_field_size = sizeof(void*);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARRAY: {
|
||||
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
|
||||
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
|
||||
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
|
||||
mp_uint_t item_s;
|
||||
if (t->len == 2) {
|
||||
item_s = GET_SCALAR_SIZE(val_type);
|
||||
if (item_s > *max_field_size) {
|
||||
*max_field_size = item_s;
|
||||
}
|
||||
} else {
|
||||
item_s = uctypes_struct_size(t->items[2], max_field_size);
|
||||
}
|
||||
|
||||
mp_uint_t byte_sz = item_s * arr_sz;
|
||||
if (offset + byte_sz > total_size) {
|
||||
total_size = offset + byte_sz;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Round size up to alignment of biggest field
|
||||
total_size = (total_size + *max_field_size - 1) & ~(*max_field_size - 1);
|
||||
return total_size;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_sizeof(mp_obj_t obj_in) {
|
||||
mp_uint_t max_field_size = 0;
|
||||
if (MP_OBJ_IS_TYPE(obj_in, &uctypes_struct_type)) {
|
||||
mp_obj_uctypes_struct_t *obj = obj_in;
|
||||
obj_in = obj->desc;
|
||||
}
|
||||
mp_uint_t size = uctypes_struct_size(obj_in, &max_field_size);
|
||||
return MP_OBJ_NEW_SMALL_INT(size);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_sizeof_obj, uctypes_struct_sizeof);
|
||||
|
||||
STATIC inline mp_obj_t get_unaligned(uint val_type, void *p, int big_endian) {
|
||||
mp_int_t val = mp_binary_get_int(GET_SCALAR_SIZE(val_type), val_type & 1, big_endian, p);
|
||||
if (val_type == UINT32) {
|
||||
return mp_obj_new_int_from_uint(val);
|
||||
} else {
|
||||
return mp_obj_new_int(val);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC inline void set_unaligned(uint val_type, void *p, int big_endian, mp_obj_t val) {
|
||||
char struct_type = big_endian ? '>' : '<';
|
||||
static const char type2char[8] = "BbHhIiQq";
|
||||
mp_binary_set_val(struct_type, type2char[val_type], val, (byte**)&p);
|
||||
}
|
||||
|
||||
static inline mp_uint_t get_aligned_basic(uint val_type, void *p) {
|
||||
switch (val_type) {
|
||||
case UINT8:
|
||||
return *(uint8_t*)p;
|
||||
case UINT16:
|
||||
return *(uint16_t*)p;
|
||||
case UINT32:
|
||||
return *(uint32_t*)p;
|
||||
}
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void set_aligned_basic(uint val_type, void *p, mp_uint_t v) {
|
||||
switch (val_type) {
|
||||
case UINT8:
|
||||
*(uint8_t*)p = (uint8_t)v; return;
|
||||
case UINT16:
|
||||
*(uint16_t*)p = (uint16_t)v; return;
|
||||
case UINT32:
|
||||
*(uint32_t*)p = (uint32_t)v; return;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) {
|
||||
switch (val_type) {
|
||||
case UINT8:
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)((uint8_t*)p)[index]);
|
||||
case INT8:
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)((int8_t*)p)[index]);
|
||||
case UINT16:
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)((uint16_t*)p)[index]);
|
||||
case INT16:
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)((int16_t*)p)[index]);
|
||||
case UINT32:
|
||||
return mp_obj_new_int_from_uint(((uint32_t*)p)[index]);
|
||||
case INT32:
|
||||
return mp_obj_new_int(((int32_t*)p)[index]);
|
||||
case UINT64:
|
||||
case INT64:
|
||||
return mp_obj_new_int_from_ll(((int64_t*)p)[index]);
|
||||
case FLOAT32:
|
||||
return mp_obj_new_float(((float*)p)[index]);
|
||||
case FLOAT64:
|
||||
return mp_obj_new_float(((double*)p)[index]);
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
|
||||
mp_int_t v = mp_obj_get_int(val);
|
||||
switch (val_type) {
|
||||
case UINT8:
|
||||
((uint8_t*)p)[index] = (uint8_t)v; return;
|
||||
case INT8:
|
||||
((int8_t*)p)[index] = (int8_t)v; return;
|
||||
case UINT16:
|
||||
((uint16_t*)p)[index] = (uint16_t)v; return;
|
||||
case INT16:
|
||||
((int16_t*)p)[index] = (int16_t)v; return;
|
||||
case UINT32:
|
||||
((uint32_t*)p)[index] = (uint32_t)v; return;
|
||||
case INT32:
|
||||
((int32_t*)p)[index] = (int32_t)v; return;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set_val) {
|
||||
mp_obj_uctypes_struct_t *self = self_in;
|
||||
|
||||
// TODO: Support at least OrderedDict in addition
|
||||
if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "struct: no fields"));
|
||||
}
|
||||
|
||||
mp_obj_t deref = mp_obj_dict_get(self->desc, MP_OBJ_NEW_QSTR(attr));
|
||||
if (MP_OBJ_IS_SMALL_INT(deref)) {
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(deref);
|
||||
mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS);
|
||||
offset &= VALUE_MASK(VAL_TYPE_BITS);
|
||||
//printf("scalar type=%d offset=%x\n", val_type, offset);
|
||||
|
||||
if (val_type <= INT64) {
|
||||
// printf("size=%d\n", GET_SCALAR_SIZE(val_type));
|
||||
if (self->flags == LAYOUT_NATIVE) {
|
||||
if (set_val == MP_OBJ_NULL) {
|
||||
return get_aligned(val_type, self->addr + offset, 0);
|
||||
} else {
|
||||
set_aligned(val_type, self->addr + offset, 0, set_val);
|
||||
return set_val; // just !MP_OBJ_NULL
|
||||
}
|
||||
} else {
|
||||
if (set_val == MP_OBJ_NULL) {
|
||||
return get_unaligned(val_type, self->addr + offset, self->flags);
|
||||
} else {
|
||||
set_unaligned(val_type, self->addr + offset, self->flags, set_val);
|
||||
return set_val; // just !MP_OBJ_NULL
|
||||
}
|
||||
}
|
||||
} else if (val_type >= BFUINT8 && val_type <= BFINT32) {
|
||||
uint bit_offset = (offset >> 17) & 31;
|
||||
uint bit_len = (offset >> 22) & 31;
|
||||
offset &= (1 << 17) - 1;
|
||||
mp_uint_t val;
|
||||
if (self->flags == LAYOUT_NATIVE) {
|
||||
val = get_aligned_basic(val_type & 6, self->addr + offset);
|
||||
} else {
|
||||
val = mp_binary_get_int(GET_SCALAR_SIZE(val_type & 7), val_type & 1, self->flags, self->addr + offset);
|
||||
}
|
||||
if (set_val == MP_OBJ_NULL) {
|
||||
val >>= bit_offset;
|
||||
val &= (1 << bit_len) - 1;
|
||||
// TODO: signed
|
||||
assert((val_type & 1) == 0);
|
||||
return mp_obj_new_int(val);
|
||||
} else {
|
||||
mp_uint_t set_val_int = (mp_uint_t)mp_obj_get_int(set_val);
|
||||
mp_uint_t mask = (1 << bit_len) - 1;
|
||||
set_val_int &= mask;
|
||||
set_val_int <<= bit_offset;
|
||||
mask <<= bit_offset;
|
||||
val = (val & ~mask) | set_val_int;
|
||||
|
||||
if (self->flags == LAYOUT_NATIVE) {
|
||||
set_aligned_basic(val_type & 6, self->addr + offset, val);
|
||||
} else {
|
||||
mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN,
|
||||
self->addr + offset, (byte*)&val);
|
||||
}
|
||||
return set_val; // just !MP_OBJ_NULL
|
||||
}
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
if (!MP_OBJ_IS_TYPE(deref, &mp_type_tuple)) {
|
||||
syntax_error();
|
||||
}
|
||||
|
||||
if (set_val != MP_OBJ_NULL) {
|
||||
// Cannot assign to aggregate
|
||||
syntax_error();
|
||||
}
|
||||
|
||||
mp_obj_tuple_t *sub = (mp_obj_tuple_t*)deref;
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(sub->items[0]);
|
||||
mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
|
||||
offset &= VALUE_MASK(AGG_TYPE_BITS);
|
||||
//printf("agg type=%d offset=%x\n", agg_type, offset);
|
||||
|
||||
switch (agg_type) {
|
||||
case STRUCT: {
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
o->desc = sub->items[1];
|
||||
o->addr = self->addr + offset;
|
||||
o->flags = self->flags;
|
||||
return o;
|
||||
}
|
||||
case PTR: case ARRAY: {
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
o->desc = sub;
|
||||
o->addr = self->addr + offset;
|
||||
o->flags = self->flags;
|
||||
//printf("PTR/ARR base addr=%p\n", o->addr);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
// Should be unreachable once all cases are handled
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
STATIC void uctypes_struct_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
mp_obj_t val = uctypes_struct_attr_op(self_in, attr, MP_OBJ_NULL);
|
||||
*dest = val;
|
||||
}
|
||||
|
||||
STATIC bool uctypes_struct_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t val) {
|
||||
return uctypes_struct_attr_op(self_in, attr, val) != MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
|
||||
mp_obj_uctypes_struct_t *self = self_in;
|
||||
|
||||
if (value == MP_OBJ_NULL) {
|
||||
// delete
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
} else if (value == MP_OBJ_SENTINEL) {
|
||||
// load
|
||||
if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "struct: cannot index"));
|
||||
}
|
||||
|
||||
mp_obj_tuple_t *t = (mp_obj_tuple_t*)self->desc;
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
|
||||
|
||||
mp_int_t index = MP_OBJ_SMALL_INT_VALUE(index_in);
|
||||
|
||||
if (agg_type == ARRAY) {
|
||||
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
|
||||
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
|
||||
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
|
||||
if (index >= arr_sz) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "struct: index out of range"));
|
||||
}
|
||||
|
||||
if (t->len == 2) {
|
||||
byte *p = self->addr + GET_SCALAR_SIZE(val_type) * index;
|
||||
return get_unaligned(val_type, p, self->flags);
|
||||
} else {
|
||||
mp_uint_t dummy = 0;
|
||||
mp_uint_t size = uctypes_struct_size(t->items[2], &dummy);
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
o->desc = t->items[2];
|
||||
o->addr = self->addr + size * index;
|
||||
o->flags = self->flags;
|
||||
return o;
|
||||
}
|
||||
} else if (agg_type == PTR) {
|
||||
byte *p = *(void**)self->addr;
|
||||
if (MP_OBJ_IS_SMALL_INT(t->items[1])) {
|
||||
uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS);
|
||||
return get_aligned(val_type, p, index);
|
||||
} else {
|
||||
mp_uint_t dummy = 0;
|
||||
mp_uint_t size = uctypes_struct_size(t->items[1], &dummy);
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
o->desc = t->items[1];
|
||||
o->addr = p + size * index;
|
||||
o->flags = self->flags;
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
assert(0);
|
||||
} else {
|
||||
// store
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
/// \function addressof()
|
||||
/// Return address of object's data (applies to object providing buffer
|
||||
/// interface).
|
||||
mp_obj_t uctypes_struct_addressof(mp_obj_t buf) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
|
||||
return mp_obj_new_int((mp_int_t)bufinfo.buf);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof);
|
||||
|
||||
/// \function bytearray_at()
|
||||
/// Capture memory at given address of given size as bytearray. Memory is
|
||||
/// captured by reference (and thus memory pointed by bytearray may change
|
||||
/// or become invalid at later time). Use bytes_at() to capture by value.
|
||||
mp_obj_t uctypes_struct_bytearray_at(mp_obj_t ptr, mp_obj_t size) {
|
||||
return mp_obj_new_bytearray_by_ref(mp_obj_int_get(size), (void*)mp_obj_int_get(ptr));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytearray_at);
|
||||
|
||||
/// \function bytes_at()
|
||||
/// Capture memory at given address of given size as bytes. Memory is
|
||||
/// captured by value, i.e. copied. Use bytearray_at() to capture by reference
|
||||
/// ("zero copy").
|
||||
mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) {
|
||||
return mp_obj_new_bytes((void*)mp_obj_int_get(ptr), mp_obj_int_get(size));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at);
|
||||
|
||||
|
||||
STATIC const mp_obj_type_t uctypes_struct_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_struct,
|
||||
.print = uctypes_struct_print,
|
||||
.make_new = uctypes_struct_make_new,
|
||||
.load_attr = uctypes_struct_load_attr,
|
||||
.store_attr = uctypes_struct_store_attr,
|
||||
.subscr = uctypes_struct_subscr,
|
||||
};
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_uctypes_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uctypes) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&uctypes_struct_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sizeof), (mp_obj_t)&uctypes_struct_sizeof_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_addressof), (mp_obj_t)&uctypes_struct_addressof_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytes_at), (mp_obj_t)&uctypes_struct_bytes_at_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytearray_at), (mp_obj_t)&uctypes_struct_bytearray_at_obj },
|
||||
|
||||
/// \moduleref uctypes
|
||||
|
||||
/// \constant NATIVE - Native structure layout - native endianness,
|
||||
/// platform-specific field alignment
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_NATIVE), MP_OBJ_NEW_SMALL_INT(LAYOUT_NATIVE) },
|
||||
/// \constant LITTLE_ENDIAN - Little-endian structure layout, tightly packed
|
||||
/// (no alignment constraints)
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_LITTLE_ENDIAN), MP_OBJ_NEW_SMALL_INT(LAYOUT_LITTLE_ENDIAN) },
|
||||
/// \constant BIG_ENDIAN - Big-endian structure layout, tightly packed
|
||||
/// (no alignment constraints)
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BIG_ENDIAN), MP_OBJ_NEW_SMALL_INT(LAYOUT_BIG_ENDIAN) },
|
||||
|
||||
/// \constant VOID - void value type, may be used only as pointer target type.
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_VOID), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT8, VAL_TYPE_BITS)) },
|
||||
|
||||
/// \constant UINT8 - uint8_t value type
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_UINT8), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT8, 4)) },
|
||||
/// \constant INT8 - int8_t value type
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT8), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(INT8, 4)) },
|
||||
/// \constant UINT16 - uint16_t value type
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_UINT16), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT16, 4)) },
|
||||
/// \constant INT16 - int16_t value type
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT16), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(INT16, 4)) },
|
||||
/// \constant UINT32 - uint32_t value type
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_UINT32), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT32, 4)) },
|
||||
/// \constant INT32 - int32_t value type
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT32), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(INT32, 4)) },
|
||||
/// \constant UINT64 - uint64_t value type
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_UINT64), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(UINT64, 4)) },
|
||||
/// \constant INT64 - int64_t value type
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT64), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(INT64, 4)) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFUINT8), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFUINT8, 4)) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFINT8), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFINT8, 4)) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFUINT16), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFUINT16, 4)) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFINT16), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFINT16, 4)) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFUINT32), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFUINT32, 4)) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BFINT32), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(BFINT32, 4)) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BF_POS), MP_OBJ_NEW_SMALL_INT(17) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_BF_LEN), MP_OBJ_NEW_SMALL_INT(22) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PTR), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(PTR, AGG_TYPE_BITS)) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ARRAY), MP_OBJ_NEW_SMALL_INT(TYPE2SMALLINT(ARRAY, AGG_TYPE_BITS)) },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_uctypes_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_uctypes_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_uctypes_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_uctypes_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
const mp_obj_module_t mp_module_uctypes = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_uctypes,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_uctypes_globals,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -28,8 +28,8 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "asmthumb.h"
|
||||
|
||||
// wrapper around everything in this file
|
||||
@@ -133,7 +133,7 @@ uint asm_thumb_get_code_size(asm_thumb_t *as) {
|
||||
|
||||
void *asm_thumb_get_code(asm_thumb_t *as) {
|
||||
// need to set low bit to indicate that it's thumb code
|
||||
return (void *)(((machine_uint_t)as->code_base) | 1);
|
||||
return (void *)(((mp_uint_t)as->code_base) | 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -378,7 +378,7 @@ void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label) {
|
||||
}
|
||||
}
|
||||
|
||||
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32) {
|
||||
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32) {
|
||||
// movw, movt does it in 8 bytes
|
||||
// ldr [pc, #], dw does it in 6 bytes, but we might not reach to end of code for dw
|
||||
|
||||
@@ -499,7 +499,7 @@ void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp
|
||||
if (0) {
|
||||
// load ptr to function into register using immediate, then branch
|
||||
// not relocatable
|
||||
asm_thumb_mov_reg_i32(as, reg_temp, (machine_uint_t)fun_ptr);
|
||||
asm_thumb_mov_reg_i32(as, reg_temp, (mp_uint_t)fun_ptr);
|
||||
asm_thumb_op16(as, OP_BLX(reg_temp));
|
||||
} else if (1) {
|
||||
asm_thumb_op16(as, OP_FORMAT_9_10(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, reg_temp, REG_R7, fun_id));
|
||||
|
||||
@@ -185,7 +185,7 @@ void asm_thumb_ite_ge(asm_thumb_t *as);
|
||||
void asm_thumb_b_n(asm_thumb_t *as, uint label);
|
||||
void asm_thumb_bcc_n(asm_thumb_t *as, int cond, uint label);
|
||||
|
||||
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, machine_uint_t i32_src); // convenience
|
||||
void asm_thumb_mov_reg_i32(asm_thumb_t *as, uint reg_dest, mp_uint_t i32_src); // convenience
|
||||
void asm_thumb_mov_reg_i32_optimised(asm_thumb_t *as, uint reg_dest, int i32_src); // convenience
|
||||
void asm_thumb_mov_reg_i32_aligned(asm_thumb_t *as, uint reg_dest, int i32); // convenience
|
||||
void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src); // convenience
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
|
||||
// wrapper around everything in this file
|
||||
#if MICROPY_EMIT_X64
|
||||
|
||||
6
py/bc.h
6
py/bc.h
@@ -55,6 +55,6 @@ void mp_bytecode_print(const void *descr, const byte *code, int len);
|
||||
void mp_bytecode_print2(const byte *code, int len);
|
||||
|
||||
// Helper macros to access pointer with least significant bit holding a flag
|
||||
#define MP_TAGPTR_PTR(x) ((void*)((machine_uint_t)(x) & ~((machine_uint_t)1)))
|
||||
#define MP_TAGPTR_TAG(x) ((machine_uint_t)(x) & 1)
|
||||
#define MP_TAGPTR_MAKE(ptr, tag) ((void*)((machine_uint_t)(ptr) | tag))
|
||||
#define MP_TAGPTR_PTR(x) ((void*)((mp_uint_t)(x) & ~((mp_uint_t)1)))
|
||||
#define MP_TAGPTR_TAG(x) ((mp_uint_t)(x) & 1)
|
||||
#define MP_TAGPTR_MAKE(ptr, tag) ((void*)((mp_uint_t)(ptr) | tag))
|
||||
|
||||
92
py/binary.c
92
py/binary.c
@@ -29,8 +29,8 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "binary.h"
|
||||
@@ -88,7 +88,7 @@ int mp_binary_get_size(char struct_type, char val_type, uint *palign) {
|
||||
}
|
||||
|
||||
mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
|
||||
machine_int_t val = 0;
|
||||
mp_int_t val = 0;
|
||||
switch (typecode) {
|
||||
case 'b':
|
||||
val = ((int8_t*)p)[index];
|
||||
@@ -125,32 +125,17 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
|
||||
return MP_OBJ_NEW_SMALL_INT(val);
|
||||
}
|
||||
|
||||
#define is_signed(typecode) (typecode > 'Z')
|
||||
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
|
||||
byte *p = *ptr;
|
||||
uint align;
|
||||
|
||||
int size = mp_binary_get_size(struct_type, val_type, &align);
|
||||
if (struct_type == '@') {
|
||||
// Make pointer aligned
|
||||
p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
|
||||
#if MP_ENDIANNESS_LITTLE
|
||||
struct_type = '<';
|
||||
#else
|
||||
struct_type = '>';
|
||||
#endif
|
||||
}
|
||||
|
||||
mp_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p) {
|
||||
int delta;
|
||||
if (struct_type == '<') {
|
||||
if (!big_endian) {
|
||||
delta = -1;
|
||||
p += size - 1;
|
||||
} else {
|
||||
delta = 1;
|
||||
}
|
||||
|
||||
machine_int_t val = 0;
|
||||
if (is_signed(val_type) && *p & 0x80) {
|
||||
mp_int_t val = 0;
|
||||
if (is_signed && *p & 0x80) {
|
||||
val = -1;
|
||||
}
|
||||
for (uint i = 0; i < size; i++) {
|
||||
@@ -159,7 +144,28 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
|
||||
p += delta;
|
||||
}
|
||||
|
||||
*ptr += size;
|
||||
return val;
|
||||
}
|
||||
|
||||
#define is_signed(typecode) (typecode > 'Z')
|
||||
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
|
||||
byte *p = *ptr;
|
||||
uint align;
|
||||
|
||||
int size = mp_binary_get_size(struct_type, val_type, &align);
|
||||
if (struct_type == '@') {
|
||||
// Make pointer aligned
|
||||
p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
|
||||
#if MP_ENDIANNESS_LITTLE
|
||||
struct_type = '<';
|
||||
#else
|
||||
struct_type = '>';
|
||||
#endif
|
||||
}
|
||||
*ptr = p + size;
|
||||
|
||||
mp_int_t val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p);
|
||||
|
||||
if (val_type == 'O') {
|
||||
return (mp_obj_t)val;
|
||||
} else if (val_type == 'S') {
|
||||
@@ -171,6 +177,23 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
void mp_binary_set_int(uint val_sz, bool big_endian, byte *p, byte *val_ptr) {
|
||||
int in_delta, out_delta;
|
||||
if (big_endian) {
|
||||
in_delta = -1;
|
||||
out_delta = 1;
|
||||
val_ptr += val_sz - 1;
|
||||
} else {
|
||||
in_delta = out_delta = 1;
|
||||
}
|
||||
|
||||
for (uint i = val_sz; i > 0; i--) {
|
||||
*p = *val_ptr;
|
||||
p += out_delta;
|
||||
val_ptr += in_delta;
|
||||
}
|
||||
}
|
||||
|
||||
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr) {
|
||||
byte *p = *ptr;
|
||||
uint align;
|
||||
@@ -178,18 +201,19 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
|
||||
int size = mp_binary_get_size(struct_type, val_type, &align);
|
||||
if (struct_type == '@') {
|
||||
// Make pointer aligned
|
||||
p = (byte*)(((machine_uint_t)p + align - 1) & ~(align - 1));
|
||||
p = (byte*)(((mp_uint_t)p + align - 1) & ~((mp_uint_t)align - 1));
|
||||
#if MP_ENDIANNESS_LITTLE
|
||||
struct_type = '<';
|
||||
#else
|
||||
struct_type = '>';
|
||||
#endif
|
||||
}
|
||||
*ptr = p + size;
|
||||
|
||||
#if MP_ENDIANNESS_BIG
|
||||
#error Not implemented
|
||||
#endif
|
||||
machine_int_t val;
|
||||
mp_int_t val;
|
||||
byte *in = (byte*)&val;
|
||||
switch (val_type) {
|
||||
case 'O':
|
||||
@@ -199,23 +223,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **
|
||||
val = mp_obj_get_int(val_in);
|
||||
}
|
||||
|
||||
int in_delta, out_delta;
|
||||
uint val_sz = MIN(size, sizeof(val));
|
||||
if (struct_type == '>') {
|
||||
in_delta = -1;
|
||||
out_delta = 1;
|
||||
in += val_sz - 1;
|
||||
} else {
|
||||
in_delta = out_delta = 1;
|
||||
}
|
||||
|
||||
for (uint i = val_sz; i > 0; i--) {
|
||||
*p = *in;
|
||||
p += out_delta;
|
||||
in += in_delta;
|
||||
}
|
||||
|
||||
*ptr += size;
|
||||
mp_binary_set_int(MIN(size, sizeof(val)), struct_type == '>', p, in);
|
||||
}
|
||||
|
||||
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in) {
|
||||
@@ -233,7 +241,7 @@ void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in)
|
||||
}
|
||||
}
|
||||
|
||||
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val) {
|
||||
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, mp_int_t val) {
|
||||
switch (typecode) {
|
||||
case 'b':
|
||||
((int8_t*)p)[index] = val;
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
int mp_binary_get_size(char struct_type, char val_type, uint *palign);
|
||||
mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index);
|
||||
void mp_binary_set_val_array(char typecode, void *p, int index, mp_obj_t val_in);
|
||||
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, machine_int_t val);
|
||||
void mp_binary_set_val_array_from_int(char typecode, void *p, int index, mp_int_t val);
|
||||
mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr);
|
||||
void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte **ptr);
|
||||
mp_int_t mp_binary_get_int(uint size, bool is_signed, bool big_endian, byte *p);
|
||||
void mp_binary_set_int(uint val_sz, bool big_endian, byte *p, byte *val_ptr);
|
||||
|
||||
62
py/builtin.c
62
py/builtin.c
@@ -99,7 +99,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print
|
||||
|
||||
mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(o_in)) {
|
||||
mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
|
||||
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(o_in);
|
||||
if (val < 0) {
|
||||
val = -val;
|
||||
}
|
||||
@@ -113,10 +113,12 @@ mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
|
||||
} else {
|
||||
return o_in;
|
||||
}
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_complex)) {
|
||||
mp_float_t real, imag;
|
||||
mp_obj_complex_get(o_in, &real, &imag);
|
||||
return mp_obj_new_float(MICROPY_FLOAT_C_FUN(sqrt)(real*real + imag*imag));
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
assert(0);
|
||||
@@ -154,7 +156,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) {
|
||||
mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in };
|
||||
return mp_obj_str_format(ARRAY_SIZE(args), args);
|
||||
return mp_obj_str_format(MP_ARRAY_SIZE(args), args);
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin);
|
||||
@@ -170,13 +172,40 @@ STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
|
||||
int ord = mp_obj_get_int(o_in);
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
mp_int_t c = mp_obj_get_int(o_in);
|
||||
char str[4];
|
||||
int len = 0;
|
||||
if (c < 0x80) {
|
||||
*str = c; len = 1;
|
||||
} else if (c < 0x800) {
|
||||
str[0] = (c >> 6) | 0xC0;
|
||||
str[1] = (c & 0x3F) | 0x80;
|
||||
len = 2;
|
||||
} else if (c < 0x10000) {
|
||||
str[0] = (c >> 12) | 0xE0;
|
||||
str[1] = ((c >> 6) & 0x3F) | 0x80;
|
||||
str[2] = (c & 0x3F) | 0x80;
|
||||
len = 3;
|
||||
} else if (c < 0x110000) {
|
||||
str[0] = (c >> 18) | 0xF0;
|
||||
str[1] = ((c >> 12) & 0x3F) | 0x80;
|
||||
str[2] = ((c >> 6) & 0x3F) | 0x80;
|
||||
str[3] = (c & 0x3F) | 0x80;
|
||||
len = 4;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
|
||||
}
|
||||
return mp_obj_new_str(str, len, true);
|
||||
#else
|
||||
mp_int_t ord = mp_obj_get_int(o_in);
|
||||
if (0 <= ord && ord <= 0x10ffff) {
|
||||
char str[1] = {ord};
|
||||
return mp_obj_new_str(str, 1, true);
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr);
|
||||
@@ -221,8 +250,8 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj, 0, 1, mp_builtin_dir);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
|
||||
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
|
||||
mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
|
||||
mp_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
|
||||
mp_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
|
||||
mp_obj_t args[2];
|
||||
args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
|
||||
args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
|
||||
@@ -342,13 +371,32 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct);
|
||||
STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
|
||||
uint len;
|
||||
const char *str = mp_obj_str_get_data(o_in, &len);
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
mp_uint_t charlen = unichar_charlen(str, len);
|
||||
if (charlen == 1) {
|
||||
if (MP_OBJ_IS_STR(o_in) && UTF8_IS_NONASCII(*str)) {
|
||||
mp_int_t ord = *str++ & 0x7F;
|
||||
for (mp_int_t mask = 0x40; ord & mask; mask >>= 1) {
|
||||
ord &= ~mask;
|
||||
}
|
||||
while (UTF8_IS_CONT(*str)) {
|
||||
ord = (ord << 6) | (*str++ & 0x3F);
|
||||
}
|
||||
return mp_obj_new_int(ord);
|
||||
} else {
|
||||
return mp_obj_new_int(((const byte*)str)[0]);
|
||||
}
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", charlen));
|
||||
}
|
||||
#else
|
||||
if (len == 1) {
|
||||
// don't sign extend when converting to ord
|
||||
// TODO unicode
|
||||
return mp_obj_new_int(((const byte*)str)[0]);
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", len));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord);
|
||||
@@ -430,7 +478,7 @@ STATIC mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *k
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) {
|
||||
return mp_obj_new_int((machine_int_t)o_in);
|
||||
return mp_obj_new_int((mp_int_t)o_in);
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_builtin_id);
|
||||
|
||||
@@ -80,3 +80,6 @@ extern const mp_obj_module_t mp_module_micropython;
|
||||
extern const mp_obj_module_t mp_module_struct;
|
||||
extern const mp_obj_module_t mp_module_sys;
|
||||
extern const mp_obj_module_t mp_module_gc;
|
||||
|
||||
// extmod modules
|
||||
extern const mp_obj_module_t mp_module_uctypes;
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -43,8 +43,10 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
// built-in types
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bool), (mp_obj_t)&mp_type_bool },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytes), (mp_obj_t)&mp_type_bytes },
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bytearray), (mp_obj_t)&mp_type_bytearray },
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_complex), (mp_obj_t)&mp_type_complex },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&mp_type_dict },
|
||||
@@ -150,8 +152,8 @@ const mp_obj_dict_t mp_builtin_object_dict_obj = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_builtin_object_table),
|
||||
.alloc = ARRAY_SIZE(mp_builtin_object_table),
|
||||
.used = MP_ARRAY_SIZE(mp_builtin_object_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_builtin_object_table),
|
||||
.table = (mp_map_elem_t*)mp_builtin_object_table,
|
||||
},
|
||||
};
|
||||
@@ -160,7 +162,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___main__), (mp_obj_t)&mp_module___main__ },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_micropython), (mp_obj_t)&mp_module_micropython },
|
||||
|
||||
#if MICROPY_PY_ARRAY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_module_array },
|
||||
#endif
|
||||
#if MICROPY_PY_IO
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR__io), (mp_obj_t)&mp_module_io },
|
||||
#endif
|
||||
@@ -186,6 +190,12 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_gc), (mp_obj_t)&mp_module_gc },
|
||||
#endif
|
||||
|
||||
// extmod modules
|
||||
|
||||
#if MICROPY_PY_UCTYPES
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uctypes), (mp_obj_t)&mp_module_uctypes },
|
||||
#endif
|
||||
|
||||
// extra builtin modules as defined by a port
|
||||
MICROPY_PORT_BUILTIN_MODULES
|
||||
};
|
||||
@@ -195,8 +205,8 @@ const mp_obj_dict_t mp_builtin_module_dict_obj = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_builtin_module_table),
|
||||
.alloc = ARRAY_SIZE(mp_builtin_module_table),
|
||||
.used = MP_ARRAY_SIZE(mp_builtin_module_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_builtin_module_table),
|
||||
.table = (mp_map_elem_t*)mp_builtin_module_table,
|
||||
},
|
||||
};
|
||||
|
||||
59
py/compile.c
59
py/compile.c
@@ -31,8 +31,8 @@
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
@@ -95,7 +95,7 @@ typedef struct _compiler_t {
|
||||
STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
|
||||
// TODO store the error message to a variable in compiler_t instead of printing it
|
||||
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
|
||||
printf(" File \"%s\", line " UINT_FMT "\n", qstr_str(comp->source_file), (machine_uint_t)((mp_parse_node_struct_t*)pn)->source_line);
|
||||
printf(" File \"%s\", line " UINT_FMT "\n", qstr_str(comp->source_file), (mp_uint_t)((mp_parse_node_struct_t*)pn)->source_line);
|
||||
} else {
|
||||
printf(" File \"%s\"\n", qstr_str(comp->source_file));
|
||||
}
|
||||
@@ -104,6 +104,9 @@ STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const cha
|
||||
}
|
||||
|
||||
STATIC const mp_map_elem_t mp_constants_table[] = {
|
||||
#if MICROPY_PY_UCTYPES
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uctypes), (mp_obj_t)&mp_module_uctypes },
|
||||
#endif
|
||||
// Extra constants as defined by a port
|
||||
MICROPY_PORT_CONSTANTS
|
||||
};
|
||||
@@ -111,8 +114,8 @@ STATIC const mp_map_elem_t mp_constants_table[] = {
|
||||
STATIC const mp_map_t mp_constants_map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_constants_table),
|
||||
.alloc = ARRAY_SIZE(mp_constants_table),
|
||||
.used = MP_ARRAY_SIZE(mp_constants_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_constants_table),
|
||||
.table = (mp_map_elem_t*)mp_constants_table,
|
||||
};
|
||||
|
||||
@@ -158,7 +161,7 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "constant must be an integer");
|
||||
break;
|
||||
}
|
||||
machine_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
|
||||
mp_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
|
||||
|
||||
// store the value in the table of dynamic constants
|
||||
mp_map_elem_t *elem = mp_map_lookup(consts, MP_OBJ_NEW_QSTR(id_qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
@@ -200,8 +203,8 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
case PN_expr:
|
||||
if (n == 2 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
|
||||
// int | int
|
||||
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
|
||||
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 | arg1);
|
||||
}
|
||||
break;
|
||||
@@ -209,16 +212,16 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
case PN_and_expr:
|
||||
if (n == 2 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
|
||||
// int & int
|
||||
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
|
||||
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 & arg1);
|
||||
}
|
||||
break;
|
||||
|
||||
case PN_shift_expr:
|
||||
if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
|
||||
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
|
||||
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
|
||||
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_LESS)) {
|
||||
// int << int
|
||||
if (!(arg1 >= BITS_PER_WORD || arg0 > (MP_SMALL_INT_MAX >> arg1) || arg0 < (MP_SMALL_INT_MIN >> arg1))) {
|
||||
@@ -235,10 +238,10 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
break;
|
||||
|
||||
case PN_arith_expr:
|
||||
// overflow checking here relies on SMALL_INT being strictly smaller than machine_int_t
|
||||
// overflow checking here relies on SMALL_INT being strictly smaller than mp_int_t
|
||||
if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
|
||||
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
|
||||
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
|
||||
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_PLUS)) {
|
||||
// int + int
|
||||
arg0 += arg1;
|
||||
@@ -258,8 +261,8 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
|
||||
case PN_term:
|
||||
if (n == 3 && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[0]) && MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[2])) {
|
||||
machine_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
machine_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
|
||||
mp_int_t arg0 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[0]);
|
||||
mp_int_t arg1 = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[2]);
|
||||
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_STAR)) {
|
||||
// int * int
|
||||
if (!mp_small_int_mul_overflow(arg0, arg1)) {
|
||||
@@ -288,7 +291,7 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
|
||||
case PN_factor_2:
|
||||
if (MP_PARSE_NODE_IS_SMALL_INT(pns->nodes[1])) {
|
||||
machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
|
||||
mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pns->nodes[1]);
|
||||
if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[0], MP_TOKEN_OP_PLUS)) {
|
||||
// +int
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg);
|
||||
@@ -336,7 +339,7 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method_maybe(elem->value, q_attr, dest);
|
||||
if (MP_OBJ_IS_SMALL_INT(dest[0]) && dest[1] == NULL) {
|
||||
machine_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
|
||||
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(dest[0]);
|
||||
if (MP_SMALL_INT_FITS(val)) {
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, val);
|
||||
}
|
||||
@@ -482,7 +485,7 @@ STATIC void cpython_c_print_quoted_str(vstr_t *vstr, const char *str, uint len,
|
||||
STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vstr_t *vstr) {
|
||||
if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_string)) {
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
|
||||
cpython_c_print_quoted_str(vstr, (const char*)pns->nodes[0], (machine_uint_t)pns->nodes[1], false);
|
||||
cpython_c_print_quoted_str(vstr, (const char*)pns->nodes[0], (mp_uint_t)pns->nodes[1], false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1894,7 +1897,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
|
||||
EMIT_ARG(jump, success_label); // jump over exception handler
|
||||
|
||||
EMIT_ARG(label_assign, l1); // start of exception handler
|
||||
EMIT_ARG(adjust_stack_size, 6); // stack adjust for the 3 exception items, +3 for possible UNWIND_JUMP state
|
||||
EMIT(start_except_handler);
|
||||
|
||||
uint l2 = comp_next_label(comp);
|
||||
|
||||
@@ -1966,7 +1969,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
|
||||
|
||||
compile_decrease_except_level(comp);
|
||||
EMIT(end_finally);
|
||||
EMIT_ARG(adjust_stack_size, -5); // stack adjust
|
||||
EMIT(end_except_handler);
|
||||
|
||||
EMIT_ARG(label_assign, success_label);
|
||||
compile_node(comp, pn_else); // else block, can be null
|
||||
@@ -2528,7 +2531,7 @@ void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
|
||||
assert(MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_string);
|
||||
pn_kind = MP_PARSE_NODE_STRING;
|
||||
n_bytes += (machine_uint_t)pns_string->nodes[1];
|
||||
n_bytes += (mp_uint_t)pns_string->nodes[1];
|
||||
}
|
||||
if (i == 0) {
|
||||
string_kind = pn_kind;
|
||||
@@ -2549,8 +2552,8 @@ void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
s_dest += s_len;
|
||||
} else {
|
||||
mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
|
||||
memcpy(s_dest, (const char*)pns_string->nodes[0], (machine_uint_t)pns_string->nodes[1]);
|
||||
s_dest += (machine_uint_t)pns_string->nodes[1];
|
||||
memcpy(s_dest, (const char*)pns_string->nodes[0], (mp_uint_t)pns_string->nodes[1]);
|
||||
s_dest += (mp_uint_t)pns_string->nodes[1];
|
||||
}
|
||||
}
|
||||
qstr q = qstr_build_end(q_ptr);
|
||||
@@ -2858,10 +2861,10 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
||||
if (MP_PARSE_NODE_IS_NULL(pn)) {
|
||||
// pass
|
||||
} else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
|
||||
machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
|
||||
mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
|
||||
EMIT_ARG(load_const_small_int, arg);
|
||||
} else if (MP_PARSE_NODE_IS_LEAF(pn)) {
|
||||
machine_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
|
||||
case MP_PARSE_NODE_ID: EMIT_ARG(load_id, arg); break;
|
||||
case MP_PARSE_NODE_INTEGER: EMIT_ARG(load_const_int, arg); break;
|
||||
@@ -2883,7 +2886,7 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) {
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
|
||||
EMIT_ARG(set_line_number, pns->source_line);
|
||||
if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_string) {
|
||||
EMIT_ARG(load_const_str, qstr_from_strn((const char*)pns->nodes[0], (machine_uint_t)pns->nodes[1]), false);
|
||||
EMIT_ARG(load_const_str, qstr_from_strn((const char*)pns->nodes[0], (mp_uint_t)pns->nodes[1]), false);
|
||||
} else {
|
||||
compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
|
||||
if (f == NULL) {
|
||||
@@ -3337,7 +3340,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
|
||||
return;
|
||||
}
|
||||
if (pass > MP_PASS_SCOPE) {
|
||||
machine_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
|
||||
mp_int_t bytesize = MP_PARSE_NODE_LEAF_SMALL_INT(pn_arg[0]);
|
||||
for (uint i = 1; i < n_args; i++) {
|
||||
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_arg[i])) {
|
||||
compile_syntax_error(comp, nodes[i], "inline assembler 'data' requires integer arguments");
|
||||
|
||||
@@ -65,7 +65,7 @@ typedef struct _emit_method_table_t {
|
||||
void (*import_from)(emit_t *emit, qstr qstr);
|
||||
void (*import_star)(emit_t *emit);
|
||||
void (*load_const_tok)(emit_t *emit, mp_token_kind_t tok);
|
||||
void (*load_const_small_int)(emit_t *emit, machine_int_t arg);
|
||||
void (*load_const_small_int)(emit_t *emit, mp_int_t arg);
|
||||
void (*load_const_int)(emit_t *emit, qstr qstr);
|
||||
void (*load_const_dec)(emit_t *emit, qstr qstr);
|
||||
void (*load_const_str)(emit_t *emit, qstr qstr, bool bytes);
|
||||
@@ -134,6 +134,11 @@ typedef struct _emit_method_table_t {
|
||||
void (*yield_value)(emit_t *emit);
|
||||
void (*yield_from)(emit_t *emit);
|
||||
|
||||
// these methods are used to control entry to/exit from an exception handler
|
||||
// they may or may not emit code
|
||||
void (*start_except_handler)(emit_t *emit);
|
||||
void (*end_except_handler)(emit_t *emit);
|
||||
|
||||
#if MICROPY_EMIT_CPYTHON
|
||||
// these methods are only needed for emitcpy
|
||||
void (*load_const_verbatim_str)(emit_t *emit, const char *str);
|
||||
|
||||
32
py/emitbc.c
32
py/emitbc.c
@@ -30,8 +30,8 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
@@ -50,7 +50,6 @@
|
||||
struct _emit_t {
|
||||
pass_kind_t pass : 8;
|
||||
uint last_emit_was_return_value : 8;
|
||||
byte dummy_data[DUMMY_DATA_SIZE];
|
||||
|
||||
int stack_size;
|
||||
|
||||
@@ -67,6 +66,8 @@ struct _emit_t {
|
||||
uint bytecode_offset;
|
||||
uint bytecode_size;
|
||||
byte *code_base; // stores both byte code and code info
|
||||
// Accessed as uint, so must be aligned as such
|
||||
byte dummy_data[DUMMY_DATA_SIZE];
|
||||
};
|
||||
|
||||
STATIC void emit_bc_rot_two(emit_t *emit);
|
||||
@@ -99,7 +100,7 @@ STATIC byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_writ
|
||||
}
|
||||
|
||||
STATIC void emit_align_code_info_to_machine_word(emit_t* emit) {
|
||||
emit->code_info_offset = (emit->code_info_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1));
|
||||
emit->code_info_offset = (emit->code_info_offset + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1));
|
||||
}
|
||||
|
||||
STATIC void emit_write_code_info_qstr(emit_t* emit, qstr qstr) {
|
||||
@@ -139,7 +140,7 @@ STATIC byte* emit_get_cur_to_write_bytecode(emit_t* emit, int num_bytes_to_write
|
||||
}
|
||||
|
||||
STATIC void emit_align_bytecode_to_machine_word(emit_t* emit) {
|
||||
emit->bytecode_offset = (emit->bytecode_offset + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1));
|
||||
emit->bytecode_offset = (emit->bytecode_offset + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1));
|
||||
}
|
||||
|
||||
STATIC void emit_write_bytecode_byte(emit_t* emit, byte b1) {
|
||||
@@ -171,7 +172,7 @@ STATIC void emit_write_bytecode_uint(emit_t* emit, uint num) {
|
||||
}
|
||||
|
||||
// Similar to emit_write_bytecode_uint(), just some extra handling to encode sign
|
||||
STATIC void emit_write_bytecode_byte_int(emit_t* emit, byte b1, machine_int_t num) {
|
||||
STATIC void emit_write_bytecode_byte_int(emit_t* emit, byte b1, mp_int_t num) {
|
||||
emit_write_bytecode_byte(emit, b1);
|
||||
|
||||
// We store each 7 bits in a separate byte, and that's how many bytes needed
|
||||
@@ -206,8 +207,10 @@ STATIC void emit_write_bytecode_byte_uint(emit_t* emit, byte b, uint num) {
|
||||
STATIC void emit_write_bytecode_byte_ptr(emit_t* emit, byte b, void *ptr) {
|
||||
emit_write_bytecode_byte(emit, b);
|
||||
emit_align_bytecode_to_machine_word(emit);
|
||||
machine_uint_t *c = (machine_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(machine_uint_t));
|
||||
*c = (machine_uint_t)ptr;
|
||||
mp_uint_t *c = (mp_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_uint_t));
|
||||
// Verify thar c is already uint-aligned
|
||||
assert(c == MP_ALIGN(c, sizeof(mp_uint_t)));
|
||||
*c = (mp_uint_t)ptr;
|
||||
}
|
||||
|
||||
/* currently unused
|
||||
@@ -269,7 +272,7 @@ STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
||||
// write code info size; use maximum space (4 bytes) to write it; TODO possible optimise this
|
||||
{
|
||||
byte* c = emit_get_cur_to_write_code_info(emit, 4);
|
||||
machine_uint_t s = emit->code_info_size;
|
||||
mp_uint_t s = emit->code_info_size;
|
||||
c[0] = s & 0xff;
|
||||
c[1] = (s >> 8) & 0xff;
|
||||
c[2] = (s >> 16) & 0xff;
|
||||
@@ -428,7 +431,7 @@ STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void emit_bc_load_const_small_int(emit_t *emit, machine_int_t arg) {
|
||||
STATIC void emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
|
||||
emit_bc_pre(emit, 1);
|
||||
emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
|
||||
}
|
||||
@@ -849,6 +852,14 @@ STATIC void emit_bc_yield_from(emit_t *emit) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_YIELD_FROM);
|
||||
}
|
||||
|
||||
STATIC void emit_bc_start_except_handler(emit_t *emit) {
|
||||
emit_bc_adjust_stack_size(emit, 6); // stack adjust for the 3 exception items, +3 for possible UNWIND_JUMP state
|
||||
}
|
||||
|
||||
STATIC void emit_bc_end_except_handler(emit_t *emit) {
|
||||
emit_bc_adjust_stack_size(emit, -5); // stack adjust
|
||||
}
|
||||
|
||||
const emit_method_table_t emit_bc_method_table = {
|
||||
emit_bc_set_native_types,
|
||||
emit_bc_start_pass,
|
||||
@@ -934,6 +945,9 @@ const emit_method_table_t emit_bc_method_table = {
|
||||
emit_bc_raise_varargs,
|
||||
emit_bc_yield_value,
|
||||
emit_bc_yield_from,
|
||||
|
||||
emit_bc_start_except_handler,
|
||||
emit_bc_end_except_handler,
|
||||
};
|
||||
|
||||
#endif // !MICROPY_EMIT_CPYTHON
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
|
||||
15
py/emitcpy.c
15
py/emitcpy.c
@@ -30,8 +30,8 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
@@ -173,7 +173,7 @@ STATIC void emit_cpy_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void emit_cpy_load_const_small_int(emit_t *emit, machine_int_t arg) {
|
||||
STATIC void emit_cpy_load_const_small_int(emit_t *emit, mp_int_t arg) {
|
||||
emit_pre(emit, 1, 3);
|
||||
if (emit->pass == MP_PASS_EMIT) {
|
||||
printf("LOAD_CONST " INT_FMT "\n", arg);
|
||||
@@ -792,6 +792,14 @@ STATIC void emit_cpy_yield_from(emit_t *emit) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void emit_cpy_start_except_handler(emit_t *emit) {
|
||||
emit_cpy_adjust_stack_size(emit, 3); // stack adjust for the 3 exception items
|
||||
}
|
||||
|
||||
STATIC void emit_cpy_end_except_handler(emit_t *emit) {
|
||||
emit_cpy_adjust_stack_size(emit, -5); // stack adjust
|
||||
}
|
||||
|
||||
STATIC void emit_cpy_load_const_verbatim_str(emit_t *emit, const char *str) {
|
||||
emit_pre(emit, 1, 3);
|
||||
if (emit->pass == MP_PASS_EMIT) {
|
||||
@@ -899,6 +907,9 @@ const emit_method_table_t emit_cpython_method_table = {
|
||||
emit_cpy_yield_value,
|
||||
emit_cpy_yield_from,
|
||||
|
||||
emit_cpy_start_except_handler,
|
||||
emit_cpy_end_except_handler,
|
||||
|
||||
// emitcpy specific functions
|
||||
emit_cpy_load_const_verbatim_str,
|
||||
emit_cpy_load_closure,
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime0.h"
|
||||
@@ -95,7 +95,7 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
DEBUG_printf("assign native: kind=%d fun=%p len=%u n_args=%d\n", kind, fun, len, n_args);
|
||||
byte *fun_data = (byte*)(((machine_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
|
||||
byte *fun_data = (byte*)(((mp_uint_t)fun) & (~1)); // need to clear lower bit in case it's thumb code
|
||||
for (int i = 0; i < 128 && i < len; i++) {
|
||||
if (i > 0 && i % 16 == 0) {
|
||||
DEBUG_printf("\n");
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
@@ -167,7 +167,7 @@ STATIC uint get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t
|
||||
if (MP_PARSE_NODE_IS_ID(pn)) {
|
||||
qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
const char *reg_str = qstr_str(reg_qstr);
|
||||
for (uint i = 0; i < ARRAY_SIZE(reg_name_table); i++) {
|
||||
for (uint i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) {
|
||||
const reg_name_t *r = ®_name_table[i];
|
||||
if (reg_str[0] == r->name[0] && reg_str[1] == r->name[1] && reg_str[2] == r->name[2] && (reg_str[2] == '\0' || reg_str[3] == '\0')) {
|
||||
if (r->reg > max_reg) {
|
||||
@@ -286,7 +286,7 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
|
||||
asm_thumb_b_n(emit->as, label_num);
|
||||
} else if (op_str[0] == 'b' && op_len == 3) {
|
||||
uint cc = -1;
|
||||
for (uint i = 0; i < ARRAY_SIZE(cc_name_table); i++) {
|
||||
for (uint i = 0; i < MP_ARRAY_SIZE(cc_name_table); i++) {
|
||||
if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) {
|
||||
cc = cc_name_table[i].cc;
|
||||
}
|
||||
|
||||
163
py/emitnative.c
163
py/emitnative.c
@@ -48,8 +48,9 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
@@ -139,7 +140,7 @@ typedef struct _stack_info_t {
|
||||
stack_info_kind_t kind;
|
||||
union {
|
||||
int u_reg;
|
||||
machine_int_t u_imm;
|
||||
mp_int_t u_imm;
|
||||
};
|
||||
} stack_info_t;
|
||||
|
||||
@@ -284,7 +285,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
|
||||
}
|
||||
}
|
||||
|
||||
asm_thumb_mov_reg_i32(emit->as, REG_R7, (machine_uint_t)mp_fun_table);
|
||||
asm_thumb_mov_reg_i32(emit->as, REG_R7, (mp_uint_t)mp_fun_table);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -471,7 +472,7 @@ STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) {
|
||||
adjust_stack(emit, 1);
|
||||
}
|
||||
|
||||
STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, machine_int_t imm) {
|
||||
STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) {
|
||||
stack_info_t *si = &emit->stack_info[emit->stack_size];
|
||||
si->vtype = vtype;
|
||||
si->kind = STACK_IMM;
|
||||
@@ -515,9 +516,9 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, int reg_dest, in
|
||||
case VTYPE_BOOL:
|
||||
si->vtype = VTYPE_PYOBJ;
|
||||
if (si->u_imm == 0) {
|
||||
ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
|
||||
ASM_MOV_IMM_TO_LOCAL_USING((mp_uint_t)mp_const_false, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
|
||||
} else {
|
||||
ASM_MOV_IMM_TO_LOCAL_USING((machine_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
|
||||
ASM_MOV_IMM_TO_LOCAL_USING((mp_uint_t)mp_const_true, emit->stack_start + emit->stack_size - 1 - i, reg_dest);
|
||||
}
|
||||
break;
|
||||
case VTYPE_INT:
|
||||
@@ -556,7 +557,7 @@ STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind, void *fun) {
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val, int arg_reg) {
|
||||
STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val, int arg_reg) {
|
||||
need_reg_all(emit);
|
||||
ASM_MOV_IMM_TO_REG(arg_val, arg_reg);
|
||||
#if N_X64
|
||||
@@ -566,8 +567,8 @@ STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, void *f
|
||||
#endif
|
||||
}
|
||||
|
||||
// the first arg is stored in the code aligned on a machine_uint_t boundary
|
||||
STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val, int arg_reg) {
|
||||
// the first arg is stored in the code aligned on a mp_uint_t boundary
|
||||
STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val, int arg_reg) {
|
||||
need_reg_all(emit);
|
||||
ASM_MOV_ALIGNED_IMM_TO_REG(arg_val, arg_reg);
|
||||
#if N_X64
|
||||
@@ -577,7 +578,7 @@ STATIC void emit_call_with_imm_arg_aligned(emit_t *emit, mp_fun_kind_t fun_kind,
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val1, int arg_reg1, machine_int_t arg_val2, int arg_reg2) {
|
||||
STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) {
|
||||
need_reg_all(emit);
|
||||
ASM_MOV_IMM_TO_REG(arg_val1, arg_reg1);
|
||||
ASM_MOV_IMM_TO_REG(arg_val2, arg_reg2);
|
||||
@@ -588,8 +589,8 @@ STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, void
|
||||
#endif
|
||||
}
|
||||
|
||||
// the first arg is stored in the code aligned on a machine_uint_t boundary
|
||||
STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, machine_int_t arg_val1, int arg_reg1, machine_int_t arg_val2, int arg_reg2, machine_int_t arg_val3, int arg_reg3) {
|
||||
// the first arg is stored in the code aligned on a mp_uint_t boundary
|
||||
STATIC void emit_call_with_3_imm_args_and_first_aligned(emit_t *emit, mp_fun_kind_t fun_kind, void *fun, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2, mp_int_t arg_val3, int arg_reg3) {
|
||||
need_reg_all(emit);
|
||||
ASM_MOV_ALIGNED_IMM_TO_REG(arg_val1, arg_reg1);
|
||||
ASM_MOV_IMM_TO_REG(arg_val2, arg_reg2);
|
||||
@@ -670,7 +671,7 @@ STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
|
||||
DEBUG_printf("load_const_tok %d\n", tok);
|
||||
emit_native_pre(emit);
|
||||
int vtype;
|
||||
machine_uint_t val;
|
||||
mp_uint_t val;
|
||||
if (emit->do_viper_types) {
|
||||
switch (tok) {
|
||||
case MP_TOKEN_KW_NONE: vtype = VTYPE_PTR_NONE; val = 0; break;
|
||||
@@ -681,16 +682,16 @@ STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
|
||||
} else {
|
||||
vtype = VTYPE_PYOBJ;
|
||||
switch (tok) {
|
||||
case MP_TOKEN_KW_NONE: val = (machine_uint_t)mp_const_none; break;
|
||||
case MP_TOKEN_KW_FALSE: val = (machine_uint_t)mp_const_false; break;
|
||||
case MP_TOKEN_KW_TRUE: val = (machine_uint_t)mp_const_true; break;
|
||||
case MP_TOKEN_KW_NONE: val = (mp_uint_t)mp_const_none; break;
|
||||
case MP_TOKEN_KW_FALSE: val = (mp_uint_t)mp_const_false; break;
|
||||
case MP_TOKEN_KW_TRUE: val = (mp_uint_t)mp_const_true; break;
|
||||
default: assert(0); vtype = 0; val = 0; // shouldn't happen
|
||||
}
|
||||
}
|
||||
emit_post_push_imm(emit, vtype, val);
|
||||
}
|
||||
|
||||
STATIC void emit_native_load_const_small_int(emit_t *emit, machine_int_t arg) {
|
||||
STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) {
|
||||
DEBUG_printf("load_const_small_int %d\n", arg);
|
||||
emit_native_pre(emit);
|
||||
if (emit->do_viper_types) {
|
||||
@@ -721,9 +722,13 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
|
||||
// not implemented properly
|
||||
// load a pointer to the asciiz string?
|
||||
assert(0);
|
||||
emit_post_push_imm(emit, VTYPE_PTR, (machine_uint_t)qstr_str(qstr));
|
||||
emit_post_push_imm(emit, VTYPE_PTR, (mp_uint_t)qstr_str(qstr));
|
||||
} else {
|
||||
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, mp_load_const_str, qstr, REG_ARG_1);
|
||||
if (bytes) {
|
||||
emit_call_with_imm_arg(emit, 0, mp_load_const_bytes, qstr, REG_ARG_1); // TODO need to add function to runtime table
|
||||
} else {
|
||||
emit_call_with_imm_arg(emit, MP_F_LOAD_CONST_STR, mp_load_const_str, qstr, REG_ARG_1);
|
||||
}
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
}
|
||||
}
|
||||
@@ -810,7 +815,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) {
|
||||
vtype_kind_t vtype_lhs, vtype_rhs;
|
||||
emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_2, &vtype_lhs, REG_ARG_1);
|
||||
if (vtype_lhs == VTYPE_PYOBJ && vtype_rhs == VTYPE_PYOBJ) {
|
||||
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (machine_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);
|
||||
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (mp_uint_t)MP_OBJ_SENTINEL, REG_ARG_3);
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
} else {
|
||||
printf("ViperTypeError: can't do subscr of types %d and %d\n", vtype_lhs, vtype_rhs);
|
||||
@@ -917,8 +922,11 @@ STATIC void emit_native_delete_global(emit_t *emit, qstr qstr) {
|
||||
}
|
||||
|
||||
STATIC void emit_native_delete_attr(emit_t *emit, qstr qstr) {
|
||||
// not supported
|
||||
assert(0);
|
||||
vtype_kind_t vtype_base;
|
||||
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
|
||||
assert(vtype_base == VTYPE_PYOBJ);
|
||||
emit_call_with_2_imm_args(emit, MP_F_STORE_ATTR, mp_store_attr, qstr, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg2 = attribute name, arg3 = value (null for delete)
|
||||
emit_post(emit);
|
||||
}
|
||||
|
||||
STATIC void emit_native_delete_subscr(emit_t *emit) {
|
||||
@@ -926,7 +934,7 @@ STATIC void emit_native_delete_subscr(emit_t *emit) {
|
||||
emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base
|
||||
assert(vtype_index == VTYPE_PYOBJ);
|
||||
assert(vtype_base == VTYPE_PYOBJ);
|
||||
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
|
||||
emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, mp_obj_subscr, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);
|
||||
}
|
||||
|
||||
STATIC void emit_native_dup_top(emit_t *emit) {
|
||||
@@ -1054,17 +1062,33 @@ STATIC void emit_native_setup_with(emit_t *emit, uint label) {
|
||||
// not supported, or could be with runtime call
|
||||
assert(0);
|
||||
}
|
||||
|
||||
STATIC void emit_native_with_cleanup(emit_t *emit) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
STATIC void emit_native_setup_except(emit_t *emit, uint label) {
|
||||
assert(0);
|
||||
emit_native_pre(emit);
|
||||
// need to commit stack because we may jump elsewhere
|
||||
need_stack_settled(emit);
|
||||
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_1, sizeof(nlr_buf_t) / sizeof(mp_uint_t)); // arg1 = pointer to nlr buf
|
||||
emit_call(emit, 0, nlr_push); // TODO need to add function to runtime table
|
||||
#if N_X64
|
||||
asm_x64_test_r8_with_r8(emit->as, REG_RET, REG_RET);
|
||||
asm_x64_jcc_label(emit->as, JCC_JNZ, label);
|
||||
#elif N_THUMB
|
||||
asm_thumb_cmp_rlo_i8(emit->as, REG_RET, 0);
|
||||
asm_thumb_bcc_label(emit->as, THUMB_CC_NE, label);
|
||||
#endif
|
||||
emit_post(emit);
|
||||
}
|
||||
|
||||
STATIC void emit_native_setup_finally(emit_t *emit, uint label) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
STATIC void emit_native_end_finally(emit_t *emit) {
|
||||
assert(0);
|
||||
//assert(0);
|
||||
}
|
||||
|
||||
STATIC void emit_native_get_iter(emit_t *emit) {
|
||||
@@ -1084,7 +1108,7 @@ STATIC void emit_native_for_iter(emit_t *emit, uint label) {
|
||||
emit_access_stack(emit, 1, &vtype, REG_ARG_1);
|
||||
assert(vtype == VTYPE_PYOBJ);
|
||||
emit_call(emit, MP_F_ITERNEXT, mp_iternext);
|
||||
ASM_MOV_IMM_TO_REG((machine_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
|
||||
ASM_MOV_IMM_TO_REG((mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
|
||||
#if N_X64
|
||||
asm_x64_cmp_r64_with_r64(emit->as, REG_RET, REG_TEMP1);
|
||||
asm_x64_jcc_label(emit->as, JCC_JE, label);
|
||||
@@ -1104,19 +1128,31 @@ STATIC void emit_native_for_iter_end(emit_t *emit) {
|
||||
|
||||
STATIC void emit_native_pop_block(emit_t *emit) {
|
||||
emit_native_pre(emit);
|
||||
emit_call(emit, 0, nlr_pop); // TODO need to add function to runtime table
|
||||
adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
|
||||
emit_post(emit);
|
||||
}
|
||||
|
||||
STATIC void emit_native_pop_except(emit_t *emit) {
|
||||
assert(0);
|
||||
/*
|
||||
emit_native_pre(emit);
|
||||
emit_call(emit, 0, nlr_pop); // TODO need to add function to runtime table
|
||||
adjust_stack(emit, -(mp_int_t)(sizeof(nlr_buf_t) / sizeof(mp_uint_t)));
|
||||
emit_post(emit);
|
||||
*/
|
||||
}
|
||||
|
||||
STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) {
|
||||
vtype_kind_t vtype;
|
||||
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
|
||||
assert(vtype == VTYPE_PYOBJ);
|
||||
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, mp_unary_op, op, REG_ARG_1);
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
if (op == MP_UNARY_OP_NOT) {
|
||||
// we need to synthesise this operation
|
||||
assert(0);
|
||||
} else {
|
||||
vtype_kind_t vtype;
|
||||
emit_pre_pop_reg(emit, &vtype, REG_ARG_2);
|
||||
assert(vtype == VTYPE_PYOBJ);
|
||||
emit_call_with_imm_arg(emit, MP_F_UNARY_OP, mp_unary_op, op, REG_ARG_1);
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
|
||||
@@ -1230,17 +1266,26 @@ STATIC void emit_native_set_add(emit_t *emit, int set_index) {
|
||||
|
||||
STATIC void emit_native_build_slice(emit_t *emit, int n_args) {
|
||||
DEBUG_printf("build_slice %d\n", n_args);
|
||||
assert(n_args == 2);
|
||||
vtype_kind_t vtype_start, vtype_stop;
|
||||
emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
|
||||
assert(vtype_start == VTYPE_PYOBJ);
|
||||
assert(vtype_stop == VTYPE_PYOBJ);
|
||||
emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, mp_obj_new_slice, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3); // arg3 = step
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
if (n_args == 2) {
|
||||
vtype_kind_t vtype_start, vtype_stop;
|
||||
emit_pre_pop_reg_reg(emit, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop
|
||||
assert(vtype_start == VTYPE_PYOBJ);
|
||||
assert(vtype_stop == VTYPE_PYOBJ);
|
||||
emit_call_with_imm_arg(emit, MP_F_NEW_SLICE, mp_obj_new_slice, (mp_uint_t)mp_const_none, REG_ARG_3); // arg3 = step
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
} else {
|
||||
assert(n_args == 3);
|
||||
vtype_kind_t vtype_start, vtype_stop, vtype_step;
|
||||
emit_pre_pop_reg_reg_reg(emit, &vtype_step, REG_ARG_3, &vtype_stop, REG_ARG_2, &vtype_start, REG_ARG_1); // arg1 = start, arg2 = stop, arg3 = step
|
||||
assert(vtype_start == VTYPE_PYOBJ);
|
||||
assert(vtype_stop == VTYPE_PYOBJ);
|
||||
assert(vtype_step == VTYPE_PYOBJ);
|
||||
emit_call(emit, MP_F_NEW_SLICE, mp_obj_new_slice);
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
|
||||
// TODO this is untested
|
||||
DEBUG_printf("unpack_sequence %d\n", n_args);
|
||||
vtype_kind_t vtype_base;
|
||||
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
|
||||
@@ -1250,26 +1295,25 @@ STATIC void emit_native_unpack_sequence(emit_t *emit, int n_args) {
|
||||
}
|
||||
|
||||
STATIC void emit_native_unpack_ex(emit_t *emit, int n_left, int n_right) {
|
||||
// TODO this is untested
|
||||
DEBUG_printf("unpack_ex %d %d\n", n_left, n_right);
|
||||
vtype_kind_t vtype_base;
|
||||
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq
|
||||
assert(vtype_base == VTYPE_PYOBJ);
|
||||
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right); // arg3 = dest ptr
|
||||
emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, mp_unpack_ex, n_left + n_right, REG_ARG_2); // arg2 = n_left + n_right
|
||||
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, n_left + n_right + 1); // arg3 = dest ptr
|
||||
emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, mp_unpack_ex, n_left | (n_right << 8), REG_ARG_2); // arg2 = n_left + n_right
|
||||
}
|
||||
|
||||
STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, uint n_pos_defaults, uint n_kw_defaults) {
|
||||
// call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them
|
||||
emit_native_pre(emit);
|
||||
if (n_pos_defaults == 0 && n_kw_defaults == 0) {
|
||||
emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1, (machine_uint_t)MP_OBJ_NULL, REG_ARG_2, (machine_uint_t)MP_OBJ_NULL, REG_ARG_3);
|
||||
emit_call_with_3_imm_args_and_first_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (mp_uint_t)scope->raw_code, REG_ARG_1, (mp_uint_t)MP_OBJ_NULL, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3);
|
||||
} else {
|
||||
vtype_kind_t vtype_def_tuple, vtype_def_dict;
|
||||
emit_pre_pop_reg_reg(emit, &vtype_def_dict, REG_ARG_3, &vtype_def_tuple, REG_ARG_2);
|
||||
assert(vtype_def_tuple == VTYPE_PYOBJ);
|
||||
assert(vtype_def_dict == VTYPE_PYOBJ);
|
||||
emit_call_with_imm_arg_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (machine_uint_t)scope->raw_code, REG_ARG_1);
|
||||
emit_call_with_imm_arg_aligned(emit, MP_F_MAKE_FUNCTION_FROM_RAW_CODE, mp_make_function_from_raw_code, (mp_uint_t)scope->raw_code, REG_ARG_1);
|
||||
}
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
}
|
||||
@@ -1365,9 +1409,16 @@ STATIC void emit_native_return_value(emit_t *emit) {
|
||||
}
|
||||
|
||||
STATIC void emit_native_raise_varargs(emit_t *emit, int n_args) {
|
||||
// call runtime
|
||||
assert(0);
|
||||
assert(n_args == 1);
|
||||
vtype_kind_t vtype_err;
|
||||
emit_pre_pop_reg(emit, &vtype_err, REG_ARG_1); // arg1 = object to raise
|
||||
assert(vtype_err == VTYPE_PYOBJ);
|
||||
emit_call(emit, 0, mp_make_raise_obj); // TODO need to add function to runtime table
|
||||
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
|
||||
emit_pre_pop_reg(emit, &vtype_err, REG_ARG_1);
|
||||
emit_call(emit, 0, nlr_jump); // TODO need to add function to runtime table
|
||||
}
|
||||
|
||||
STATIC void emit_native_yield_value(emit_t *emit) {
|
||||
// not supported (for now)
|
||||
assert(0);
|
||||
@@ -1377,6 +1428,21 @@ STATIC void emit_native_yield_from(emit_t *emit) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
STATIC void emit_native_start_except_handler(emit_t *emit) {
|
||||
// This instruction follows an nlr_pop, so the stack counter is back to zero, when really
|
||||
// it should be up by a whole nlr_buf_t. We then want to pop the nlr_buf_t here, but save
|
||||
// the first 2 elements, so we can get the thrown value.
|
||||
adjust_stack(emit, 2);
|
||||
vtype_kind_t vtype_nlr;
|
||||
emit_pre_pop_reg(emit, &vtype_nlr, REG_ARG_1); // get the thrown value
|
||||
emit_pre_pop_discard(emit, &vtype_nlr); // discard the linked-list pointer in the nlr_buf
|
||||
emit_post_push_reg_reg_reg(emit, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1, VTYPE_PYOBJ, REG_ARG_1); // push the 3 exception items
|
||||
}
|
||||
|
||||
STATIC void emit_native_end_except_handler(emit_t *emit) {
|
||||
adjust_stack(emit, -3); // stack adjust (not sure why it's this much...)
|
||||
}
|
||||
|
||||
const emit_method_table_t EXPORT_FUN(method_table) = {
|
||||
emit_native_set_viper_types,
|
||||
emit_native_start_pass,
|
||||
@@ -1462,6 +1528,9 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
|
||||
emit_native_raise_varargs,
|
||||
emit_native_yield_value,
|
||||
emit_native_yield_from,
|
||||
|
||||
emit_native_start_except_handler,
|
||||
emit_native_end_except_handler,
|
||||
};
|
||||
|
||||
#endif // (MICROPY_EMIT_X64 && N_X64) || (MICROPY_EMIT_THUMB && N_THUMB)
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
@@ -214,6 +214,10 @@ const emit_method_table_t emit_pass1_method_table = {
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
|
||||
#if MICROPY_EMIT_CPYTHON
|
||||
(void*)emit_pass1_dummy,
|
||||
(void*)emit_pass1_dummy,
|
||||
|
||||
156
py/gc.c
156
py/gc.c
@@ -33,7 +33,6 @@
|
||||
#include "misc.h"
|
||||
#include "gc.h"
|
||||
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
@@ -52,17 +51,17 @@
|
||||
#define STACK_SIZE (64) // tunable; minimum is 1
|
||||
|
||||
STATIC byte *gc_alloc_table_start;
|
||||
STATIC machine_uint_t gc_alloc_table_byte_len;
|
||||
STATIC mp_uint_t gc_alloc_table_byte_len;
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
STATIC byte *gc_finaliser_table_start;
|
||||
#endif
|
||||
STATIC machine_uint_t *gc_pool_start;
|
||||
STATIC machine_uint_t *gc_pool_end;
|
||||
STATIC mp_uint_t *gc_pool_start;
|
||||
STATIC mp_uint_t *gc_pool_end;
|
||||
|
||||
STATIC int gc_stack_overflow;
|
||||
STATIC machine_uint_t gc_stack[STACK_SIZE];
|
||||
STATIC machine_uint_t *gc_sp;
|
||||
STATIC machine_uint_t gc_lock_depth;
|
||||
STATIC mp_uint_t gc_stack[STACK_SIZE];
|
||||
STATIC mp_uint_t *gc_sp;
|
||||
STATIC mp_uint_t gc_lock_depth;
|
||||
|
||||
// ATB = allocation table byte
|
||||
// 0b00 = FREE -- free block
|
||||
@@ -94,8 +93,8 @@ STATIC machine_uint_t gc_lock_depth;
|
||||
#define ATB_HEAD_TO_MARK(block) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0)
|
||||
#define ATB_MARK_TO_HEAD(block) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0)
|
||||
|
||||
#define BLOCK_FROM_PTR(ptr) (((ptr) - (machine_uint_t)gc_pool_start) / BYTES_PER_BLOCK)
|
||||
#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (machine_uint_t)gc_pool_start))
|
||||
#define BLOCK_FROM_PTR(ptr) (((ptr) - (mp_uint_t)gc_pool_start) / BYTES_PER_BLOCK)
|
||||
#define PTR_FROM_BLOCK(block) (((block) * BYTES_PER_BLOCK + (mp_uint_t)gc_pool_start))
|
||||
#define ATB_FROM_BLOCK(bl) ((bl) / BLOCKS_PER_ATB)
|
||||
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
@@ -112,15 +111,15 @@ STATIC machine_uint_t gc_lock_depth;
|
||||
// TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool
|
||||
void gc_init(void *start, void *end) {
|
||||
// align end pointer on block boundary
|
||||
end = (void*)((machine_uint_t)end & (~(BYTES_PER_BLOCK - 1)));
|
||||
DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, end - start);
|
||||
end = (void*)((mp_uint_t)end & (~(BYTES_PER_BLOCK - 1)));
|
||||
DEBUG_printf("Initializing GC heap: %p..%p = " UINT_FMT " bytes\n", start, end, (byte*)end - (byte*)start);
|
||||
|
||||
// calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes):
|
||||
// T = A + F + P
|
||||
// F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB
|
||||
// P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK
|
||||
// => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK)
|
||||
machine_uint_t total_byte_len = end - start;
|
||||
mp_uint_t total_byte_len = (byte*)end - (byte*)start;
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
gc_alloc_table_byte_len = total_byte_len * BITS_PER_BYTE / (BITS_PER_BYTE + BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB + BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK);
|
||||
#else
|
||||
@@ -131,13 +130,13 @@ void gc_init(void *start, void *end) {
|
||||
gc_alloc_table_start = (byte*)start;
|
||||
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
machine_uint_t gc_finaliser_table_byte_len = (gc_alloc_table_byte_len * BLOCKS_PER_ATB) / BLOCKS_PER_FTB;
|
||||
mp_uint_t gc_finaliser_table_byte_len = (gc_alloc_table_byte_len * BLOCKS_PER_ATB) / BLOCKS_PER_FTB;
|
||||
gc_finaliser_table_start = gc_alloc_table_start + gc_alloc_table_byte_len;
|
||||
#endif
|
||||
|
||||
machine_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
|
||||
gc_pool_start = end - gc_pool_block_len * BYTES_PER_BLOCK;
|
||||
gc_pool_end = end;
|
||||
mp_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
|
||||
gc_pool_start = (mp_uint_t*)((byte*)end - gc_pool_block_len * BYTES_PER_BLOCK);
|
||||
gc_pool_end = (mp_uint_t*)end;
|
||||
|
||||
// clear ATBs
|
||||
memset(gc_alloc_table_start, 0, gc_alloc_table_byte_len);
|
||||
@@ -173,16 +172,20 @@ void gc_unlock(void) {
|
||||
gc_lock_depth--;
|
||||
}
|
||||
|
||||
bool gc_is_locked(void) {
|
||||
return gc_lock_depth != 0;
|
||||
}
|
||||
|
||||
#define VERIFY_PTR(ptr) ( \
|
||||
(ptr & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \
|
||||
&& ptr >= (machine_uint_t)gc_pool_start /* must be above start of pool */ \
|
||||
&& ptr < (machine_uint_t)gc_pool_end /* must be below end of pool */ \
|
||||
&& ptr >= (mp_uint_t)gc_pool_start /* must be above start of pool */ \
|
||||
&& ptr < (mp_uint_t)gc_pool_end /* must be below end of pool */ \
|
||||
)
|
||||
|
||||
#define VERIFY_MARK_AND_PUSH(ptr) \
|
||||
do { \
|
||||
if (VERIFY_PTR(ptr)) { \
|
||||
machine_uint_t _block = BLOCK_FROM_PTR(ptr); \
|
||||
mp_uint_t _block = BLOCK_FROM_PTR(ptr); \
|
||||
if (ATB_GET_KIND(_block) == AT_HEAD) { \
|
||||
/* an unmarked head, mark it, and push it on gc stack */ \
|
||||
ATB_HEAD_TO_MARK(_block); \
|
||||
@@ -198,18 +201,18 @@ void gc_unlock(void) {
|
||||
STATIC void gc_drain_stack(void) {
|
||||
while (gc_sp > gc_stack) {
|
||||
// pop the next block off the stack
|
||||
machine_uint_t block = *--gc_sp;
|
||||
mp_uint_t block = *--gc_sp;
|
||||
|
||||
// work out number of consecutive blocks in the chain starting with this one
|
||||
machine_uint_t n_blocks = 0;
|
||||
mp_uint_t n_blocks = 0;
|
||||
do {
|
||||
n_blocks += 1;
|
||||
} while (ATB_GET_KIND(block + n_blocks) == AT_TAIL);
|
||||
|
||||
// check this block's children
|
||||
machine_uint_t *scan = (machine_uint_t*)PTR_FROM_BLOCK(block);
|
||||
for (machine_uint_t i = n_blocks * WORDS_PER_BLOCK; i > 0; i--, scan++) {
|
||||
machine_uint_t ptr2 = *scan;
|
||||
mp_uint_t *scan = (mp_uint_t*)PTR_FROM_BLOCK(block);
|
||||
for (mp_uint_t i = n_blocks * WORDS_PER_BLOCK; i > 0; i--, scan++) {
|
||||
mp_uint_t ptr2 = *scan;
|
||||
VERIFY_MARK_AND_PUSH(ptr2);
|
||||
}
|
||||
}
|
||||
@@ -221,7 +224,7 @@ STATIC void gc_deal_with_stack_overflow(void) {
|
||||
gc_sp = gc_stack;
|
||||
|
||||
// scan entire memory looking for blocks which have been marked but not their children
|
||||
for (machine_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
|
||||
for (mp_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
|
||||
// trace (again) if mark bit set
|
||||
if (ATB_GET_KIND(block) == AT_MARK) {
|
||||
*gc_sp++ = block;
|
||||
@@ -241,7 +244,7 @@ STATIC void gc_sweep(void) {
|
||||
#endif
|
||||
// free unmarked heads and their tails
|
||||
int free_tail = 0;
|
||||
for (machine_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
|
||||
for (mp_uint_t block = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
|
||||
switch (ATB_GET_KIND(block)) {
|
||||
case AT_HEAD:
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
@@ -268,6 +271,7 @@ STATIC void gc_sweep(void) {
|
||||
|
||||
case AT_TAIL:
|
||||
if (free_tail) {
|
||||
DEBUG_printf("gc_sweep(%p)\n",PTR_FROM_BLOCK(block));
|
||||
ATB_ANY_TO_FREE(block);
|
||||
}
|
||||
break;
|
||||
@@ -286,9 +290,9 @@ void gc_collect_start(void) {
|
||||
gc_sp = gc_stack;
|
||||
}
|
||||
|
||||
void gc_collect_root(void **ptrs, machine_uint_t len) {
|
||||
for (machine_uint_t i = 0; i < len; i++) {
|
||||
machine_uint_t ptr = (machine_uint_t)ptrs[i];
|
||||
void gc_collect_root(void **ptrs, mp_uint_t len) {
|
||||
for (mp_uint_t i = 0; i < len; i++) {
|
||||
mp_uint_t ptr = (mp_uint_t)ptrs[i];
|
||||
VERIFY_MARK_AND_PUSH(ptr);
|
||||
gc_drain_stack();
|
||||
}
|
||||
@@ -301,14 +305,14 @@ void gc_collect_end(void) {
|
||||
}
|
||||
|
||||
void gc_info(gc_info_t *info) {
|
||||
info->total = (gc_pool_end - gc_pool_start) * sizeof(machine_uint_t);
|
||||
info->total = (gc_pool_end - gc_pool_start) * sizeof(mp_uint_t);
|
||||
info->used = 0;
|
||||
info->free = 0;
|
||||
info->num_1block = 0;
|
||||
info->num_2block = 0;
|
||||
info->max_block = 0;
|
||||
for (machine_uint_t block = 0, len = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
|
||||
machine_uint_t kind = ATB_GET_KIND(block);
|
||||
for (mp_uint_t block = 0, len = 0; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB; block++) {
|
||||
mp_uint_t kind = ATB_GET_KIND(block);
|
||||
if (kind == AT_FREE || kind == AT_HEAD) {
|
||||
if (len == 1) {
|
||||
info->num_1block += 1;
|
||||
@@ -345,8 +349,8 @@ void gc_info(gc_info_t *info) {
|
||||
info->free *= BYTES_PER_BLOCK;
|
||||
}
|
||||
|
||||
void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser) {
|
||||
machine_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
|
||||
void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser) {
|
||||
mp_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
|
||||
DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks);
|
||||
|
||||
// check if GC is locked
|
||||
@@ -359,10 +363,10 @@ void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
machine_uint_t i;
|
||||
machine_uint_t end_block;
|
||||
machine_uint_t start_block;
|
||||
machine_uint_t n_free = 0;
|
||||
mp_uint_t i;
|
||||
mp_uint_t end_block;
|
||||
mp_uint_t start_block;
|
||||
mp_uint_t n_free = 0;
|
||||
int collected = 0;
|
||||
for (;;) {
|
||||
|
||||
@@ -395,19 +399,20 @@ found:
|
||||
|
||||
// mark rest of blocks as used tail
|
||||
// TODO for a run of many blocks can make this more efficient
|
||||
for (machine_uint_t bl = start_block + 1; bl <= end_block; bl++) {
|
||||
for (mp_uint_t bl = start_block + 1; bl <= end_block; bl++) {
|
||||
ATB_FREE_TO_TAIL(bl);
|
||||
}
|
||||
|
||||
// get pointer to first block
|
||||
void *ret_ptr = (void*)(gc_pool_start + start_block * WORDS_PER_BLOCK);
|
||||
DEBUG_printf("gc_alloc(%p)\n", ret_ptr);
|
||||
|
||||
// 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(ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);
|
||||
memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);
|
||||
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
if (has_finaliser) {
|
||||
@@ -422,11 +427,11 @@ found:
|
||||
}
|
||||
|
||||
/*
|
||||
void *gc_alloc(machine_uint_t n_bytes) {
|
||||
void *gc_alloc(mp_uint_t n_bytes) {
|
||||
return _gc_alloc(n_bytes, false);
|
||||
}
|
||||
|
||||
void *gc_alloc_with_finaliser(machine_uint_t n_bytes) {
|
||||
void *gc_alloc_with_finaliser(mp_uint_t n_bytes) {
|
||||
return _gc_alloc(n_bytes, true);
|
||||
}
|
||||
*/
|
||||
@@ -438,10 +443,11 @@ void gc_free(void *ptr_in) {
|
||||
return;
|
||||
}
|
||||
|
||||
machine_uint_t ptr = (machine_uint_t)ptr_in;
|
||||
mp_uint_t ptr = (mp_uint_t)ptr_in;
|
||||
DEBUG_printf("gc_free(%p)\n", ptr);
|
||||
|
||||
if (VERIFY_PTR(ptr)) {
|
||||
machine_uint_t block = BLOCK_FROM_PTR(ptr);
|
||||
mp_uint_t block = BLOCK_FROM_PTR(ptr);
|
||||
if (ATB_GET_KIND(block) == AT_HEAD) {
|
||||
// free head and all of its tail blocks
|
||||
do {
|
||||
@@ -452,14 +458,14 @@ void gc_free(void *ptr_in) {
|
||||
}
|
||||
}
|
||||
|
||||
machine_uint_t gc_nbytes(void *ptr_in) {
|
||||
machine_uint_t ptr = (machine_uint_t)ptr_in;
|
||||
mp_uint_t gc_nbytes(void *ptr_in) {
|
||||
mp_uint_t ptr = (mp_uint_t)ptr_in;
|
||||
|
||||
if (VERIFY_PTR(ptr)) {
|
||||
machine_uint_t block = BLOCK_FROM_PTR(ptr);
|
||||
mp_uint_t block = BLOCK_FROM_PTR(ptr);
|
||||
if (ATB_GET_KIND(block) == AT_HEAD) {
|
||||
// work out number of consecutive blocks in the chain starting with this on
|
||||
machine_uint_t n_blocks = 0;
|
||||
mp_uint_t n_blocks = 0;
|
||||
do {
|
||||
n_blocks += 1;
|
||||
} while (ATB_GET_KIND(block + n_blocks) == AT_TAIL);
|
||||
@@ -473,8 +479,8 @@ machine_uint_t gc_nbytes(void *ptr_in) {
|
||||
|
||||
#if 0
|
||||
// old, simple realloc that didn't expand memory in place
|
||||
void *gc_realloc(void *ptr, machine_uint_t n_bytes) {
|
||||
machine_uint_t n_existing = gc_nbytes(ptr);
|
||||
void *gc_realloc(void *ptr, mp_uint_t n_bytes) {
|
||||
mp_uint_t n_existing = gc_nbytes(ptr);
|
||||
if (n_bytes <= n_existing) {
|
||||
return ptr;
|
||||
} else {
|
||||
@@ -483,7 +489,7 @@ void *gc_realloc(void *ptr, machine_uint_t n_bytes) {
|
||||
has_finaliser = false;
|
||||
} else {
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
has_finaliser = FTB_GET(BLOCK_FROM_PTR((machine_uint_t)ptr));
|
||||
has_finaliser = FTB_GET(BLOCK_FROM_PTR((mp_uint_t)ptr));
|
||||
#else
|
||||
has_finaliser = false;
|
||||
#endif
|
||||
@@ -500,7 +506,7 @@ void *gc_realloc(void *ptr, machine_uint_t n_bytes) {
|
||||
|
||||
#else // Alternative gc_realloc impl
|
||||
|
||||
void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
|
||||
void *gc_realloc(void *ptr_in, mp_uint_t n_bytes) {
|
||||
if (gc_lock_depth > 0) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -510,7 +516,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
|
||||
return gc_alloc(n_bytes, false);
|
||||
}
|
||||
|
||||
machine_uint_t ptr = (machine_uint_t)ptr_in;
|
||||
mp_uint_t ptr = (mp_uint_t)ptr_in;
|
||||
|
||||
// sanity check the ptr
|
||||
if (!VERIFY_PTR(ptr)) {
|
||||
@@ -518,7 +524,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
|
||||
}
|
||||
|
||||
// get first block
|
||||
machine_uint_t block = BLOCK_FROM_PTR(ptr);
|
||||
mp_uint_t block = BLOCK_FROM_PTR(ptr);
|
||||
|
||||
// sanity check the ptr is pointing to the head of a block
|
||||
if (ATB_GET_KIND(block) != AT_HEAD) {
|
||||
@@ -526,14 +532,14 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
|
||||
}
|
||||
|
||||
// compute number of new blocks that are requested
|
||||
machine_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK;
|
||||
mp_uint_t new_blocks = (n_bytes + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK;
|
||||
|
||||
// get the number of consecutive tail blocks and
|
||||
// the number of free blocks after last tail block
|
||||
// stop if we reach (or are at) end of heap
|
||||
machine_uint_t n_free = 0;
|
||||
machine_uint_t n_blocks = 1; // counting HEAD block
|
||||
machine_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
|
||||
mp_uint_t n_free = 0;
|
||||
mp_uint_t n_blocks = 1; // counting HEAD block
|
||||
mp_uint_t max_block = gc_alloc_table_byte_len * BLOCKS_PER_ATB;
|
||||
while (block + n_blocks + n_free < max_block) {
|
||||
if (n_blocks + n_free >= new_blocks) {
|
||||
// stop as soon as we find enough blocks for n_bytes
|
||||
@@ -556,7 +562,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
|
||||
// check if we can shrink the allocated area
|
||||
if (new_blocks < n_blocks) {
|
||||
// free unneeded tail blocks
|
||||
for (machine_uint_t bl = block + new_blocks; ATB_GET_KIND(bl) == AT_TAIL; bl++) {
|
||||
for (mp_uint_t bl = block + new_blocks; ATB_GET_KIND(bl) == AT_TAIL; bl++) {
|
||||
ATB_ANY_TO_FREE(bl);
|
||||
}
|
||||
return ptr_in;
|
||||
@@ -565,13 +571,13 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
|
||||
// check if we can expand in place
|
||||
if (new_blocks <= n_blocks + n_free) {
|
||||
// mark few more blocks as used tail
|
||||
for (machine_uint_t bl = block + n_blocks; bl < block + new_blocks; bl++) {
|
||||
for (mp_uint_t bl = block + n_blocks; bl < block + new_blocks; bl++) {
|
||||
assert(ATB_GET_KIND(bl) == AT_FREE);
|
||||
ATB_FREE_TO_TAIL(bl);
|
||||
}
|
||||
|
||||
// zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc)
|
||||
memset(ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);
|
||||
memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);
|
||||
|
||||
return ptr_in;
|
||||
}
|
||||
@@ -590,7 +596,7 @@ void *gc_realloc(void *ptr_in, machine_uint_t n_bytes) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG_printf("gc_realloc: allocating new block\n");
|
||||
DEBUG_printf("gc_realloc(%p -> %p)\n", ptr_in, ptr_out);
|
||||
memcpy(ptr_out, ptr_in, n_blocks * BYTES_PER_BLOCK);
|
||||
gc_free(ptr_in);
|
||||
return ptr_out;
|
||||
@@ -607,7 +613,7 @@ void gc_dump_info() {
|
||||
|
||||
void gc_dump_alloc_table(void) {
|
||||
printf("GC memory layout; from %p:", gc_pool_start);
|
||||
for (machine_uint_t bl = 0; bl < gc_alloc_table_byte_len * BLOCKS_PER_ATB; bl++) {
|
||||
for (mp_uint_t bl = 0; bl < gc_alloc_table_byte_len * BLOCKS_PER_ATB; bl++) {
|
||||
if (bl % 64 == 0) {
|
||||
printf("\n%04x: ", (uint)bl);
|
||||
}
|
||||
@@ -617,12 +623,12 @@ void gc_dump_alloc_table(void) {
|
||||
case AT_HEAD: c = 'h'; break;
|
||||
/* this prints the uPy object type of the head block
|
||||
case AT_HEAD: {
|
||||
machine_uint_t *ptr = gc_pool_start + bl * WORDS_PER_BLOCK;
|
||||
if (*ptr == (machine_uint_t)&mp_type_tuple) { c = 'T'; }
|
||||
else if (*ptr == (machine_uint_t)&mp_type_list) { c = 'L'; }
|
||||
else if (*ptr == (machine_uint_t)&mp_type_dict) { c = 'D'; }
|
||||
else if (*ptr == (machine_uint_t)&mp_type_float) { c = 'F'; }
|
||||
else if (*ptr == (machine_uint_t)&mp_type_fun_bc) { c = 'B'; }
|
||||
mp_uint_t *ptr = gc_pool_start + bl * WORDS_PER_BLOCK;
|
||||
if (*ptr == (mp_uint_t)&mp_type_tuple) { c = 'T'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_list) { c = 'L'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_dict) { c = 'D'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_float) { c = 'F'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_fun_bc) { c = 'B'; }
|
||||
else { c = 'h'; }
|
||||
break;
|
||||
}
|
||||
@@ -637,23 +643,23 @@ void gc_dump_alloc_table(void) {
|
||||
|
||||
#if DEBUG_PRINT
|
||||
void gc_test(void) {
|
||||
machine_uint_t len = 500;
|
||||
machine_uint_t *heap = malloc(len);
|
||||
gc_init(heap, heap + len / sizeof(machine_uint_t));
|
||||
mp_uint_t len = 500;
|
||||
mp_uint_t *heap = malloc(len);
|
||||
gc_init(heap, heap + len / sizeof(mp_uint_t));
|
||||
void *ptrs[100];
|
||||
{
|
||||
machine_uint_t **p = gc_alloc(16, false);
|
||||
mp_uint_t **p = gc_alloc(16, false);
|
||||
p[0] = gc_alloc(64, false);
|
||||
p[1] = gc_alloc(1, false);
|
||||
p[2] = gc_alloc(1, false);
|
||||
p[3] = gc_alloc(1, false);
|
||||
machine_uint_t ***p2 = gc_alloc(16, false);
|
||||
mp_uint_t ***p2 = gc_alloc(16, false);
|
||||
p2[0] = p;
|
||||
p2[1] = p;
|
||||
ptrs[0] = p2;
|
||||
}
|
||||
for (int i = 0; i < 25; i+=2) {
|
||||
machine_uint_t *p = gc_alloc(i, false);
|
||||
mp_uint_t *p = gc_alloc(i, false);
|
||||
printf("p=%p\n", p);
|
||||
if (i & 3) {
|
||||
//ptrs[i] = p;
|
||||
|
||||
21
py/gc.h
21
py/gc.h
@@ -30,25 +30,26 @@ void gc_init(void *start, void *end);
|
||||
// They can be used to prevent the GC from allocating/freeing.
|
||||
void gc_lock(void);
|
||||
void gc_unlock(void);
|
||||
bool gc_is_locked(void);
|
||||
|
||||
// A given port must implement gc_collect by using the other collect functions.
|
||||
void gc_collect(void);
|
||||
void gc_collect_start(void);
|
||||
void gc_collect_root(void **ptrs, machine_uint_t len);
|
||||
void gc_collect_root(void **ptrs, mp_uint_t len);
|
||||
void gc_collect_end(void);
|
||||
|
||||
void *gc_alloc(machine_uint_t n_bytes, bool has_finaliser);
|
||||
void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser);
|
||||
void gc_free(void *ptr);
|
||||
machine_uint_t gc_nbytes(void *ptr);
|
||||
void *gc_realloc(void *ptr, machine_uint_t n_bytes);
|
||||
mp_uint_t gc_nbytes(void *ptr);
|
||||
void *gc_realloc(void *ptr, mp_uint_t n_bytes);
|
||||
|
||||
typedef struct _gc_info_t {
|
||||
machine_uint_t total;
|
||||
machine_uint_t used;
|
||||
machine_uint_t free;
|
||||
machine_uint_t num_1block;
|
||||
machine_uint_t num_2block;
|
||||
machine_uint_t max_block;
|
||||
mp_uint_t total;
|
||||
mp_uint_t used;
|
||||
mp_uint_t free;
|
||||
mp_uint_t num_1block;
|
||||
mp_uint_t num_2block;
|
||||
mp_uint_t max_block;
|
||||
} gc_info_t;
|
||||
|
||||
void gc_info(gc_info_t *info);
|
||||
|
||||
94
py/lexer.c
94
py/lexer.c
@@ -32,8 +32,8 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
|
||||
@@ -50,25 +50,25 @@ struct _mp_lexer_t {
|
||||
|
||||
unichar chr0, chr1, chr2; // current cached characters from source
|
||||
|
||||
uint line; // source line
|
||||
uint column; // source column
|
||||
mp_uint_t line; // source line
|
||||
mp_uint_t column; // source column
|
||||
|
||||
int emit_dent; // non-zero when there are INDENT/DEDENT tokens to emit
|
||||
int nested_bracket_level; // >0 when there are nested brackets over multiple lines
|
||||
mp_int_t emit_dent; // non-zero when there are INDENT/DEDENT tokens to emit
|
||||
mp_int_t nested_bracket_level; // >0 when there are nested brackets over multiple lines
|
||||
|
||||
uint alloc_indent_level;
|
||||
uint num_indent_level;
|
||||
mp_uint_t alloc_indent_level;
|
||||
mp_uint_t num_indent_level;
|
||||
uint16_t *indent_level;
|
||||
|
||||
vstr_t vstr;
|
||||
mp_token_t tok_cur;
|
||||
};
|
||||
|
||||
uint mp_optimise_value;
|
||||
mp_uint_t mp_optimise_value;
|
||||
|
||||
// TODO replace with a call to a standard function
|
||||
bool str_strn_equal(const char *str, const char *strn, int len) {
|
||||
uint i = 0;
|
||||
bool str_strn_equal(const char *str, const char *strn, mp_uint_t len) {
|
||||
mp_uint_t i = 0;
|
||||
|
||||
while (i < len && *str == *strn) {
|
||||
++i;
|
||||
@@ -81,10 +81,10 @@ bool str_strn_equal(const char *str, const char *strn, int len) {
|
||||
|
||||
#ifdef MICROPY_DEBUG_PRINTERS
|
||||
void mp_token_show(const mp_token_t *tok) {
|
||||
printf("(%d:%d) kind:%d str:%p len:%d", tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
|
||||
printf("(" UINT_FMT ":" UINT_FMT ") kind:%u str:%p len:" UINT_FMT, tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
|
||||
if (tok->str != NULL && tok->len > 0) {
|
||||
const char *i = tok->str;
|
||||
const char *j = i + tok->len;
|
||||
const byte *i = (const byte *)tok->str;
|
||||
const byte *j = (const byte *)i + tok->len;
|
||||
printf(" ");
|
||||
while (i < j) {
|
||||
unichar c = utf8_get_char(i);
|
||||
@@ -175,7 +175,7 @@ STATIC void next_char(mp_lexer_t *lex) {
|
||||
return;
|
||||
}
|
||||
|
||||
int advance = 1;
|
||||
mp_uint_t advance = 1;
|
||||
|
||||
if (lex->chr0 == '\n') {
|
||||
// LF is a new line
|
||||
@@ -210,7 +210,7 @@ STATIC void next_char(mp_lexer_t *lex) {
|
||||
}
|
||||
}
|
||||
|
||||
void indent_push(mp_lexer_t *lex, uint indent) {
|
||||
void indent_push(mp_lexer_t *lex, mp_uint_t indent) {
|
||||
if (lex->num_indent_level >= lex->alloc_indent_level) {
|
||||
// TODO use m_renew_maybe and somehow indicate an error if it fails... probably by using MP_TOKEN_MEMORY_ERROR
|
||||
lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC);
|
||||
@@ -219,7 +219,7 @@ void indent_push(mp_lexer_t *lex, uint indent) {
|
||||
lex->indent_level[lex->num_indent_level++] = indent;
|
||||
}
|
||||
|
||||
uint indent_top(mp_lexer_t *lex) {
|
||||
mp_uint_t indent_top(mp_lexer_t *lex) {
|
||||
return lex->indent_level[lex->num_indent_level - 1];
|
||||
}
|
||||
|
||||
@@ -308,9 +308,9 @@ STATIC const char *tok_kw[] = {
|
||||
"__debug__",
|
||||
};
|
||||
|
||||
STATIC int hex_digit(unichar c) {
|
||||
STATIC mp_uint_t hex_digit(unichar c) {
|
||||
// c is assumed to be hex digit
|
||||
int n = c - '0';
|
||||
mp_uint_t n = c - '0';
|
||||
if (n > 9) {
|
||||
n &= ~('a' - 'A');
|
||||
n -= ('A' - ('9' + 1));
|
||||
@@ -320,8 +320,9 @@ STATIC int hex_digit(unichar c) {
|
||||
|
||||
// This is called with CUR_CHAR() before first hex digit, and should return with
|
||||
// it pointing to last hex digit
|
||||
STATIC bool get_hex(mp_lexer_t *lex, int num_digits, uint *result) {
|
||||
uint num = 0;
|
||||
// num_digits must be greater than zero
|
||||
STATIC bool get_hex(mp_lexer_t *lex, mp_uint_t num_digits, mp_uint_t *result) {
|
||||
mp_uint_t num = 0;
|
||||
while (num_digits-- != 0) {
|
||||
next_char(lex);
|
||||
unichar c = CUR_CHAR(lex);
|
||||
@@ -394,7 +395,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
} else if (had_physical_newline && lex->nested_bracket_level == 0) {
|
||||
tok->kind = MP_TOKEN_NEWLINE;
|
||||
|
||||
uint num_spaces = lex->column - 1;
|
||||
mp_uint_t num_spaces = lex->column - 1;
|
||||
lex->emit_dent = 0;
|
||||
if (num_spaces == indent_top(lex)) {
|
||||
} else if (num_spaces > indent_top(lex)) {
|
||||
@@ -463,7 +464,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
next_char(lex);
|
||||
|
||||
// work out if it's a single or triple quoted literal
|
||||
int num_quotes;
|
||||
mp_uint_t num_quotes;
|
||||
if (is_char_and(lex, quote_char, quote_char)) {
|
||||
// triple quotes
|
||||
next_char(lex);
|
||||
@@ -475,7 +476,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
}
|
||||
|
||||
// parse the literal
|
||||
int n_closing = 0;
|
||||
mp_uint_t n_closing = 0;
|
||||
while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\n')) && n_closing < num_quotes) {
|
||||
if (is_char(lex, quote_char)) {
|
||||
n_closing += 1;
|
||||
@@ -502,24 +503,37 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
case 'v': c = 0x0b; break;
|
||||
case 'f': c = 0x0c; break;
|
||||
case 'r': c = 0x0d; break;
|
||||
case 'u':
|
||||
case 'U':
|
||||
if (is_bytes) {
|
||||
// b'\u1234' == b'\\u1234'
|
||||
vstr_add_char(&lex->vstr, '\\');
|
||||
break;
|
||||
}
|
||||
// Otherwise fall through.
|
||||
case 'x':
|
||||
{
|
||||
uint num = 0;
|
||||
if (!get_hex(lex, 2, &num)) {
|
||||
mp_uint_t num = 0;
|
||||
if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {
|
||||
// TODO error message
|
||||
assert(0);
|
||||
}
|
||||
c = num;
|
||||
break;
|
||||
}
|
||||
case 'N': break; // TODO \N{name} only in strings
|
||||
case 'u': break; // TODO \uxxxx only in strings
|
||||
case 'U': break; // TODO \Uxxxxxxxx only in strings
|
||||
case 'N':
|
||||
// Supporting '\N{LATIN SMALL LETTER A}' == 'a' would require keeping the
|
||||
// entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly
|
||||
// 3MB of text; even gzip-compressed and with minimal structure, it'll take
|
||||
// roughly half a meg of storage. This form of Unicode escape may be added
|
||||
// later on, but it's definitely not a priority right now. -- CJA 20140607
|
||||
assert(!"Unicode name escapes not supported");
|
||||
break;
|
||||
default:
|
||||
if (c >= '0' && c <= '7') {
|
||||
// Octal sequence, 1-3 chars
|
||||
int digits = 3;
|
||||
int num = c - '0';
|
||||
mp_uint_t digits = 3;
|
||||
mp_uint_t num = c - '0';
|
||||
while (is_following_odigit(lex) && --digits != 0) {
|
||||
next_char(lex);
|
||||
num = num * 8 + (CUR_CHAR(lex) - '0');
|
||||
@@ -533,7 +547,13 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
}
|
||||
}
|
||||
if (c != MP_LEXER_CHAR_EOF) {
|
||||
vstr_add_char(&lex->vstr, c);
|
||||
if (c < 0x110000 && !is_bytes) {
|
||||
vstr_add_char(&lex->vstr, c);
|
||||
} else if (c < 0x100 && is_bytes) {
|
||||
vstr_add_byte(&lex->vstr, c);
|
||||
} else {
|
||||
assert(!"TODO: Throw an error, invalid escape code probably");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
|
||||
@@ -608,7 +628,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
// search for encoded delimiter or operator
|
||||
|
||||
const char *t = tok_enc;
|
||||
uint tok_enc_index = 0;
|
||||
mp_uint_t tok_enc_index = 0;
|
||||
for (; *t != 0 && !is_char(lex, *t); t += 1) {
|
||||
if (*t == 'e' || *t == 'c') {
|
||||
t += 1;
|
||||
@@ -630,7 +650,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
|
||||
// get the maximum characters for a valid token
|
||||
t += 1;
|
||||
uint t_index = tok_enc_index;
|
||||
mp_uint_t t_index = tok_enc_index;
|
||||
for (;;) {
|
||||
for (; *t == 'e'; t += 1) {
|
||||
t += 1;
|
||||
@@ -693,11 +713,11 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
|
||||
// the parser gives a syntax error on, eg, x.__debug__. Otherwise, we
|
||||
// need to check for this special token in many places in the compiler.
|
||||
// TODO improve speed of these string comparisons
|
||||
//for (int i = 0; tok_kw[i] != NULL; i++) {
|
||||
for (int i = 0; i < ARRAY_SIZE(tok_kw); i++) {
|
||||
//for (mp_int_t i = 0; tok_kw[i] != NULL; i++) {
|
||||
for (mp_int_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
|
||||
if (str_strn_equal(tok_kw[i], tok->str, tok->len)) {
|
||||
if (i == ARRAY_SIZE(tok_kw) - 1) {
|
||||
// tok_kw[ARRAY_SIZE(tok_kw) - 1] == "__debug__"
|
||||
if (i == MP_ARRAY_SIZE(tok_kw) - 1) {
|
||||
// tok_kw[MP_ARRAY_SIZE(tok_kw) - 1] == "__debug__"
|
||||
tok->kind = (mp_optimise_value == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
|
||||
} else {
|
||||
tok->kind = MP_TOKEN_KW_FALSE + i;
|
||||
|
||||
10
py/lexer.h
10
py/lexer.h
@@ -131,12 +131,12 @@ typedef enum _mp_token_kind_t {
|
||||
} mp_token_kind_t;
|
||||
|
||||
typedef struct _mp_token_t {
|
||||
uint src_line; // source line
|
||||
uint src_column; // source column
|
||||
mp_uint_t src_line; // source line
|
||||
mp_uint_t src_column; // source column
|
||||
|
||||
mp_token_kind_t kind; // kind of token
|
||||
const char *str; // string of token (valid only while this token is current token)
|
||||
uint len; // (byte) length of string of token
|
||||
mp_uint_t len; // (byte) length of string of token
|
||||
} mp_token_t;
|
||||
|
||||
// the next-char function must return the next character in the stream
|
||||
@@ -151,7 +151,7 @@ typedef struct _mp_lexer_t mp_lexer_t;
|
||||
void mp_token_show(const mp_token_t *tok);
|
||||
|
||||
mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close);
|
||||
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, uint len, uint free_len);
|
||||
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len);
|
||||
|
||||
void mp_lexer_free(mp_lexer_t *lex);
|
||||
qstr mp_lexer_source_name(mp_lexer_t *lex);
|
||||
@@ -177,4 +177,4 @@ typedef enum {
|
||||
mp_import_stat_t mp_import_stat(const char *path);
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename);
|
||||
|
||||
extern uint mp_optimise_value;
|
||||
extern mp_uint_t mp_optimise_value;
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
|
||||
typedef struct _mp_lexer_str_buf_t {
|
||||
uint free_len; // if > 0, src_beg will be freed when done by: m_free(src_beg, free_len)
|
||||
mp_uint_t free_len; // if > 0, src_beg will be freed when done by: m_free(src_beg, free_len)
|
||||
const char *src_beg; // beginning of source
|
||||
const char *src_cur; // current location in source
|
||||
const char *src_end; // end (exclusive) of source
|
||||
@@ -51,7 +51,7 @@ STATIC void str_buf_free(mp_lexer_str_buf_t *sb) {
|
||||
m_del_obj(mp_lexer_str_buf_t, sb);
|
||||
}
|
||||
|
||||
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, uint len, uint free_len) {
|
||||
mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len) {
|
||||
mp_lexer_str_buf_t *sb = m_new_obj(mp_lexer_str_buf_t);
|
||||
sb->free_len = free_len;
|
||||
sb->src_beg = str;
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
|
||||
#if MICROPY_HELPER_LEXER_UNIX
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
|
||||
#if 0 // print debugging info
|
||||
#define DEBUG_printf DEBUG_printf
|
||||
|
||||
6
py/map.c
6
py/map.c
@@ -27,8 +27,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime0.h"
|
||||
@@ -167,7 +167,7 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
|
||||
}
|
||||
}
|
||||
|
||||
machine_uint_t hash = mp_obj_hash(index);
|
||||
mp_uint_t hash = mp_obj_hash(index);
|
||||
uint pos = hash % map->alloc;
|
||||
uint start_pos = pos;
|
||||
mp_map_elem_t *avail_slot = NULL;
|
||||
@@ -270,7 +270,7 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t looku
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
machine_uint_t hash = mp_obj_hash(index);
|
||||
mp_uint_t hash = mp_obj_hash(index);
|
||||
uint pos = hash % set->alloc;
|
||||
uint start_pos = pos;
|
||||
mp_obj_t *avail_slot = NULL;
|
||||
|
||||
26
py/misc.h
26
py/misc.h
@@ -82,14 +82,17 @@ int m_get_peak_bytes_allocated(void);
|
||||
/** array helpers ***********************************************/
|
||||
|
||||
// get the number of elements in a fixed-size array
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
// align ptr to the nearest multiple of "alignment"
|
||||
#define MP_ALIGN(ptr, alignment) (void*)(((mp_uint_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1))
|
||||
|
||||
/** unichar / UTF-8 *********************************************/
|
||||
|
||||
typedef int unichar; // TODO
|
||||
|
||||
unichar utf8_get_char(const char *s);
|
||||
char *utf8_next_char(const char *s);
|
||||
unichar utf8_get_char(const byte *s);
|
||||
const byte *utf8_next_char(const byte *s);
|
||||
|
||||
bool unichar_isspace(unichar c);
|
||||
bool unichar_isalpha(unichar c);
|
||||
@@ -100,6 +103,9 @@ bool unichar_isupper(unichar c);
|
||||
bool unichar_islower(unichar c);
|
||||
unichar unichar_tolower(unichar c);
|
||||
unichar unichar_toupper(unichar c);
|
||||
mp_uint_t unichar_charlen(const char *str, mp_uint_t len);
|
||||
#define UTF8_IS_NONASCII(ch) ((ch) & 0x80)
|
||||
#define UTF8_IS_CONT(ch) (((ch) & 0xC0) == 0x80)
|
||||
|
||||
/** variable string *********************************************/
|
||||
|
||||
@@ -163,4 +169,18 @@ int DEBUG_printf(const char *fmt, ...);
|
||||
|
||||
extern uint mp_verbose_flag;
|
||||
|
||||
// This is useful for unicode handling. Some CPU archs has
|
||||
// special instructions for efficient implentation of this
|
||||
// function (e.g. CLZ on ARM).
|
||||
// NOTE: this function is unused at the moment
|
||||
#ifndef count_lead_ones
|
||||
static inline uint count_lead_ones(byte val) {
|
||||
uint c = 0;
|
||||
for (byte mask = 0x80; val & mask; mask >>= 1) {
|
||||
c++;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _INCLUDED_MINILIB_H
|
||||
|
||||
@@ -73,9 +73,9 @@ all: $(PROG)
|
||||
|
||||
$(PROG): $(OBJ)
|
||||
$(ECHO) "LINK $@"
|
||||
$(Q)$(CC) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
|
||||
$(Q)$(CC) $(COPT) -o $@ $(OBJ) $(LIB) $(LDFLAGS)
|
||||
ifndef DEBUG
|
||||
$(Q)$(STRIP) $(PROG)
|
||||
$(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)
|
||||
endif
|
||||
$(Q)$(SIZE) $(PROG)
|
||||
|
||||
@@ -97,4 +97,10 @@ print-cfg:
|
||||
$(ECHO) "OBJ = $(OBJ)"
|
||||
.PHONY: print-cfg
|
||||
|
||||
print-def:
|
||||
@$(ECHO) "The following defines are built into the $(CC) compiler"
|
||||
touch __empty__.c
|
||||
@$(CC) -E -Wp,-dM __empty__.c
|
||||
@$(RM) -f __empty__.c
|
||||
|
||||
-include $(OBJ:.o=.P)
|
||||
|
||||
@@ -24,12 +24,14 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
|
||||
#if MICROPY_PY_ARRAY
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_array_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_array) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mp_type_array },
|
||||
@@ -40,8 +42,8 @@ STATIC const mp_obj_dict_t mp_module_array_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_array_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_array_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_array_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_array_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_array_globals_table,
|
||||
},
|
||||
};
|
||||
@@ -51,3 +53,5 @@ const mp_obj_module_t mp_module_array = {
|
||||
.name = MP_QSTR_array,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_array_globals,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -142,8 +142,8 @@ STATIC const mp_obj_dict_t mp_module_cmath_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_cmath_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_cmath_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_cmath_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_cmath_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_cmath_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -42,8 +42,8 @@ STATIC const mp_obj_dict_t mp_module_collections_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_collections_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_collections_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_collections_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_collections_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_collections_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
24
py/modgc.c
24
py/modgc.c
@@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -42,7 +42,7 @@ extern uint gc_collected;
|
||||
STATIC mp_obj_t py_gc_collect(void) {
|
||||
gc_collect();
|
||||
#if MICROPY_PY_GC_COLLECT_RETVAL
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_uint_t)gc_collected);
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)gc_collected);
|
||||
#else
|
||||
return mp_const_none;
|
||||
#endif
|
||||
@@ -61,11 +61,27 @@ STATIC mp_obj_t gc_enable(void) {
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable);
|
||||
|
||||
STATIC mp_obj_t gc_mem_free(void) {
|
||||
gc_info_t info;
|
||||
gc_info(&info);
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)info.free);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free);
|
||||
|
||||
STATIC mp_obj_t gc_mem_alloc(void) {
|
||||
gc_info_t info;
|
||||
gc_info(&info);
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)info.used);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_alloc_obj, gc_mem_alloc);
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_gc_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_gc) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_collect), (mp_obj_t)&gc_collect_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&gc_disable_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&gc_enable_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_free), (mp_obj_t)&gc_mem_free_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_alloc), (mp_obj_t)&gc_mem_alloc_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_gc_globals = {
|
||||
@@ -73,8 +89,8 @@ STATIC const mp_obj_dict_t mp_module_gc_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_gc_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_gc_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_gc_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_gc_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_gc_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -57,8 +57,8 @@ STATIC const mp_obj_dict_t mp_module_io_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_io_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_io_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_io_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_io_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_io_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -48,7 +48,7 @@
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
#define MATH_FUN_1_TO_INT(py_name, c_name) \
|
||||
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int((machine_int_t)MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
|
||||
mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int((mp_int_t)MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
// These are also used by cmath.c
|
||||
@@ -172,8 +172,8 @@ STATIC const mp_obj_dict_t mp_module_math_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_math_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_math_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_math_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_math_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_math_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -35,15 +35,15 @@
|
||||
|
||||
#if MICROPY_MEM_STATS
|
||||
STATIC mp_obj_t mp_micropython_mem_total() {
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_total_bytes_allocated());
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)m_get_total_bytes_allocated());
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_micropython_mem_current() {
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_current_bytes_allocated());
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)m_get_current_bytes_allocated());
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_micropython_mem_peak() {
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_int_t)m_get_peak_bytes_allocated());
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)m_get_peak_bytes_allocated());
|
||||
}
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total);
|
||||
@@ -65,8 +65,8 @@ STATIC const mp_obj_dict_t mp_module_micropython_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_micropython_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_micropython_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_micropython_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_micropython_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_micropython_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -74,13 +74,13 @@ STATIC char get_fmt_type(const char **fmt) {
|
||||
return t;
|
||||
}
|
||||
|
||||
STATIC machine_uint_t get_fmt_num(const char **p) {
|
||||
STATIC mp_uint_t get_fmt_num(const char **p) {
|
||||
const char *num = *p;
|
||||
uint len = 1;
|
||||
while (unichar_isdigit(*++num)) {
|
||||
len++;
|
||||
}
|
||||
machine_uint_t val = (machine_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10));
|
||||
mp_uint_t val = (mp_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10));
|
||||
*p = num;
|
||||
return val;
|
||||
}
|
||||
@@ -99,10 +99,10 @@ STATIC uint calcsize_items(const char *fmt) {
|
||||
STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
|
||||
const char *fmt = mp_obj_str_get_str(fmt_in);
|
||||
char fmt_type = get_fmt_type(&fmt);
|
||||
machine_uint_t size;
|
||||
mp_uint_t size;
|
||||
for (size = 0; *fmt; fmt++) {
|
||||
uint align = 1;
|
||||
machine_uint_t cnt = 1;
|
||||
mp_uint_t cnt = 1;
|
||||
if (unichar_isdigit(*fmt)) {
|
||||
cnt = get_fmt_num(&fmt);
|
||||
}
|
||||
@@ -111,14 +111,14 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
|
||||
assert(*fmt == 's');
|
||||
}
|
||||
|
||||
machine_uint_t sz;
|
||||
mp_uint_t sz;
|
||||
if (*fmt == 's') {
|
||||
sz = cnt;
|
||||
} else {
|
||||
sz = (machine_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
|
||||
sz = (mp_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
|
||||
}
|
||||
// TODO
|
||||
assert(sz != (machine_uint_t)-1);
|
||||
assert(sz != (mp_uint_t)-1);
|
||||
// Apply alignment
|
||||
size = (size + align - 1) & ~(align - 1);
|
||||
size += sz;
|
||||
@@ -138,7 +138,7 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) {
|
||||
byte *p = bufinfo.buf;
|
||||
|
||||
for (uint i = 0; i < size; i++) {
|
||||
machine_uint_t sz = 1;
|
||||
mp_uint_t sz = 1;
|
||||
if (unichar_isdigit(*fmt)) {
|
||||
sz = get_fmt_num(&fmt);
|
||||
}
|
||||
@@ -170,7 +170,7 @@ STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
|
||||
memset(p, 0, size);
|
||||
|
||||
for (uint i = 1; i < n_args; i++) {
|
||||
machine_uint_t sz = 1;
|
||||
mp_uint_t sz = 1;
|
||||
if (unichar_isdigit(*fmt)) {
|
||||
sz = get_fmt_num(&fmt);
|
||||
}
|
||||
@@ -182,7 +182,7 @@ STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) {
|
||||
if (*fmt == 's') {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[i], &bufinfo, MP_BUFFER_READ);
|
||||
machine_uint_t to_copy = sz;
|
||||
mp_uint_t to_copy = sz;
|
||||
if (bufinfo.len < to_copy) {
|
||||
to_copy = bufinfo.len;
|
||||
}
|
||||
@@ -210,8 +210,8 @@ STATIC const mp_obj_dict_t mp_module_struct_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_struct_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_struct_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_struct_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_struct_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_struct_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
25
py/modsys.c
25
py/modsys.c
@@ -24,8 +24,10 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
@@ -33,6 +35,8 @@
|
||||
#include "objlist.h"
|
||||
#include "objtuple.h"
|
||||
#include "objstr.h"
|
||||
#include "mpz.h"
|
||||
#include "objint.h"
|
||||
|
||||
#if MICROPY_PY_SYS
|
||||
|
||||
@@ -44,6 +48,8 @@ extern struct _dummy_t mp_sys_stdin_obj;
|
||||
extern struct _dummy_t mp_sys_stdout_obj;
|
||||
extern struct _dummy_t mp_sys_stderr_obj;
|
||||
|
||||
extern mp_obj_int_t mp_maxsize_obj;
|
||||
|
||||
mp_obj_list_t mp_sys_path_obj;
|
||||
mp_obj_list_t mp_sys_argv_obj;
|
||||
#define I(n) MP_OBJ_NEW_SMALL_INT(n)
|
||||
@@ -70,6 +76,19 @@ STATIC const mp_map_elem_t mp_module_sys_globals_table[] = {
|
||||
#else
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_byteorder), MP_OBJ_NEW_QSTR(MP_QSTR_big) },
|
||||
#endif
|
||||
#if MICROPY_PY_SYS_MAXSIZE
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
|
||||
// INT_MAX is not representable as small int, as we know that small int
|
||||
// takes one bit for tag. So, we have little choice but to provide this
|
||||
// value. Apps also should be careful to not try to compare sys.maxsize
|
||||
// with some number (which may not fit in available int size), but instead
|
||||
// count number of significant bits in sys.maxsize.
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_maxsize), MP_OBJ_NEW_SMALL_INT(INT_MAX >> 1) },
|
||||
#else
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_maxsize), (mp_obj_t)&mp_maxsize_obj },
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if MICROPY_PY_SYS_EXIT
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_exit), (mp_obj_t)&mp_sys_exit_obj },
|
||||
@@ -87,8 +106,8 @@ STATIC const mp_obj_dict_t mp_module_sys_globals = {
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = ARRAY_SIZE(mp_module_sys_globals_table),
|
||||
.alloc = ARRAY_SIZE(mp_module_sys_globals_table),
|
||||
.used = MP_ARRAY_SIZE(mp_module_sys_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_sys_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_sys_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -157,6 +157,12 @@
|
||||
#define MICROPY_ENABLE_GC_FINALISER (0)
|
||||
#endif
|
||||
|
||||
// Whether to check C stack usage. C stack used for calling Python functions,
|
||||
// etc. Not checking means segfault on overflow.
|
||||
#ifndef MICROPY_STACK_CHECK
|
||||
#define MICROPY_STACK_CHECK (1)
|
||||
#endif
|
||||
|
||||
// Whether to include REPL helper function
|
||||
#ifndef MICROPY_HELPER_REPL
|
||||
#define MICROPY_HELPER_REPL (0)
|
||||
@@ -223,6 +229,10 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_BUILTINS_FLOAT (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_BUILTINS_COMPLEX
|
||||
#define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT)
|
||||
#endif
|
||||
|
||||
// Enable features which improve CPython compatibility
|
||||
// but may lead to more code size/memory usage.
|
||||
// TODO: Originally intended as generic category to not
|
||||
@@ -239,6 +249,16 @@ typedef double mp_float_t;
|
||||
/*****************************************************************************/
|
||||
/* Fine control over Python builtins, classes, modules, etc */
|
||||
|
||||
// Whether str object is proper unicode
|
||||
#ifndef MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
|
||||
#endif
|
||||
|
||||
// Whether to support bytearray object
|
||||
#ifndef MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
|
||||
#endif
|
||||
|
||||
// Whether to support set object
|
||||
#ifndef MICROPY_PY_BUILTINS_SET
|
||||
#define MICROPY_PY_BUILTINS_SET (1)
|
||||
@@ -259,6 +279,13 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_BUILTINS_PROPERTY (1)
|
||||
#endif
|
||||
|
||||
// Whether to provide "array" module. Note that large chunk of the
|
||||
// underlying code is shared with "bytearray" builtin type, so to
|
||||
// get real savings, it should be disabled too.
|
||||
#ifndef MICROPY_PY_ARRAY
|
||||
#define MICROPY_PY_ARRAY (1)
|
||||
#endif
|
||||
|
||||
// Whether to provide "collections" module
|
||||
#ifndef MICROPY_PY_COLLECTIONS
|
||||
#define MICROPY_PY_COLLECTIONS (1)
|
||||
@@ -309,6 +336,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_SYS (1)
|
||||
#endif
|
||||
|
||||
// Whether to provide "sys.maxsize" constant
|
||||
#ifndef MICROPY_PY_SYS_MAXSIZE
|
||||
#define MICROPY_PY_SYS_MAXSIZE (0)
|
||||
#endif
|
||||
|
||||
// Whether to provide "sys.exit" function
|
||||
#ifndef MICROPY_PY_SYS_EXIT
|
||||
#define MICROPY_PY_SYS_EXIT (0)
|
||||
@@ -319,6 +351,12 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_SYS_STDFILES (0)
|
||||
#endif
|
||||
|
||||
|
||||
// Extended modules
|
||||
#ifndef MICROPY_PY_UCTYPES
|
||||
#define MICROPY_PY_UCTYPES (0)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Hooks for a port to add builtins */
|
||||
|
||||
@@ -348,8 +386,8 @@ typedef double mp_float_t;
|
||||
|
||||
#define BITS_PER_BYTE (8)
|
||||
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
|
||||
// machine_int_t value with most significant bit set
|
||||
#define WORD_MSBIT_HIGH (((machine_uint_t)1) << (BYTES_PER_WORD * 8 - 1))
|
||||
// mp_int_t value with most significant bit set
|
||||
#define WORD_MSBIT_HIGH (((mp_uint_t)1) << (BYTES_PER_WORD * 8 - 1))
|
||||
|
||||
#if !defined(MP_ENDIANNESS_LITTLE) && !defined(MP_ENDIANNESS_BIG)
|
||||
// Just because most archs are such?
|
||||
@@ -360,14 +398,14 @@ typedef double mp_float_t;
|
||||
#define MP_ENDIANNESS_LITTLE (0)
|
||||
#endif
|
||||
|
||||
// printf format spec to use for machine_int_t and friends
|
||||
// printf format spec to use for mp_int_t and friends
|
||||
#ifndef INT_FMT
|
||||
#ifdef __LP64__
|
||||
// Archs where machine_int_t == long, long != int
|
||||
// Archs where mp_int_t == long, long != int
|
||||
#define UINT_FMT "%lu"
|
||||
#define INT_FMT "%ld"
|
||||
#else
|
||||
// Archs where machine_int_t == int
|
||||
// Archs where mp_int_t == int
|
||||
#define UINT_FMT "%u"
|
||||
#define INT_FMT "%d"
|
||||
#endif
|
||||
@@ -377,3 +415,8 @@ typedef double mp_float_t;
|
||||
#ifndef NORETURN
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#endif
|
||||
|
||||
// Modifier for weak functions
|
||||
#ifndef MP_WEAK
|
||||
#define MP_WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
32
py/mpz.c
32
py/mpz.c
@@ -30,8 +30,8 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "mpz.h"
|
||||
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
|
||||
@@ -351,7 +351,7 @@ STATIC uint mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, uint jlen, mpz_dig_t *kdig
|
||||
modifies den_dig memory, but restors it to original state at end
|
||||
*/
|
||||
|
||||
STATIC void mpn_div(mpz_dig_t *num_dig, machine_uint_t *num_len, mpz_dig_t *den_dig, machine_uint_t den_len, mpz_dig_t *quo_dig, machine_uint_t *quo_len) {
|
||||
STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, mp_uint_t den_len, mpz_dig_t *quo_dig, mp_uint_t *quo_len) {
|
||||
mpz_dig_t *orig_num_dig = num_dig;
|
||||
mpz_dig_t *orig_quo_dig = quo_dig;
|
||||
mpz_dig_t norm_shift = 0;
|
||||
@@ -502,12 +502,12 @@ void mpz_init_zero(mpz_t *z) {
|
||||
z->dig = NULL;
|
||||
}
|
||||
|
||||
void mpz_init_from_int(mpz_t *z, machine_int_t val) {
|
||||
void mpz_init_from_int(mpz_t *z, mp_int_t val) {
|
||||
mpz_init_zero(z);
|
||||
mpz_set_from_int(z, val);
|
||||
}
|
||||
|
||||
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, uint alloc, machine_int_t val) {
|
||||
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, uint alloc, mp_int_t val) {
|
||||
z->neg = 0;
|
||||
z->fixed_dig = 1;
|
||||
z->alloc = alloc;
|
||||
@@ -528,7 +528,7 @@ mpz_t *mpz_zero(void) {
|
||||
return z;
|
||||
}
|
||||
|
||||
mpz_t *mpz_from_int(machine_int_t val) {
|
||||
mpz_t *mpz_from_int(mp_int_t val) {
|
||||
mpz_t *z = mpz_zero();
|
||||
mpz_set_from_int(z, val);
|
||||
return z;
|
||||
@@ -594,10 +594,10 @@ void mpz_set(mpz_t *dest, const mpz_t *src) {
|
||||
memcpy(dest->dig, src->dig, src->len * sizeof(mpz_dig_t));
|
||||
}
|
||||
|
||||
void mpz_set_from_int(mpz_t *z, machine_int_t val) {
|
||||
void mpz_set_from_int(mpz_t *z, mp_int_t val) {
|
||||
mpz_need_dig(z, MPZ_NUM_DIG_FOR_INT);
|
||||
|
||||
machine_uint_t uval;
|
||||
mp_uint_t uval;
|
||||
if (val < 0) {
|
||||
z->neg = 1;
|
||||
uval = -val;
|
||||
@@ -704,7 +704,7 @@ int mpz_cmp(const mpz_t *z1, const mpz_t *z2) {
|
||||
#if 0
|
||||
// obsolete
|
||||
// compares mpz with an integer that fits within DIG_SIZE bits
|
||||
int mpz_cmp_sml_int(const mpz_t *z, machine_int_t sml_int) {
|
||||
int mpz_cmp_sml_int(const mpz_t *z, mp_int_t sml_int) {
|
||||
int cmp;
|
||||
if (z->neg == 0) {
|
||||
if (sml_int < 0) return 1;
|
||||
@@ -830,7 +830,7 @@ void mpz_not_inpl(mpz_t *dest, const mpz_t *z) {
|
||||
/* computes dest = lhs << rhs
|
||||
can have dest, lhs the same
|
||||
*/
|
||||
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs) {
|
||||
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_int_t rhs) {
|
||||
if (lhs->len == 0 || rhs == 0) {
|
||||
mpz_set(dest, lhs);
|
||||
} else if (rhs < 0) {
|
||||
@@ -845,7 +845,7 @@ void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs) {
|
||||
/* computes dest = lhs >> rhs
|
||||
can have dest, lhs the same
|
||||
*/
|
||||
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs) {
|
||||
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_int_t rhs) {
|
||||
if (lhs->len == 0 || rhs == 0) {
|
||||
mpz_set(dest, lhs);
|
||||
} else if (rhs < 0) {
|
||||
@@ -1214,12 +1214,12 @@ mpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs) {
|
||||
#endif
|
||||
|
||||
// TODO check that this correctly handles overflow in all cases
|
||||
machine_int_t mpz_as_int(const mpz_t *i) {
|
||||
machine_int_t val = 0;
|
||||
mp_int_t mpz_as_int(const mpz_t *i) {
|
||||
mp_int_t val = 0;
|
||||
mpz_dig_t *d = i->dig + i->len;
|
||||
|
||||
while (--d >= i->dig) {
|
||||
machine_int_t oldval = val;
|
||||
mp_int_t oldval = val;
|
||||
val = (val << DIG_SIZE) | *d;
|
||||
if (val < oldval) {
|
||||
// overflow, return +/- "infinity"
|
||||
@@ -1241,12 +1241,12 @@ machine_int_t mpz_as_int(const mpz_t *i) {
|
||||
}
|
||||
|
||||
// TODO check that this correctly handles overflow in all cases
|
||||
bool mpz_as_int_checked(const mpz_t *i, machine_int_t *value) {
|
||||
machine_int_t val = 0;
|
||||
bool mpz_as_int_checked(const mpz_t *i, mp_int_t *value) {
|
||||
mp_int_t val = 0;
|
||||
mpz_dig_t *d = i->dig + i->len;
|
||||
|
||||
while (--d >= i->dig) {
|
||||
machine_int_t oldval = val;
|
||||
mp_int_t oldval = val;
|
||||
val = (val << DIG_SIZE) | *d;
|
||||
if (val < oldval) {
|
||||
// overflow
|
||||
|
||||
26
py/mpz.h
26
py/mpz.h
@@ -29,27 +29,27 @@ typedef uint32_t mpz_dbl_dig_t;
|
||||
typedef int32_t mpz_dbl_dig_signed_t;
|
||||
|
||||
typedef struct _mpz_t {
|
||||
machine_uint_t neg : 1;
|
||||
machine_uint_t fixed_dig : 1;
|
||||
machine_uint_t alloc : 30;
|
||||
machine_uint_t len;
|
||||
mp_uint_t neg : 1;
|
||||
mp_uint_t fixed_dig : 1;
|
||||
mp_uint_t alloc : 30;
|
||||
mp_uint_t len;
|
||||
mpz_dig_t *dig;
|
||||
} mpz_t;
|
||||
|
||||
#define MPZ_DIG_SIZE (15) // see mpn_div for why this needs to be at most 15
|
||||
#define MPZ_NUM_DIG_FOR_INT (sizeof(machine_int_t) * 8 / MPZ_DIG_SIZE + 1)
|
||||
#define MPZ_NUM_DIG_FOR_INT (sizeof(mp_int_t) * 8 / MPZ_DIG_SIZE + 1)
|
||||
#define MPZ_NUM_DIG_FOR_LL (sizeof(long long) * 8 / MPZ_DIG_SIZE + 1)
|
||||
|
||||
// convenience macro to declare an mpz with a digit array from the stack, initialised by an integer
|
||||
#define MPZ_CONST_INT(z, val) mpz_t z; mpz_dig_t z ## _digits[MPZ_NUM_DIG_FOR_INT]; mpz_init_fixed_from_int(&z, z_digits, MPZ_NUM_DIG_FOR_INT, val);
|
||||
|
||||
void mpz_init_zero(mpz_t *z);
|
||||
void mpz_init_from_int(mpz_t *z, machine_int_t val);
|
||||
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, uint dig_alloc, machine_int_t val);
|
||||
void mpz_init_from_int(mpz_t *z, mp_int_t val);
|
||||
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, uint dig_alloc, mp_int_t val);
|
||||
void mpz_deinit(mpz_t *z);
|
||||
|
||||
mpz_t *mpz_zero();
|
||||
mpz_t *mpz_from_int(machine_int_t i);
|
||||
mpz_t *mpz_from_int(mp_int_t i);
|
||||
mpz_t *mpz_from_ll(long long i);
|
||||
mpz_t *mpz_from_str(const char *str, uint len, bool neg, uint base);
|
||||
void mpz_free(mpz_t *z);
|
||||
@@ -57,7 +57,7 @@ void mpz_free(mpz_t *z);
|
||||
mpz_t *mpz_clone(const mpz_t *src);
|
||||
|
||||
void mpz_set(mpz_t *dest, const mpz_t *src);
|
||||
void mpz_set_from_int(mpz_t *z, machine_int_t src);
|
||||
void mpz_set_from_int(mpz_t *z, mp_int_t src);
|
||||
void mpz_set_from_ll(mpz_t *z, long long i);
|
||||
uint mpz_set_from_str(mpz_t *z, const char *str, uint len, bool neg, uint base);
|
||||
|
||||
@@ -79,8 +79,8 @@ mpz_t *mpz_pow(const mpz_t *lhs, const mpz_t *rhs);
|
||||
void mpz_abs_inpl(mpz_t *dest, const mpz_t *z);
|
||||
void mpz_neg_inpl(mpz_t *dest, const mpz_t *z);
|
||||
void mpz_not_inpl(mpz_t *dest, const mpz_t *z);
|
||||
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs);
|
||||
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, machine_int_t rhs);
|
||||
void mpz_shl_inpl(mpz_t *dest, const mpz_t *lhs, mp_int_t rhs);
|
||||
void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_int_t rhs);
|
||||
void mpz_add_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
||||
void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
||||
void mpz_mul_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs);
|
||||
@@ -96,8 +96,8 @@ void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const m
|
||||
mpz_t *mpz_div(const mpz_t *lhs, const mpz_t *rhs);
|
||||
mpz_t *mpz_mod(const mpz_t *lhs, const mpz_t *rhs);
|
||||
|
||||
machine_int_t mpz_as_int(const mpz_t *z);
|
||||
bool mpz_as_int_checked(const mpz_t *z, machine_int_t *value);
|
||||
mp_int_t mpz_as_int(const mpz_t *z);
|
||||
bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_float_t mpz_as_float(const mpz_t *z);
|
||||
#endif
|
||||
|
||||
3
py/nlr.h
3
py/nlr.h
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef struct _nlr_buf_t nlr_buf_t;
|
||||
struct _nlr_buf_t {
|
||||
@@ -44,7 +45,7 @@ struct _nlr_buf_t {
|
||||
#else
|
||||
void *regs[8];
|
||||
#endif
|
||||
#elif defined(__thumb2__)
|
||||
#elif defined(__thumb2__) || defined(__thumb__) || defined(__arm__)
|
||||
void *regs[10];
|
||||
#else
|
||||
#define MICROPY_NLR_SETJMP (1)
|
||||
|
||||
@@ -24,19 +24,21 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(__thumb2__) && !MICROPY_NLR_SETJMP
|
||||
/* thumb callee save: bx, bp, sp, r12, r14, r14, r15 */
|
||||
#if !MICROPY_NLR_SETJMP && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
|
||||
/* arm callee save: bx, bp, sp, r12, r14, r14, r15 */
|
||||
|
||||
.syntax unified
|
||||
/*.cpu cortex-m4*/
|
||||
.thumb
|
||||
/*.thumb*/
|
||||
.text
|
||||
.align 2
|
||||
|
||||
/* uint nlr_push(r0=nlr_buf_t *nlr) */
|
||||
.global nlr_push
|
||||
#if defined(__thumb2__)
|
||||
.thumb
|
||||
.thumb_func
|
||||
#endif
|
||||
.type nlr_push, %function
|
||||
nlr_push:
|
||||
str lr, [r0, #8] @ store lr into nlr_buf
|
||||
@@ -64,8 +66,10 @@ nlr_push:
|
||||
|
||||
@ void nlr_pop()
|
||||
.global nlr_pop
|
||||
#if defined(__thumb2__)
|
||||
.thumb
|
||||
.thumb_func
|
||||
#endif
|
||||
.type nlr_pop, %function
|
||||
nlr_pop:
|
||||
ldr r3, .L5 @ load addr of nlr_top
|
||||
@@ -80,8 +84,10 @@ nlr_pop:
|
||||
|
||||
/* void nlr_jump(r0=uint val) */
|
||||
.global nlr_jump
|
||||
#if defined(__thumb2__)
|
||||
.thumb
|
||||
.thumb_func
|
||||
#endif
|
||||
.type nlr_jump, %function
|
||||
nlr_jump:
|
||||
ldr r3, .L2 @ load addr of nlr_top
|
||||
|
||||
34
py/obj.c
34
py/obj.c
@@ -35,6 +35,7 @@
|
||||
#include "obj.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "stackctrl.h"
|
||||
|
||||
mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(o_in)) {
|
||||
@@ -59,6 +60,8 @@ void printf_wrapper(void *env, const char *fmt, ...) {
|
||||
}
|
||||
|
||||
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
|
||||
// There can be data structures nested too deep, or just recursive
|
||||
MP_STACK_CHECK();
|
||||
#if !NDEBUG
|
||||
if (o_in == NULL) {
|
||||
print(env, "(nil)");
|
||||
@@ -80,7 +83,7 @@ void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
|
||||
// helper function to print an exception with traceback
|
||||
void mp_obj_print_exception(mp_obj_t exc) {
|
||||
if (mp_obj_is_exception_instance(exc)) {
|
||||
machine_uint_t n, *values;
|
||||
mp_uint_t n, *values;
|
||||
mp_obj_exception_get_traceback(exc, &n, &values);
|
||||
if (n > 0) {
|
||||
assert(n % 3 == 0);
|
||||
@@ -142,7 +145,7 @@ bool mp_obj_is_callable(mp_obj_t o_in) {
|
||||
return mp_obj_get_type(o_in)->call != NULL;
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_hash(mp_obj_t o_in) {
|
||||
mp_int_t mp_obj_hash(mp_obj_t o_in) {
|
||||
if (o_in == mp_const_false) {
|
||||
return 0; // needs to hash to same as the integer 0, since False==0
|
||||
} else if (o_in == mp_const_true) {
|
||||
@@ -152,13 +155,13 @@ machine_int_t mp_obj_hash(mp_obj_t o_in) {
|
||||
} else if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
|
||||
return mp_obj_str_get_hash(o_in);
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_NoneType)) {
|
||||
return (machine_int_t)o_in;
|
||||
return (mp_int_t)o_in;
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_fun_native) || MP_OBJ_IS_TYPE(o_in, &mp_type_fun_bc)) {
|
||||
return (machine_int_t)o_in;
|
||||
return (mp_int_t)o_in;
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_tuple)) {
|
||||
return mp_obj_tuple_hash(o_in);
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &mp_type_type)) {
|
||||
return (machine_int_t)o_in;
|
||||
return (mp_int_t)o_in;
|
||||
|
||||
// TODO hash class and instances
|
||||
// TODO delegate to __hash__ method if it exists
|
||||
@@ -222,7 +225,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_get_int(mp_const_obj_t arg) {
|
||||
mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
|
||||
// This function essentially performs implicit type conversion to int
|
||||
// Note that Python does NOT provide implicit type conversion from
|
||||
// float to int in the core expression language, try some_list[1.0].
|
||||
@@ -241,8 +244,8 @@ machine_int_t mp_obj_get_int(mp_const_obj_t arg) {
|
||||
|
||||
// returns false if arg is not of integral type
|
||||
// returns true and sets *value if it is of integral type
|
||||
// can throw OverflowError if arg is of integral type, but doesn't fit in a machine_int_t
|
||||
bool mp_obj_get_int_maybe(mp_const_obj_t arg, machine_int_t *value) {
|
||||
// can throw OverflowError if arg is of integral type, but doesn't fit in a mp_int_t
|
||||
bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) {
|
||||
if (arg == mp_const_false) {
|
||||
*value = 0;
|
||||
} else if (arg == mp_const_true) {
|
||||
@@ -274,6 +277,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
|
||||
}
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
|
||||
if (arg == mp_const_false) {
|
||||
*real = 0;
|
||||
@@ -297,6 +301,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items) {
|
||||
if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {
|
||||
@@ -325,8 +330,8 @@ void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items) {
|
||||
}
|
||||
|
||||
// is_slice determines whether the index is a slice index
|
||||
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index, bool is_slice) {
|
||||
machine_int_t i;
|
||||
uint mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice) {
|
||||
mp_int_t i;
|
||||
if (MP_OBJ_IS_SMALL_INT(index)) {
|
||||
i = MP_OBJ_SMALL_INT_VALUE(index);
|
||||
} else if (!mp_obj_get_int_maybe(index, &i)) {
|
||||
@@ -352,8 +357,13 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index,
|
||||
|
||||
// may return MP_OBJ_NULL
|
||||
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
|
||||
if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_str_get_len(o_in));
|
||||
if (
|
||||
#if !MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
// It's simple - unicode is slow, non-unicode is fast
|
||||
MP_OBJ_IS_STR(o_in) ||
|
||||
#endif
|
||||
MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) {
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)mp_obj_str_get_len(o_in));
|
||||
} else {
|
||||
mp_obj_type_t *type = mp_obj_get_type(o_in);
|
||||
if (type->unary_op != NULL) {
|
||||
|
||||
85
py/obj.h
85
py/obj.h
@@ -35,11 +35,6 @@
|
||||
typedef machine_ptr_t mp_obj_t;
|
||||
typedef machine_const_ptr_t mp_const_obj_t;
|
||||
|
||||
// Integers that fit in a pointer have this type
|
||||
// (do we need to expose this in the public API?)
|
||||
|
||||
typedef machine_int_t mp_small_int_t;
|
||||
|
||||
// Anything that wants to be a Micro Python object must have
|
||||
// mp_obj_base_t as its first member (except small ints and qstrs)
|
||||
|
||||
@@ -73,18 +68,18 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
|
||||
// These macros check for small int, qstr or object, and access small int and qstr values
|
||||
|
||||
// these macros have now become inline functions; see below
|
||||
//#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0)
|
||||
//#define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2)
|
||||
//#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0)
|
||||
//#define MP_OBJ_IS_SMALL_INT(o) ((((mp_int_t)(o)) & 1) != 0)
|
||||
//#define MP_OBJ_IS_QSTR(o) ((((mp_int_t)(o)) & 3) == 2)
|
||||
//#define MP_OBJ_IS_OBJ(o) ((((mp_int_t)(o)) & 3) == 0)
|
||||
#define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))) // this does not work for checking a string, use below macro for that
|
||||
#define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int))
|
||||
#define MP_OBJ_IS_STR(o) (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str))
|
||||
|
||||
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_small_int_t)(o)) >> 1)
|
||||
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_int_t)(o)) >> 1)
|
||||
#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((small_int) << 1) | 1))
|
||||
|
||||
#define MP_OBJ_QSTR_VALUE(o) (((mp_small_int_t)(o)) >> 2)
|
||||
#define MP_OBJ_NEW_QSTR(qstr) ((mp_obj_t)((((machine_uint_t)qstr) << 2) | 2))
|
||||
#define MP_OBJ_QSTR_VALUE(o) (((mp_int_t)(o)) >> 2)
|
||||
#define MP_OBJ_NEW_QSTR(qstr) ((mp_obj_t)((((mp_uint_t)qstr) << 2) | 2))
|
||||
|
||||
// These macros are used to declare and define constant function objects
|
||||
// You can put "static" in front of the definitions to make them local
|
||||
@@ -137,10 +132,10 @@ typedef struct _mp_map_elem_t {
|
||||
// would also need a trucated dict structure
|
||||
|
||||
typedef struct _mp_map_t {
|
||||
machine_uint_t all_keys_are_qstrs : 1;
|
||||
machine_uint_t table_is_fixed_array : 1;
|
||||
machine_uint_t used : (8 * sizeof(machine_uint_t) - 2);
|
||||
machine_uint_t alloc;
|
||||
mp_uint_t all_keys_are_qstrs : 1;
|
||||
mp_uint_t table_is_fixed_array : 1;
|
||||
mp_uint_t used : (8 * sizeof(mp_uint_t) - 2);
|
||||
mp_uint_t alloc;
|
||||
mp_map_elem_t *table;
|
||||
} mp_map_t;
|
||||
|
||||
@@ -151,7 +146,7 @@ typedef enum _mp_map_lookup_kind_t {
|
||||
MP_MAP_LOOKUP_REMOVE_IF_FOUND, // 2
|
||||
} mp_map_lookup_kind_t;
|
||||
|
||||
static inline bool MP_MAP_SLOT_IS_FILLED(const mp_map_t *map, machine_uint_t pos) { return ((map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL); }
|
||||
static inline bool MP_MAP_SLOT_IS_FILLED(const mp_map_t *map, mp_uint_t pos) { return ((map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL); }
|
||||
|
||||
void mp_map_init(mp_map_t *map, int n);
|
||||
void mp_map_init_fixed_table(mp_map_t *map, int n, const mp_obj_t *table);
|
||||
@@ -165,12 +160,12 @@ void mp_map_dump(mp_map_t *map);
|
||||
// Underlying set implementation (not set object)
|
||||
|
||||
typedef struct _mp_set_t {
|
||||
machine_uint_t alloc;
|
||||
machine_uint_t used;
|
||||
mp_uint_t alloc;
|
||||
mp_uint_t used;
|
||||
mp_obj_t *table;
|
||||
} mp_set_t;
|
||||
|
||||
static inline bool MP_SET_SLOT_IS_FILLED(const mp_set_t *set, machine_uint_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); }
|
||||
static inline bool MP_SET_SLOT_IS_FILLED(const mp_set_t *set, mp_uint_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); }
|
||||
|
||||
void mp_set_init(mp_set_t *set, int n);
|
||||
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);
|
||||
@@ -216,7 +211,7 @@ typedef struct _mp_buffer_info_t {
|
||||
//int ver; // ?
|
||||
|
||||
void *buf;
|
||||
machine_int_t len; // in bytes
|
||||
mp_int_t len; // in bytes
|
||||
int typecode; // as per binary.h
|
||||
|
||||
// Rationale: to load arbitrary-sized sprites directly to LCD
|
||||
@@ -227,7 +222,7 @@ typedef struct _mp_buffer_info_t {
|
||||
#define MP_BUFFER_WRITE (2)
|
||||
#define MP_BUFFER_RW (MP_BUFFER_READ | MP_BUFFER_WRITE)
|
||||
typedef struct _mp_buffer_p_t {
|
||||
machine_int_t (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
|
||||
mp_int_t (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
|
||||
} mp_buffer_p_t;
|
||||
bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
|
||||
void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
|
||||
@@ -236,8 +231,8 @@ void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, int flags);
|
||||
typedef struct _mp_stream_p_t {
|
||||
// On error, functions should return -1 and fill in *errcode (values are
|
||||
// implementation-dependent, but will be exposed to user, e.g. via exception).
|
||||
machine_int_t (*read)(mp_obj_t obj, void *buf, machine_uint_t size, int *errcode);
|
||||
machine_int_t (*write)(mp_obj_t obj, const void *buf, machine_uint_t size, int *errcode);
|
||||
mp_int_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
|
||||
mp_int_t (*write)(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode);
|
||||
// add seek() ?
|
||||
int is_bytes : 1;
|
||||
} mp_stream_p_t;
|
||||
@@ -365,8 +360,8 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict);
|
||||
mp_obj_t mp_obj_new_none(void);
|
||||
mp_obj_t mp_obj_new_bool(bool value);
|
||||
mp_obj_t mp_obj_new_cell(mp_obj_t obj);
|
||||
mp_obj_t mp_obj_new_int(machine_int_t value);
|
||||
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value);
|
||||
mp_obj_t mp_obj_new_int(mp_int_t value);
|
||||
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value);
|
||||
mp_obj_t mp_obj_new_int_from_str_len(const char **str, uint len, bool neg, uint base);
|
||||
mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception)
|
||||
mp_obj_t mp_obj_new_str(const char* data, uint len, bool make_qstr_if_not_already);
|
||||
@@ -406,20 +401,20 @@ void mp_obj_print_exception(mp_obj_t exc);
|
||||
int mp_obj_is_true(mp_obj_t arg);
|
||||
|
||||
// TODO make these all lower case when they have proven themselves
|
||||
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o) { return ((((mp_small_int_t)(o)) & 3) == 0); }
|
||||
static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o) { return ((((mp_small_int_t)(o)) & 1) != 0); }
|
||||
static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 0); }
|
||||
static inline bool MP_OBJ_IS_SMALL_INT(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 1) != 0); }
|
||||
//static inline bool MP_OBJ_IS_TYPE(mp_const_obj_t o, const mp_obj_type_t *t) { return (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))); } // this does not work for checking a string, use below macro for that
|
||||
//static inline bool MP_OBJ_IS_INT(mp_const_obj_t o) { return (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int)); } // returns true if o is a small int or long int
|
||||
static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_bool); } // returns true if o is bool, small int or long int
|
||||
static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o) { return ((((mp_small_int_t)(o)) & 3) == 2); }
|
||||
static inline bool MP_OBJ_IS_QSTR(mp_const_obj_t o) { return ((((mp_int_t)(o)) & 3) == 2); }
|
||||
//static inline bool MP_OBJ_IS_STR(mp_const_obj_t o) { return (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str)); }
|
||||
|
||||
bool mp_obj_is_callable(mp_obj_t o_in);
|
||||
machine_int_t mp_obj_hash(mp_obj_t o_in);
|
||||
mp_int_t mp_obj_hash(mp_obj_t o_in);
|
||||
bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2);
|
||||
|
||||
machine_int_t mp_obj_get_int(mp_const_obj_t arg);
|
||||
bool mp_obj_get_int_maybe(mp_const_obj_t arg, machine_int_t *value);
|
||||
mp_int_t mp_obj_get_int(mp_const_obj_t arg);
|
||||
bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_float_t mp_obj_get_float(mp_obj_t self_in);
|
||||
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
|
||||
@@ -427,26 +422,26 @@ void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
|
||||
//qstr mp_obj_get_qstr(mp_obj_t arg);
|
||||
void mp_obj_get_array(mp_obj_t o, uint *len, mp_obj_t **items);
|
||||
void mp_obj_get_array_fixed_n(mp_obj_t o, uint len, mp_obj_t **items);
|
||||
uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index, bool is_slice);
|
||||
uint mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice);
|
||||
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); /* may return MP_OBJ_NULL */
|
||||
mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t val);
|
||||
|
||||
// bool
|
||||
// TODO make lower case when it has proven itself
|
||||
static inline mp_obj_t MP_BOOL(machine_int_t x) { return x ? mp_const_true : mp_const_false; }
|
||||
static inline mp_obj_t MP_BOOL(mp_int_t x) { return x ? mp_const_true : mp_const_false; }
|
||||
|
||||
// cell
|
||||
mp_obj_t mp_obj_cell_get(mp_obj_t self_in);
|
||||
void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj);
|
||||
|
||||
// int
|
||||
// For long int, returns value truncated to machine_int_t
|
||||
machine_int_t mp_obj_int_get(mp_const_obj_t self_in);
|
||||
// For long int, returns value truncated to mp_int_t
|
||||
mp_int_t mp_obj_int_get(mp_const_obj_t self_in);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_float_t mp_obj_int_as_float(mp_obj_t self_in);
|
||||
#endif
|
||||
// Will raise exception if value doesn't fit into machine_int_t
|
||||
machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in);
|
||||
// Will raise exception if value doesn't fit into mp_int_t
|
||||
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in);
|
||||
|
||||
// exception
|
||||
#define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new)
|
||||
@@ -454,8 +449,8 @@ bool mp_obj_is_exception_type(mp_obj_t self_in);
|
||||
bool mp_obj_is_exception_instance(mp_obj_t self_in);
|
||||
bool mp_obj_exception_match(mp_obj_t exc, const mp_obj_type_t *exc_type);
|
||||
void mp_obj_exception_clear_traceback(mp_obj_t self_in);
|
||||
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block);
|
||||
void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values);
|
||||
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line, qstr block);
|
||||
void mp_obj_exception_get_traceback(mp_obj_t self_in, mp_uint_t *n, mp_uint_t **values);
|
||||
mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
|
||||
|
||||
@@ -469,7 +464,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway conve
|
||||
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
|
||||
const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len);
|
||||
mp_obj_t mp_obj_str_intern(mp_obj_t str);
|
||||
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len);
|
||||
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len, bool is_bytes);
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
// float
|
||||
@@ -488,7 +483,7 @@ mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_im
|
||||
// tuple
|
||||
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
|
||||
void mp_obj_tuple_del(mp_obj_t self_in);
|
||||
machine_int_t mp_obj_tuple_hash(mp_obj_t self_in);
|
||||
mp_int_t mp_obj_tuple_hash(mp_obj_t self_in);
|
||||
|
||||
// list
|
||||
struct _mp_obj_list_t;
|
||||
@@ -562,14 +557,14 @@ const mp_obj_t *mp_obj_property_get(mp_obj_t self_in);
|
||||
|
||||
// slice indexes resolved to particular sequence
|
||||
typedef struct {
|
||||
machine_uint_t start;
|
||||
machine_uint_t stop;
|
||||
machine_int_t step;
|
||||
mp_uint_t start;
|
||||
mp_uint_t stop;
|
||||
mp_int_t step;
|
||||
} mp_bound_slice_t;
|
||||
|
||||
void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest);
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes);
|
||||
bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes);
|
||||
#endif
|
||||
#define mp_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t))
|
||||
#define mp_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); }
|
||||
|
||||
@@ -37,13 +37,15 @@
|
||||
#include "runtime.h"
|
||||
#include "binary.h"
|
||||
|
||||
#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
|
||||
typedef struct _mp_obj_array_t {
|
||||
mp_obj_base_t base;
|
||||
machine_uint_t typecode : 8;
|
||||
mp_uint_t typecode : 8;
|
||||
// free is number of unused elements after len used elements
|
||||
// alloc size = len + free
|
||||
machine_uint_t free : (8 * sizeof(machine_uint_t) - 8);
|
||||
machine_uint_t len; // in elements
|
||||
mp_uint_t free : (8 * sizeof(mp_uint_t) - 8);
|
||||
mp_uint_t len; // in elements
|
||||
void *items;
|
||||
} mp_obj_array_t;
|
||||
|
||||
@@ -58,7 +60,7 @@ STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *en
|
||||
mp_obj_array_t *o = o_in;
|
||||
if (o->typecode == BYTEARRAY_TYPECODE) {
|
||||
print(env, "bytearray(b", o->typecode);
|
||||
mp_str_print_quoted(print, env, o->items, o->len);
|
||||
mp_str_print_quoted(print, env, o->items, o->len, true);
|
||||
} else {
|
||||
print(env, "array('%c'", o->typecode);
|
||||
if (o->len > 0) {
|
||||
@@ -204,7 +206,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
||||
}
|
||||
}
|
||||
|
||||
STATIC machine_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, int flags) {
|
||||
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, int flags) {
|
||||
mp_obj_array_t *o = o_in;
|
||||
bufinfo->buf = o->items;
|
||||
bufinfo->len = o->len * mp_binary_get_size('@', o->typecode, NULL);
|
||||
@@ -283,7 +285,7 @@ mp_obj_t mp_obj_new_bytearray_by_ref(uint n, void *items) {
|
||||
typedef struct _mp_obj_array_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_array_t *array;
|
||||
machine_uint_t cur;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_array_it_t;
|
||||
|
||||
STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
|
||||
@@ -310,3 +312,5 @@ STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
|
||||
o->cur = 0;
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
|
||||
@@ -61,7 +61,7 @@ STATIC mp_obj_t bool_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp
|
||||
}
|
||||
|
||||
STATIC mp_obj_t bool_unary_op(int op, mp_obj_t o_in) {
|
||||
machine_int_t value = ((mp_obj_bool_t*)o_in)->value;
|
||||
mp_int_t value = ((mp_obj_bool_t*)o_in)->value;
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL: return o_in;
|
||||
case MP_UNARY_OP_POSITIVE: return MP_OBJ_NEW_SMALL_INT(value);
|
||||
@@ -74,7 +74,7 @@ STATIC mp_obj_t bool_unary_op(int op, mp_obj_t o_in) {
|
||||
|
||||
STATIC mp_obj_t bool_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
if (MP_BINARY_OP_OR <= op && op <= MP_BINARY_OP_NOT_EQUAL) {
|
||||
return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_is_true(lhs_in)), rhs_in);
|
||||
return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT((mp_int_t)mp_obj_is_true(lhs_in)), rhs_in);
|
||||
}
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
typedef struct _mp_obj_closure_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t fun;
|
||||
machine_uint_t n_closed;
|
||||
mp_uint_t n_closed;
|
||||
mp_obj_t closed[];
|
||||
} mp_obj_closure_t;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
||||
14
py/objdict.c
14
py/objdict.c
@@ -75,7 +75,7 @@ STATIC mp_obj_t dict_unary_op(int op, mp_obj_t self_in) {
|
||||
mp_obj_dict_t *self = self_in;
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL: return MP_BOOL(self->map.used != 0);
|
||||
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->map.used);
|
||||
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((mp_int_t)self->map.used);
|
||||
default: return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
@@ -94,10 +94,10 @@ STATIC mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
return mp_const_false;
|
||||
}
|
||||
|
||||
machine_uint_t size = o->map.alloc;
|
||||
mp_uint_t size = o->map.alloc;
|
||||
mp_map_t *map = &o->map;
|
||||
|
||||
for (machine_uint_t i = 0; i < size; i++) {
|
||||
for (mp_uint_t i = 0; i < size; i++) {
|
||||
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
|
||||
mp_map_elem_t *elem = mp_map_lookup(&rhs->map, map->table[i].key, MP_MAP_LOOKUP);
|
||||
if (elem == NULL || !mp_obj_equal(map->table[i].value, elem->value)) {
|
||||
@@ -155,12 +155,12 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
typedef struct _mp_obj_dict_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_dict_t *dict;
|
||||
machine_uint_t cur;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_dict_it_t;
|
||||
|
||||
STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in) {
|
||||
mp_obj_dict_it_t *self = self_in;
|
||||
machine_uint_t max = self->dict->map.alloc;
|
||||
mp_uint_t max = self->dict->map.alloc;
|
||||
mp_map_t *map = &self->dict->map;
|
||||
|
||||
for (int i = self->cur; i < max; i++) {
|
||||
@@ -374,7 +374,7 @@ STATIC mp_obj_t dict_update(uint n_args, const mp_obj_t *args, mp_map_t *kwargs)
|
||||
}
|
||||
|
||||
// update the dict with any keyword args
|
||||
for (machine_uint_t i = 0; i < kwargs->alloc; i++) {
|
||||
for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
|
||||
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
|
||||
mp_map_lookup(&self->map, kwargs->table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = kwargs->table[i].value;
|
||||
}
|
||||
@@ -403,7 +403,7 @@ typedef struct _mp_obj_dict_view_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_dict_view_kind_t kind;
|
||||
mp_obj_dict_it_t *iter;
|
||||
machine_uint_t cur;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_dict_view_it_t;
|
||||
|
||||
typedef struct _mp_obj_dict_view_t {
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
@@ -36,7 +36,7 @@
|
||||
typedef struct _mp_obj_enumerate_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t iter;
|
||||
machine_int_t cur;
|
||||
mp_int_t cur;
|
||||
} mp_obj_enumerate_t;
|
||||
|
||||
STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in);
|
||||
@@ -45,7 +45,7 @@ STATIC const mp_arg_t enumerate_make_new_args[] = {
|
||||
{ MP_QSTR_iterable, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_start, MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
#define ENUMERATE_MAKE_NEW_NUM_ARGS ARRAY_SIZE(enumerate_make_new_args)
|
||||
#define ENUMERATE_MAKE_NEW_NUM_ARGS MP_ARRAY_SIZE(enumerate_make_new_args)
|
||||
|
||||
STATIC mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "objtype.h"
|
||||
#include "runtime.h"
|
||||
#include "runtime0.h"
|
||||
#include "gc.h"
|
||||
|
||||
typedef struct _mp_obj_exception_t {
|
||||
mp_obj_base_t base;
|
||||
@@ -334,19 +335,26 @@ void mp_obj_exception_clear_traceback(mp_obj_t self_in) {
|
||||
self->traceback = MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, machine_uint_t line, qstr block) {
|
||||
void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, mp_uint_t line, qstr block) {
|
||||
#if MICROPY_ENABLE_GC
|
||||
if (gc_is_locked()) {
|
||||
// We can't allocate memory, so don't bother to try
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
GET_NATIVE_EXCEPTION(self, self_in);
|
||||
|
||||
// for traceback, we are just using the list object for convenience, it's not really a list of Python objects
|
||||
if (self->traceback == MP_OBJ_NULL) {
|
||||
self->traceback = mp_obj_new_list(0, NULL);
|
||||
}
|
||||
mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)file);
|
||||
mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)line);
|
||||
mp_obj_list_append(self->traceback, (mp_obj_t)(machine_uint_t)block);
|
||||
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)file);
|
||||
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)line);
|
||||
mp_obj_list_append(self->traceback, (mp_obj_t)(mp_uint_t)block);
|
||||
}
|
||||
|
||||
void mp_obj_exception_get_traceback(mp_obj_t self_in, machine_uint_t *n, machine_uint_t **values) {
|
||||
void mp_obj_exception_get_traceback(mp_obj_t self_in, mp_uint_t *n, mp_uint_t **values) {
|
||||
GET_NATIVE_EXCEPTION(self, self_in);
|
||||
|
||||
if (self->traceback == MP_OBJ_NULL) {
|
||||
|
||||
@@ -102,9 +102,12 @@ STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) {
|
||||
|
||||
STATIC mp_obj_t float_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
mp_obj_float_t *lhs = lhs_in;
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
|
||||
return mp_obj_complex_binary_op(op, lhs->value, 0, rhs_in);
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
return mp_obj_float_binary_op(op, lhs->value, rhs_in);
|
||||
}
|
||||
}
|
||||
|
||||
42
py/objfun.c
42
py/objfun.c
@@ -39,6 +39,7 @@
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "bc.h"
|
||||
#include "stackctrl.h"
|
||||
|
||||
#if 0 // print debugging info
|
||||
#define DEBUG_PRINT (1)
|
||||
@@ -196,7 +197,7 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, ui
|
||||
// With this macro you can tune the maximum number of function state bytes
|
||||
// that will be allocated on the stack. Any function that needs more
|
||||
// than this will use the heap.
|
||||
#define VM_MAX_STATE_ON_STACK (10 * sizeof(machine_uint_t))
|
||||
#define VM_MAX_STATE_ON_STACK (10 * sizeof(mp_uint_t))
|
||||
|
||||
// Set this to enable a simple stack overflow check.
|
||||
#define VM_DETECT_STACK_OVERFLOW (0)
|
||||
@@ -204,8 +205,10 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, uint expected, ui
|
||||
// code_state should have ->ip filled in (pointing past code info block),
|
||||
// as well as ->n_state.
|
||||
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, uint n_args, uint 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.
|
||||
mp_obj_fun_bc_t *self = self_in;
|
||||
machine_uint_t n_state = code_state->n_state;
|
||||
mp_uint_t n_state = code_state->n_state;
|
||||
const byte *ip = code_state->ip;
|
||||
|
||||
code_state->code_info = self->bytecode;
|
||||
@@ -353,8 +356,7 @@ continue2:;
|
||||
|
||||
|
||||
STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint 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.
|
||||
MP_STACK_CHECK();
|
||||
|
||||
DEBUG_printf("Input n_args: %d, n_kw: %d\n", n_args, n_kw);
|
||||
DEBUG_printf("Input pos args: ");
|
||||
@@ -367,12 +369,12 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_o
|
||||
const byte *ip = self->bytecode;
|
||||
|
||||
// get code info size, and skip line number table
|
||||
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
|
||||
mp_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
|
||||
ip += code_info_size;
|
||||
|
||||
// bytecode prelude: state size and exception stack size; 16 bit uints
|
||||
machine_uint_t n_state = ip[0] | (ip[1] << 8);
|
||||
machine_uint_t n_exc_stack = ip[2] | (ip[3] << 8);
|
||||
mp_uint_t n_state = ip[0] | (ip[1] << 8);
|
||||
mp_uint_t n_exc_stack = ip[2] | (ip[3] << 8);
|
||||
ip += 4;
|
||||
|
||||
#if VM_DETECT_STACK_OVERFLOW
|
||||
@@ -507,13 +509,13 @@ typedef struct _mp_obj_fun_asm_t {
|
||||
void *fun;
|
||||
} mp_obj_fun_asm_t;
|
||||
|
||||
typedef machine_uint_t (*inline_asm_fun_0_t)();
|
||||
typedef machine_uint_t (*inline_asm_fun_1_t)(machine_uint_t);
|
||||
typedef machine_uint_t (*inline_asm_fun_2_t)(machine_uint_t, machine_uint_t);
|
||||
typedef machine_uint_t (*inline_asm_fun_3_t)(machine_uint_t, machine_uint_t, machine_uint_t);
|
||||
typedef mp_uint_t (*inline_asm_fun_0_t)();
|
||||
typedef mp_uint_t (*inline_asm_fun_1_t)(mp_uint_t);
|
||||
typedef mp_uint_t (*inline_asm_fun_2_t)(mp_uint_t, mp_uint_t);
|
||||
typedef mp_uint_t (*inline_asm_fun_3_t)(mp_uint_t, mp_uint_t, mp_uint_t);
|
||||
|
||||
// convert a Micro Python object to a sensible value for inline asm
|
||||
STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
|
||||
STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
|
||||
// TODO for byte_array, pass pointer to the array
|
||||
if (MP_OBJ_IS_SMALL_INT(obj)) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(obj);
|
||||
@@ -526,42 +528,42 @@ STATIC machine_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
|
||||
} else if (MP_OBJ_IS_STR(obj)) {
|
||||
// pointer to the string (it's probably constant though!)
|
||||
uint l;
|
||||
return (machine_uint_t)mp_obj_str_get_data(obj, &l);
|
||||
return (mp_uint_t)mp_obj_str_get_data(obj, &l);
|
||||
} else {
|
||||
mp_obj_type_t *type = mp_obj_get_type(obj);
|
||||
if (0) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
} else if (type == &mp_type_float) {
|
||||
// convert float to int (could also pass in float registers)
|
||||
return (machine_int_t)mp_obj_float_get(obj);
|
||||
return (mp_int_t)mp_obj_float_get(obj);
|
||||
#endif
|
||||
} else if (type == &mp_type_tuple) {
|
||||
// pointer to start of tuple (could pass length, but then could use len(x) for that)
|
||||
uint len;
|
||||
mp_obj_t *items;
|
||||
mp_obj_tuple_get(obj, &len, &items);
|
||||
return (machine_uint_t)items;
|
||||
return (mp_uint_t)items;
|
||||
} else if (type == &mp_type_list) {
|
||||
// pointer to start of list (could pass length, but then could use len(x) for that)
|
||||
uint len;
|
||||
mp_obj_t *items;
|
||||
mp_obj_list_get(obj, &len, &items);
|
||||
return (machine_uint_t)items;
|
||||
return (mp_uint_t)items;
|
||||
} else {
|
||||
mp_buffer_info_t bufinfo;
|
||||
if (mp_get_buffer(obj, &bufinfo, MP_BUFFER_WRITE)) {
|
||||
// supports the buffer protocol, return a pointer to the data
|
||||
return (machine_uint_t)bufinfo.buf;
|
||||
return (mp_uint_t)bufinfo.buf;
|
||||
} else {
|
||||
// just pass along a pointer to the object
|
||||
return (machine_uint_t)obj;
|
||||
return (mp_uint_t)obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// convert a return value from inline asm to a sensible Micro Python object
|
||||
STATIC mp_obj_t convert_val_from_inline_asm(machine_uint_t val) {
|
||||
STATIC mp_obj_t convert_val_from_inline_asm(mp_uint_t val) {
|
||||
return MP_OBJ_NEW_SMALL_INT(val);
|
||||
}
|
||||
|
||||
@@ -570,7 +572,7 @@ STATIC mp_obj_t fun_asm_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_
|
||||
|
||||
mp_arg_check_num(n_args, n_kw, self->n_args, self->n_args, false);
|
||||
|
||||
machine_uint_t ret;
|
||||
mp_uint_t ret;
|
||||
if (n_args == 0) {
|
||||
ret = ((inline_asm_fun_0_t)self->fun)();
|
||||
} else if (n_args == 1) {
|
||||
|
||||
18
py/objfun.h
18
py/objfun.h
@@ -26,15 +26,15 @@
|
||||
|
||||
typedef struct _mp_obj_fun_bc_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_dict_t *globals; // the context within which this function was defined
|
||||
machine_uint_t n_pos_args : 16; // number of arguments this function takes
|
||||
machine_uint_t n_kwonly_args : 16; // number of arguments this function takes
|
||||
machine_uint_t n_def_args : 16; // number of default arguments
|
||||
machine_uint_t has_def_kw_args : 1; // set if this function has default keyword args
|
||||
machine_uint_t takes_var_args : 1; // set if this function takes variable args
|
||||
machine_uint_t takes_kw_args : 1; // set if this function takes keyword args
|
||||
const byte *bytecode; // bytecode for the function
|
||||
qstr *args; // argument names (needed to resolve positional args passed as keywords)
|
||||
mp_obj_dict_t *globals; // the context within which this function was defined
|
||||
mp_uint_t n_pos_args : 16; // number of arguments this function takes
|
||||
mp_uint_t n_kwonly_args : 16; // number of arguments this function takes
|
||||
mp_uint_t n_def_args : 16; // number of default arguments
|
||||
mp_uint_t has_def_kw_args : 1; // set if this function has default keyword args
|
||||
mp_uint_t takes_var_args : 1; // set if this function takes variable args
|
||||
mp_uint_t takes_kw_args : 1; // set if this function takes keyword args
|
||||
const byte *bytecode; // bytecode for the function
|
||||
qstr *args; // argument names (needed to resolve positional args passed as keywords)
|
||||
// the following extra_args array is allocated space to take (in order):
|
||||
// - values of positional default args (if any)
|
||||
// - a single slot for default kw args dict (if it has them)
|
||||
|
||||
@@ -59,12 +59,12 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp
|
||||
|
||||
const byte *bytecode = self_fun->bytecode;
|
||||
// get code info size, and skip the line number table
|
||||
machine_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24);
|
||||
mp_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24);
|
||||
bytecode += code_info_size;
|
||||
|
||||
// bytecode prelude: get state size and exception stack size
|
||||
machine_uint_t n_state = bytecode[0] | (bytecode[1] << 8);
|
||||
machine_uint_t n_exc_stack = bytecode[2] | (bytecode[3] << 8);
|
||||
mp_uint_t n_state = bytecode[0] | (bytecode[1] << 8);
|
||||
mp_uint_t n_exc_stack = bytecode[2] | (bytecode[3] << 8);
|
||||
bytecode += 4;
|
||||
|
||||
// allocate the generator object, with room for local stack and exception stack
|
||||
|
||||
22
py/objint.c
22
py/objint.c
@@ -64,7 +64,7 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, co
|
||||
return mp_parse_num_integer(s, l, 0);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) {
|
||||
return MP_OBJ_NEW_SMALL_INT((machine_int_t)(MICROPY_FLOAT_C_FUN(trunc)(mp_obj_float_get(args[0]))));
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)(MICROPY_FLOAT_C_FUN(trunc)(mp_obj_float_get(args[0]))));
|
||||
#endif
|
||||
} else {
|
||||
// try to convert to small int (eg from bool)
|
||||
@@ -85,7 +85,7 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, co
|
||||
void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
// The size of this buffer is rather arbitrary. If it's not large
|
||||
// enough, a dynamic one will be allocated.
|
||||
char stack_buf[sizeof(machine_int_t) * 4];
|
||||
char stack_buf[sizeof(mp_int_t) * 4];
|
||||
char *buf = stack_buf;
|
||||
int buf_size = sizeof(stack_buf);
|
||||
int fmt_size;
|
||||
@@ -101,7 +101,7 @@ void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env,
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
|
||||
typedef mp_longint_impl_t fmt_int_t;
|
||||
#else
|
||||
typedef mp_small_int_t fmt_int_t;
|
||||
typedef mp_int_t fmt_int_t;
|
||||
#endif
|
||||
|
||||
STATIC const uint log_base2_floor[] = {
|
||||
@@ -145,7 +145,7 @@ char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_const_ob
|
||||
// Not a small int.
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
|
||||
const mp_obj_int_t *self = self_in;
|
||||
// Get the value to format; mp_obj_get_int truncates to machine_int_t.
|
||||
// Get the value to format; mp_obj_get_int truncates to mp_int_t.
|
||||
num = self->val;
|
||||
#else
|
||||
// Delegate to the implementation for the long int.
|
||||
@@ -241,7 +241,7 @@ mp_obj_t mp_obj_new_int_from_ll(long long val) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
|
||||
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
||||
// SMALL_INT accepts only signed numbers, of one bit less size
|
||||
// then word size, which totals 2 bits less for unsigned numbers.
|
||||
if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
|
||||
@@ -251,7 +251,7 @@ mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_int(machine_int_t value) {
|
||||
mp_obj_t mp_obj_new_int(mp_int_t value) {
|
||||
if (MP_SMALL_INT_FITS(value)) {
|
||||
return MP_OBJ_NEW_SMALL_INT(value);
|
||||
}
|
||||
@@ -259,11 +259,11 @@ mp_obj_t mp_obj_new_int(machine_int_t value) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
|
||||
mp_int_t mp_obj_int_get(mp_const_obj_t self_in) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(self_in);
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
|
||||
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(self_in);
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ STATIC mp_obj_t int_from_bytes(uint n_args, const mp_obj_t *args) {
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
// convert the bytes to an integer
|
||||
machine_uint_t value = 0;
|
||||
mp_uint_t value = 0;
|
||||
for (const byte* buf = (const byte*)bufinfo.buf + bufinfo.len - 1; buf >= (byte*)bufinfo.buf; buf--) {
|
||||
value = (value << 8) | *buf;
|
||||
}
|
||||
@@ -316,7 +316,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 2, 3, int_fro
|
||||
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, (const mp_obj_t)&int_from_bytes_fun_obj);
|
||||
|
||||
STATIC mp_obj_t int_to_bytes(uint n_args, const mp_obj_t *args) {
|
||||
machine_int_t val = mp_obj_int_get_checked(args[0]);
|
||||
mp_int_t val = mp_obj_int_get_checked(args[0]);
|
||||
|
||||
uint len = MP_OBJ_SMALL_INT_VALUE(args[1]);
|
||||
byte *data;
|
||||
@@ -326,7 +326,7 @@ STATIC mp_obj_t int_to_bytes(uint n_args, const mp_obj_t *args) {
|
||||
// TODO: Support signed param
|
||||
mp_obj_t o = mp_obj_str_builder_start(&mp_type_bytes, len, &data);
|
||||
memset(data, 0, len);
|
||||
memcpy(data, &val, len < sizeof(machine_int_t) ? len : sizeof(machine_int_t));
|
||||
memcpy(data, &val, len < sizeof(mp_int_t) ? len : sizeof(mp_int_t));
|
||||
return mp_obj_str_builder_end(o);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,11 @@
|
||||
#define SUFFIX ""
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_SYS_MAXSIZE
|
||||
// Export value for sys.maxsize
|
||||
const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, INT_MAX};
|
||||
#endif
|
||||
|
||||
bool mp_obj_int_is_positive(mp_obj_t self_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(self_in)) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(self_in) >= 0;
|
||||
@@ -140,14 +145,14 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_int(machine_int_t value) {
|
||||
mp_obj_t mp_obj_new_int(mp_int_t value) {
|
||||
if (MP_SMALL_INT_FITS(value)) {
|
||||
return MP_OBJ_NEW_SMALL_INT(value);
|
||||
}
|
||||
return mp_obj_new_int_from_ll(value);
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
|
||||
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
||||
// SMALL_INT accepts only signed numbers, of one bit less size
|
||||
// than word size, which totals 2 bits less for unsigned numbers.
|
||||
if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
|
||||
@@ -174,7 +179,7 @@ mp_obj_t mp_obj_new_int_from_str_len(const char **str, uint len, bool neg, uint
|
||||
return o;
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
|
||||
mp_int_t mp_obj_int_get(mp_const_obj_t self_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(self_in)) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(self_in);
|
||||
} else {
|
||||
@@ -183,7 +188,7 @@ machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
|
||||
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
|
||||
// TODO: Check overflow
|
||||
return mp_obj_int_get(self_in);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,26 @@
|
||||
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
|
||||
|
||||
#if MICROPY_PY_SYS_MAXSIZE
|
||||
// Export value for sys.maxsize
|
||||
#define DIG_MASK ((1 << MPZ_DIG_SIZE) - 1)
|
||||
STATIC const mpz_dig_t maxsize_dig[MPZ_NUM_DIG_FOR_INT] = {
|
||||
(INT_MAX >> MPZ_DIG_SIZE * 0) & DIG_MASK,
|
||||
(INT_MAX >> MPZ_DIG_SIZE * 1) & DIG_MASK,
|
||||
(INT_MAX >> MPZ_DIG_SIZE * 2) & DIG_MASK,
|
||||
#if (INT_MAX >> MPZ_DIG_SIZE * 2) > DIG_MASK
|
||||
(INT_MAX >> MPZ_DIG_SIZE * 3) & DIG_MASK,
|
||||
(INT_MAX >> MPZ_DIG_SIZE * 4) & DIG_MASK,
|
||||
// (INT_MAX >> MPZ_DIG_SIZE * 5) & DIG_MASK,
|
||||
#endif
|
||||
};
|
||||
const mp_obj_int_t mp_maxsize_obj = {
|
||||
{&mp_type_int},
|
||||
{.fixed_dig = 1, .len = MPZ_NUM_DIG_FOR_INT, .alloc = MPZ_NUM_DIG_FOR_INT, .dig = (mpz_dig_t*)maxsize_dig}
|
||||
};
|
||||
#undef DIG_MASK
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) {
|
||||
mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
|
||||
o->base.type = &mp_type_int;
|
||||
@@ -121,8 +141,10 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_float)) {
|
||||
return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
} else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_complex)) {
|
||||
return mp_obj_complex_binary_op(op, mpz_as_float(zlhs), 0, rhs_in);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
// delegate to generic function to check for extra cases
|
||||
@@ -196,7 +218,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
case MP_BINARY_OP_RSHIFT:
|
||||
case MP_BINARY_OP_INPLACE_RSHIFT: {
|
||||
// TODO check conversion overflow
|
||||
machine_int_t irhs = mpz_as_int(zrhs);
|
||||
mp_int_t irhs = mpz_as_int(zrhs);
|
||||
if (irhs < 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
|
||||
}
|
||||
@@ -239,7 +261,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_int(machine_int_t value) {
|
||||
mp_obj_t mp_obj_new_int(mp_int_t value) {
|
||||
if (MP_SMALL_INT_FITS(value)) {
|
||||
return MP_OBJ_NEW_SMALL_INT(value);
|
||||
}
|
||||
@@ -252,7 +274,7 @@ mp_obj_t mp_obj_new_int_from_ll(long long val) {
|
||||
return o;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
|
||||
mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
||||
// SMALL_INT accepts only signed numbers, of one bit less size
|
||||
// than word size, which totals 2 bits less for unsigned numbers.
|
||||
if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
|
||||
@@ -268,7 +290,7 @@ mp_obj_t mp_obj_new_int_from_str_len(const char **str, uint len, bool neg, uint
|
||||
return o;
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
|
||||
mp_int_t mp_obj_int_get(mp_const_obj_t self_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(self_in)) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(self_in);
|
||||
} else {
|
||||
@@ -277,12 +299,12 @@ machine_int_t mp_obj_int_get(mp_const_obj_t self_in) {
|
||||
}
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
|
||||
mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(self_in)) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(self_in);
|
||||
} else {
|
||||
const mp_obj_int_t *self = self_in;
|
||||
machine_int_t value;
|
||||
mp_int_t value;
|
||||
if (mpz_as_int_checked(&self->mpz, &value)) {
|
||||
return value;
|
||||
} else {
|
||||
|
||||
@@ -127,7 +127,7 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
return o;
|
||||
}
|
||||
case MP_BINARY_OP_MULTIPLY: {
|
||||
machine_int_t n;
|
||||
mp_int_t n;
|
||||
if (!mp_obj_get_int_maybe(rhs, &n)) {
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
@@ -488,7 +488,7 @@ void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
typedef struct _mp_obj_list_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_list_t *list;
|
||||
machine_uint_t cur;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_list_it_t;
|
||||
|
||||
mp_obj_t list_it_iternext(mp_obj_t self_in) {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
typedef struct _mp_obj_list_t {
|
||||
mp_obj_base_t base;
|
||||
machine_uint_t alloc;
|
||||
machine_uint_t len;
|
||||
mp_uint_t alloc;
|
||||
mp_uint_t len;
|
||||
mp_obj_t *items;
|
||||
} mp_obj_list_t;
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
typedef struct _mp_obj_map_t {
|
||||
mp_obj_base_t base;
|
||||
machine_uint_t n_iters;
|
||||
mp_uint_t n_iters;
|
||||
mp_obj_t fun;
|
||||
mp_obj_t iters[];
|
||||
} mp_obj_map_t;
|
||||
|
||||
@@ -39,9 +39,9 @@
|
||||
typedef struct _mp_obj_range_it_t {
|
||||
mp_obj_base_t base;
|
||||
// TODO make these values generic objects or something
|
||||
machine_int_t cur;
|
||||
machine_int_t stop;
|
||||
machine_int_t step;
|
||||
mp_int_t cur;
|
||||
mp_int_t stop;
|
||||
mp_int_t step;
|
||||
} mp_obj_range_it_t;
|
||||
|
||||
STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {
|
||||
@@ -77,9 +77,9 @@ mp_obj_t mp_obj_new_range_iterator(int cur, int stop, int step) {
|
||||
typedef struct _mp_obj_range_t {
|
||||
mp_obj_base_t base;
|
||||
// TODO make these values generic objects or something
|
||||
machine_int_t start;
|
||||
machine_int_t stop;
|
||||
machine_int_t step;
|
||||
mp_int_t start;
|
||||
mp_int_t stop;
|
||||
mp_int_t step;
|
||||
} mp_obj_range_t;
|
||||
|
||||
STATIC mp_obj_t range_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||
|
||||
@@ -47,7 +47,7 @@ typedef struct _mp_obj_set_t {
|
||||
typedef struct _mp_obj_set_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_set_t *set;
|
||||
machine_uint_t cur;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_set_it_t;
|
||||
|
||||
STATIC mp_obj_t set_it_iternext(mp_obj_t self_in);
|
||||
@@ -160,10 +160,10 @@ const mp_obj_type_t mp_type_set_it = {
|
||||
STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set_it));
|
||||
mp_obj_set_it_t *self = self_in;
|
||||
machine_uint_t max = self->set->set.alloc;
|
||||
mp_uint_t max = self->set->set.alloc;
|
||||
mp_set_t *set = &self->set->set;
|
||||
|
||||
for (machine_uint_t i = self->cur; i < max; i++) {
|
||||
for (mp_uint_t i = self->cur; i < max; i++) {
|
||||
if (MP_SET_SLOT_IS_FILLED(set, i)) {
|
||||
self->cur = i + 1;
|
||||
return set->table[i];
|
||||
@@ -476,7 +476,7 @@ STATIC mp_obj_t set_unary_op(int op, mp_obj_t self_in) {
|
||||
mp_obj_set_t *self = self_in;
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL: return MP_BOOL(self->set.used != 0);
|
||||
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->set.used);
|
||||
case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((mp_int_t)self->set.used);
|
||||
default: return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
217
py/objstr.c
217
py/objstr.c
@@ -32,6 +32,7 @@
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
#include "unicode.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime0.h"
|
||||
@@ -43,16 +44,7 @@
|
||||
STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t *args, mp_obj_t dict);
|
||||
const mp_obj_t mp_const_empty_bytes;
|
||||
|
||||
// use this macro to extract the string hash
|
||||
#define GET_STR_HASH(str_obj_in, str_hash) uint 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*)str_obj_in)->hash; }
|
||||
|
||||
// use this macro to extract the string length
|
||||
#define GET_STR_LEN(str_obj_in, str_len) uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; }
|
||||
|
||||
// use this macro to extract the string data and length
|
||||
#define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) const byte *str_data; uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
|
||||
mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
|
||||
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str);
|
||||
STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
|
||||
STATIC NORETURN void arg_type_mixup();
|
||||
@@ -64,7 +56,8 @@ STATIC bool is_str_or_bytes(mp_obj_t o) {
|
||||
/******************************************************************************/
|
||||
/* str */
|
||||
|
||||
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
|
||||
void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env,
|
||||
const byte *str_data, uint str_len, bool is_bytes) {
|
||||
// this escapes characters, but it will be very slow to print (calling print many times)
|
||||
bool has_single_quote = false;
|
||||
bool has_double_quote = false;
|
||||
@@ -85,7 +78,10 @@ void mp_str_print_quoted(void (*print)(void *env, const char *fmt, ...), void *e
|
||||
print(env, "\\%c", quote_char);
|
||||
} else if (*s == '\\') {
|
||||
print(env, "\\\\");
|
||||
} else if (32 <= *s && *s <= 126) {
|
||||
} else if (*s >= 0x20 && *s != 0x7f && (!is_bytes || *s < 0x80)) {
|
||||
// In strings, anything which is not ascii control character
|
||||
// is printed as is, this includes characters in range 0x80-0xff
|
||||
// (which can be non-Latin letters, etc.)
|
||||
print(env, "%c", *s);
|
||||
} else if (*s == '\n') {
|
||||
print(env, "\\n");
|
||||
@@ -109,7 +105,7 @@ STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env,
|
||||
if (is_bytes) {
|
||||
print(env, "b");
|
||||
}
|
||||
mp_str_print_quoted(print, env, str_data, str_len);
|
||||
mp_str_print_quoted(print, env, str_data, str_len, is_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,9 +226,9 @@ wrong_args:
|
||||
|
||||
// like strstr but with specified length and allows \0 bytes
|
||||
// TODO replace with something more efficient/standard
|
||||
STATIC const byte *find_subbytes(const byte *haystack, machine_uint_t hlen, const byte *needle, machine_uint_t nlen, machine_int_t direction) {
|
||||
STATIC const byte *find_subbytes(const byte *haystack, mp_uint_t hlen, const byte *needle, mp_uint_t nlen, mp_int_t direction) {
|
||||
if (hlen >= nlen) {
|
||||
machine_uint_t str_index, str_index_end;
|
||||
mp_uint_t str_index, str_index_end;
|
||||
if (direction > 0) {
|
||||
str_index = 0;
|
||||
str_index_end = hlen - nlen;
|
||||
@@ -255,7 +251,7 @@ STATIC const byte *find_subbytes(const byte *haystack, machine_uint_t hlen, cons
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
mp_obj_t mp_obj_str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
GET_STR_DATA_LEN(lhs_in, lhs_data, lhs_len);
|
||||
mp_obj_type_t *lhs_type = mp_obj_get_type(lhs_in);
|
||||
mp_obj_type_t *rhs_type = mp_obj_get_type(rhs_in);
|
||||
@@ -348,6 +344,15 @@ uncomparable:
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
|
||||
#if !MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
// objstrunicode defines own version
|
||||
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
|
||||
mp_obj_t index, bool is_slice) {
|
||||
mp_uint_t index_val = mp_get_index(type, self_len, index, is_slice);
|
||||
return self_data + index_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
mp_obj_type_t *type = mp_obj_get_type(self_in);
|
||||
GET_STR_DATA_LEN(self_in, self_data, self_len);
|
||||
@@ -363,11 +368,11 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
return mp_obj_new_str_of_type(type, self_data + slice.start, slice.stop - slice.start);
|
||||
}
|
||||
#endif
|
||||
uint index_val = mp_get_index(type, self_len, index, false);
|
||||
const byte *p = str_index_to_ptr(type, self_data, self_len, index, false);
|
||||
if (type == &mp_type_bytes) {
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self_data[index_val]);
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)*p);
|
||||
} else {
|
||||
return mp_obj_new_str((char*)self_data + index_val, 1, true);
|
||||
return mp_obj_new_str((char*)p, 1, true);
|
||||
}
|
||||
} else {
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
@@ -430,7 +435,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
|
||||
|
||||
STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) {
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
|
||||
machine_int_t splits = -1;
|
||||
mp_int_t splits = -1;
|
||||
mp_obj_t sep = mp_const_none;
|
||||
if (n_args > 1) {
|
||||
sep = args[1];
|
||||
@@ -510,8 +515,8 @@ STATIC mp_obj_t str_rsplit(uint n_args, const mp_obj_t *args) {
|
||||
mp_obj_t sep = args[1];
|
||||
GET_STR_DATA_LEN(args[0], s, len);
|
||||
|
||||
machine_int_t splits = mp_obj_get_int(args[2]);
|
||||
machine_int_t org_splits = splits;
|
||||
mp_int_t splits = mp_obj_get_int(args[2]);
|
||||
mp_int_t org_splits = splits;
|
||||
// Preallocate list to the max expected # of elements, as we
|
||||
// will fill it from the end.
|
||||
mp_obj_list_t *res = mp_obj_new_list(splits + 1, NULL);
|
||||
@@ -561,8 +566,8 @@ STATIC mp_obj_t str_rsplit(uint n_args, const mp_obj_t *args) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t direction, bool is_index) {
|
||||
STATIC mp_obj_t str_finder(uint 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(args[0]));
|
||||
assert(MP_OBJ_IS_STR(args[1]));
|
||||
@@ -570,16 +575,16 @@ STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t dire
|
||||
GET_STR_DATA_LEN(args[0], haystack, haystack_len);
|
||||
GET_STR_DATA_LEN(args[1], needle, needle_len);
|
||||
|
||||
machine_uint_t start = 0;
|
||||
machine_uint_t end = haystack_len;
|
||||
const byte *start = haystack;
|
||||
const byte *end = haystack + haystack_len;
|
||||
if (n_args >= 3 && args[2] != mp_const_none) {
|
||||
start = mp_get_index(&mp_type_str, haystack_len, args[2], true);
|
||||
start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true);
|
||||
}
|
||||
if (n_args >= 4 && args[3] != mp_const_none) {
|
||||
end = mp_get_index(&mp_type_str, haystack_len, args[3], true);
|
||||
end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);
|
||||
}
|
||||
|
||||
const byte *p = find_subbytes(haystack + start, end - start, needle, needle_len, direction);
|
||||
const byte *p = find_subbytes(start, end - start, needle, needle_len, direction);
|
||||
if (p == NULL) {
|
||||
// not found
|
||||
if (is_index) {
|
||||
@@ -589,6 +594,11 @@ STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t dire
|
||||
}
|
||||
} else {
|
||||
// found
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
if (self_type == &mp_type_str) {
|
||||
return MP_OBJ_NEW_SMALL_INT(utf8_ptr_to_index(haystack, p));
|
||||
}
|
||||
#endif
|
||||
return MP_OBJ_NEW_SMALL_INT(p - haystack);
|
||||
}
|
||||
}
|
||||
@@ -611,16 +621,17 @@ STATIC mp_obj_t str_rindex(uint n_args, const mp_obj_t *args) {
|
||||
|
||||
// TODO: (Much) more variety in args
|
||||
STATIC mp_obj_t str_startswith(uint n_args, const mp_obj_t *args) {
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
|
||||
GET_STR_DATA_LEN(args[0], str, str_len);
|
||||
GET_STR_DATA_LEN(args[1], prefix, prefix_len);
|
||||
uint index_val = 0;
|
||||
const byte *start = str;
|
||||
if (n_args > 2) {
|
||||
index_val = mp_get_index(&mp_type_str, str_len, args[2], true);
|
||||
start = str_index_to_ptr(self_type, str, str_len, args[2], true);
|
||||
}
|
||||
if (prefix_len + index_val > str_len) {
|
||||
if (prefix_len + (start - str) > str_len) {
|
||||
return mp_const_false;
|
||||
}
|
||||
return MP_BOOL(memcmp(str + index_val, prefix, prefix_len) == 0);
|
||||
return MP_BOOL(memcmp(start, prefix, prefix_len) == 0);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t str_endswith(uint n_args, const mp_obj_t *args) {
|
||||
@@ -659,16 +670,16 @@ STATIC mp_obj_t str_uni_strip(int type, uint n_args, const mp_obj_t *args) {
|
||||
|
||||
GET_STR_DATA_LEN(args[0], orig_str, orig_str_len);
|
||||
|
||||
machine_uint_t first_good_char_pos = 0;
|
||||
mp_uint_t first_good_char_pos = 0;
|
||||
bool first_good_char_pos_set = false;
|
||||
machine_uint_t last_good_char_pos = 0;
|
||||
machine_uint_t i = 0;
|
||||
machine_int_t delta = 1;
|
||||
mp_uint_t last_good_char_pos = 0;
|
||||
mp_uint_t i = 0;
|
||||
mp_int_t delta = 1;
|
||||
if (type == RSTRIP) {
|
||||
i = orig_str_len - 1;
|
||||
delta = -1;
|
||||
}
|
||||
for (machine_uint_t len = orig_str_len; len > 0; len--) {
|
||||
for (mp_uint_t len = orig_str_len; len > 0; len--) {
|
||||
if (find_subbytes(chars_to_del, chars_to_del_len, &orig_str[i], 1, 1) == NULL) {
|
||||
if (!first_good_char_pos_set) {
|
||||
first_good_char_pos_set = true;
|
||||
@@ -694,7 +705,7 @@ STATIC mp_obj_t str_uni_strip(int type, uint n_args, const mp_obj_t *args) {
|
||||
|
||||
assert(last_good_char_pos >= first_good_char_pos);
|
||||
//+1 to accomodate the last character
|
||||
machine_uint_t stripped_len = last_good_char_pos - first_good_char_pos + 1;
|
||||
mp_uint_t stripped_len = last_good_char_pos - first_good_char_pos + 1;
|
||||
if (stripped_len == orig_str_len) {
|
||||
// If nothing was stripped, don't bother to dup original string
|
||||
// TODO: watch out for this case when we'll get to bytearray.strip()
|
||||
@@ -757,7 +768,7 @@ static mp_obj_t arg_as_int(mp_obj_t arg) {
|
||||
|
||||
// TODO: Needs a way to construct an mpz integer from a float
|
||||
|
||||
mp_small_int_t num = mp_obj_get_float(arg);
|
||||
mp_int_t num = mp_obj_get_float(arg);
|
||||
return MP_OBJ_NEW_SMALL_INT(num);
|
||||
}
|
||||
#endif
|
||||
@@ -1318,7 +1329,7 @@ not_enough_args:
|
||||
STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
|
||||
assert(MP_OBJ_IS_STR(args[0]));
|
||||
|
||||
machine_int_t max_rep = -1;
|
||||
mp_int_t max_rep = -1;
|
||||
if (n_args == 4) {
|
||||
max_rep = mp_obj_get_int(args[3]);
|
||||
if (max_rep == 0) {
|
||||
@@ -1359,11 +1370,11 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
|
||||
// first pass computes the required length of the replaced string
|
||||
// second pass does the replacements
|
||||
for (;;) {
|
||||
machine_uint_t replaced_str_index = 0;
|
||||
machine_uint_t num_replacements_done = 0;
|
||||
mp_uint_t replaced_str_index = 0;
|
||||
mp_uint_t num_replacements_done = 0;
|
||||
const byte *old_occurrence;
|
||||
const byte *offset_ptr = str;
|
||||
machine_uint_t str_len_remain = str_len;
|
||||
mp_uint_t str_len_remain = str_len;
|
||||
if (old_len == 0) {
|
||||
// if old_str is empty, copy new_str to start of replaced string
|
||||
// copy the replacement string
|
||||
@@ -1418,6 +1429,7 @@ STATIC mp_obj_t str_replace(uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
|
||||
STATIC mp_obj_t str_count(uint 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(args[0]));
|
||||
assert(MP_OBJ_IS_STR(args[1]));
|
||||
@@ -1425,33 +1437,35 @@ STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) {
|
||||
GET_STR_DATA_LEN(args[0], haystack, haystack_len);
|
||||
GET_STR_DATA_LEN(args[1], needle, needle_len);
|
||||
|
||||
machine_uint_t start = 0;
|
||||
machine_uint_t end = haystack_len;
|
||||
const byte *start = haystack;
|
||||
const byte *end = haystack + haystack_len;
|
||||
if (n_args >= 3 && args[2] != mp_const_none) {
|
||||
start = mp_get_index(&mp_type_str, haystack_len, args[2], true);
|
||||
start = str_index_to_ptr(self_type, haystack, haystack_len, args[2], true);
|
||||
}
|
||||
if (n_args >= 4 && args[3] != mp_const_none) {
|
||||
end = mp_get_index(&mp_type_str, haystack_len, args[3], true);
|
||||
end = str_index_to_ptr(self_type, haystack, haystack_len, args[3], true);
|
||||
}
|
||||
|
||||
// if needle_len is zero then we count each gap between characters as an occurrence
|
||||
if (needle_len == 0) {
|
||||
return MP_OBJ_NEW_SMALL_INT(end - start + 1);
|
||||
return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char*)start, end - start) + 1);
|
||||
}
|
||||
|
||||
// count the occurrences
|
||||
machine_int_t num_occurrences = 0;
|
||||
for (machine_uint_t haystack_index = start; haystack_index + needle_len <= end; haystack_index++) {
|
||||
if (memcmp(&haystack[haystack_index], needle, needle_len) == 0) {
|
||||
mp_int_t num_occurrences = 0;
|
||||
for (const byte *haystack_ptr = start; haystack_ptr + needle_len <= end;) {
|
||||
if (memcmp(haystack_ptr, needle, needle_len) == 0) {
|
||||
num_occurrences++;
|
||||
haystack_index += needle_len - 1;
|
||||
haystack_ptr += needle_len;
|
||||
} else {
|
||||
haystack_ptr = utf8_next_char(haystack_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
return MP_OBJ_NEW_SMALL_INT(num_occurrences);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t direction) {
|
||||
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, mp_int_t direction) {
|
||||
if (!is_str_or_bytes(self_in)) {
|
||||
assert(0);
|
||||
}
|
||||
@@ -1477,7 +1491,7 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t di
|
||||
|
||||
const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction);
|
||||
if (position_ptr != NULL) {
|
||||
machine_uint_t position = position_ptr - str;
|
||||
mp_uint_t position = position_ptr - str;
|
||||
result[0] = mp_obj_new_str_of_type(self_type, str, position);
|
||||
result[1] = arg;
|
||||
result[2] = mp_obj_new_str_of_type(self_type, str + position + sep_len, str_len - position - sep_len);
|
||||
@@ -1595,7 +1609,7 @@ STATIC mp_obj_t str_encode(uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC machine_int_t str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags) {
|
||||
mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags) {
|
||||
if (flags == MP_BUFFER_READ) {
|
||||
GET_STR_DATA_LEN(self_in, str_data, str_len);
|
||||
bufinfo->buf = (void*)str_data;
|
||||
@@ -1612,38 +1626,45 @@ STATIC machine_int_t str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
|
||||
}
|
||||
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj, 1, 3, str_encode);
|
||||
#endif
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, mp_obj_str_format);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, mp_obj_str_format);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower);
|
||||
|
||||
STATIC const mp_map_elem_t str_locals_dict_table[] = {
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_decode), (mp_obj_t)&bytes_decode_obj },
|
||||
#if !MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
// If we have separate unicode type, then here we have methods only
|
||||
// for bytes type, and it should not have encode() methods. Otherwise,
|
||||
// we have non-compliant-but-practical bytestring type, which shares
|
||||
// method table with bytes, so they both have encode() and decode()
|
||||
// methods (which should do type checking at runtime).
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_encode), (mp_obj_t)&str_encode_obj },
|
||||
#endif
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj },
|
||||
@@ -1673,17 +1694,19 @@ STATIC const mp_map_elem_t str_locals_dict_table[] = {
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(str_locals_dict, str_locals_dict_table);
|
||||
|
||||
#if !MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
const mp_obj_type_t mp_type_str = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_str,
|
||||
.print = str_print,
|
||||
.make_new = str_make_new,
|
||||
.binary_op = str_binary_op,
|
||||
.binary_op = mp_obj_str_binary_op,
|
||||
.subscr = str_subscr,
|
||||
.getiter = mp_obj_new_str_iterator,
|
||||
.buffer_p = { .get_buffer = str_get_buffer },
|
||||
.buffer_p = { .get_buffer = mp_obj_str_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&str_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
// Reuses most of methods from str
|
||||
const mp_obj_type_t mp_type_bytes = {
|
||||
@@ -1691,10 +1714,10 @@ const mp_obj_type_t mp_type_bytes = {
|
||||
.name = MP_QSTR_bytes,
|
||||
.print = str_print,
|
||||
.make_new = bytes_make_new,
|
||||
.binary_op = str_binary_op,
|
||||
.binary_op = mp_obj_str_binary_op,
|
||||
.subscr = str_subscr,
|
||||
.getiter = mp_obj_new_bytes_iterator,
|
||||
.buffer_p = { .get_buffer = str_get_buffer },
|
||||
.buffer_p = { .get_buffer = mp_obj_str_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&str_locals_dict,
|
||||
};
|
||||
|
||||
@@ -1848,9 +1871,10 @@ const char *mp_obj_str_get_data(mp_obj_t self_in, uint *len) {
|
||||
typedef struct _mp_obj_str_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t str;
|
||||
machine_uint_t cur;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_str_it_t;
|
||||
|
||||
#if !MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
|
||||
mp_obj_str_it_t *self = self_in;
|
||||
GET_STR_DATA_LEN(self->str, str, len);
|
||||
@@ -1870,11 +1894,20 @@ STATIC const mp_obj_type_t mp_type_str_it = {
|
||||
.iternext = str_it_iternext,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
|
||||
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
|
||||
o->base.type = &mp_type_str_it;
|
||||
o->str = str;
|
||||
o->cur = 0;
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) {
|
||||
mp_obj_str_it_t *self = self_in;
|
||||
GET_STR_DATA_LEN(self->str, str, len);
|
||||
if (self->cur < len) {
|
||||
mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT((mp_small_int_t)str[self->cur]);
|
||||
mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT((mp_int_t)str[self->cur]);
|
||||
self->cur += 1;
|
||||
return o_out;
|
||||
} else {
|
||||
@@ -1889,14 +1922,6 @@ STATIC const mp_obj_type_t mp_type_bytes_it = {
|
||||
.iternext = bytes_it_iternext,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
|
||||
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
|
||||
o->base.type = &mp_type_str_it;
|
||||
o->str = str;
|
||||
o->cur = 0;
|
||||
return o;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str) {
|
||||
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
|
||||
o->base.type = &mp_type_bytes_it;
|
||||
|
||||
52
py/objstr.h
52
py/objstr.h
@@ -27,13 +27,61 @@
|
||||
typedef struct _mp_obj_str_t {
|
||||
mp_obj_base_t base;
|
||||
// XXX here we assume the hash size is 16 bits (it is at the moment; see qstr.c)
|
||||
machine_uint_t hash : 16;
|
||||
mp_uint_t hash : 16;
|
||||
// len == number of bytes used in data, alloc = len + 1 because (at the moment) we also append a null byte
|
||||
machine_uint_t len : 16;
|
||||
mp_uint_t len : 16;
|
||||
const byte *data;
|
||||
} 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
|
||||
#define GET_STR_HASH(str_obj_in, str_hash) \
|
||||
uint 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*)str_obj_in)->hash; }
|
||||
|
||||
// use this macro to extract the string length
|
||||
#define GET_STR_LEN(str_obj_in, str_len) \
|
||||
uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \
|
||||
{ str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; }
|
||||
|
||||
// use this macro to extract the string data and length
|
||||
#define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \
|
||||
const byte *str_data; uint str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \
|
||||
{ str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \
|
||||
else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
|
||||
|
||||
mp_obj_t mp_obj_str_format(uint n_args, const mp_obj_t *args);
|
||||
mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, uint len);
|
||||
|
||||
mp_obj_t mp_obj_str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in);
|
||||
mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, int flags);
|
||||
|
||||
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
|
||||
mp_obj_t index, bool is_slice);
|
||||
|
||||
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_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_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);
|
||||
|
||||
@@ -43,7 +43,7 @@ typedef struct _mp_obj_stringio_t {
|
||||
mp_obj_base_t base;
|
||||
vstr_t *vstr;
|
||||
// StringIO has single pointer used for both reading and writing
|
||||
machine_uint_t pos;
|
||||
mp_uint_t pos;
|
||||
} mp_obj_stringio_t;
|
||||
|
||||
STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
@@ -51,9 +51,9 @@ STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void
|
||||
print(env, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self->vstr);
|
||||
}
|
||||
|
||||
STATIC machine_int_t stringio_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
|
||||
STATIC mp_int_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_stringio_t *o = o_in;
|
||||
machine_uint_t remaining = o->vstr->len - o->pos;
|
||||
mp_uint_t remaining = o->vstr->len - o->pos;
|
||||
if (size > remaining) {
|
||||
size = remaining;
|
||||
}
|
||||
@@ -62,9 +62,9 @@ STATIC machine_int_t stringio_read(mp_obj_t o_in, void *buf, machine_uint_t size
|
||||
return size;
|
||||
}
|
||||
|
||||
STATIC machine_int_t stringio_write(mp_obj_t o_in, const void *buf, machine_uint_t size, int *errcode) {
|
||||
STATIC mp_int_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_stringio_t *o = o_in;
|
||||
machine_uint_t remaining = o->vstr->alloc - o->pos;
|
||||
mp_uint_t remaining = o->vstr->alloc - o->pos;
|
||||
if (size > remaining) {
|
||||
// Take all what's already allocated...
|
||||
o->vstr->len = o->vstr->alloc;
|
||||
|
||||
359
py/objstrunicode.c
Normal file
359
py/objstrunicode.c
Normal file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "pfenv.h"
|
||||
#include "objstr.h"
|
||||
#include "objlist.h"
|
||||
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
|
||||
|
||||
/******************************************************************************/
|
||||
/* str */
|
||||
|
||||
STATIC void uni_print_quoted(void (*print)(void *env, const char *fmt, ...), void *env, const byte *str_data, uint str_len) {
|
||||
// this escapes characters, but it will be very slow to print (calling print many times)
|
||||
bool has_single_quote = false;
|
||||
bool has_double_quote = false;
|
||||
for (const byte *s = str_data, *top = str_data + str_len; !has_double_quote && s < top; s++) {
|
||||
if (*s == '\'') {
|
||||
has_single_quote = true;
|
||||
} else if (*s == '"') {
|
||||
has_double_quote = true;
|
||||
}
|
||||
}
|
||||
int quote_char = '\'';
|
||||
if (has_single_quote && !has_double_quote) {
|
||||
quote_char = '"';
|
||||
}
|
||||
print(env, "%c", quote_char);
|
||||
const byte *s = str_data, *top = str_data + str_len;
|
||||
while (s < top) {
|
||||
unichar ch;
|
||||
ch = utf8_get_char(s);
|
||||
s = utf8_next_char(s);
|
||||
if (ch == quote_char) {
|
||||
print(env, "\\%c", quote_char);
|
||||
} else if (ch == '\\') {
|
||||
print(env, "\\\\");
|
||||
} else if (32 <= ch && ch <= 126) {
|
||||
print(env, "%c", ch);
|
||||
} else if (ch == '\n') {
|
||||
print(env, "\\n");
|
||||
} else if (ch == '\r') {
|
||||
print(env, "\\r");
|
||||
} else if (ch == '\t') {
|
||||
print(env, "\\t");
|
||||
} else if (ch < 0x100) {
|
||||
print(env, "\\x%02x", ch);
|
||||
} else if (ch < 0x10000) {
|
||||
print(env, "\\u%04x", ch);
|
||||
} else {
|
||||
print(env, "\\U%08x", ch);
|
||||
}
|
||||
}
|
||||
print(env, "%c", quote_char);
|
||||
}
|
||||
|
||||
STATIC void uni_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
GET_STR_DATA_LEN(self_in, str_data, str_len);
|
||||
if (kind == PRINT_STR) {
|
||||
print(env, "%.*s", str_len, str_data);
|
||||
} else {
|
||||
uni_print_quoted(print, env, str_data, str_len);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uni_unary_op(int op, mp_obj_t self_in) {
|
||||
GET_STR_DATA_LEN(self_in, str_data, str_len);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL:
|
||||
return MP_BOOL(str_len != 0);
|
||||
case MP_UNARY_OP_LEN:
|
||||
return MP_OBJ_NEW_SMALL_INT(unichar_charlen((const char *)str_data, str_len));
|
||||
default:
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
if (n_kw != 0) {
|
||||
mp_arg_error_unimpl_kw();
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (n_args) {
|
||||
case 0:
|
||||
return MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||
|
||||
case 1:
|
||||
{
|
||||
vstr_t *vstr = vstr_new();
|
||||
mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[0], PRINT_STR);
|
||||
mp_obj_t s = mp_obj_new_str(vstr->buf, vstr->len, false);
|
||||
vstr_free(vstr);
|
||||
return s;
|
||||
}
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
// TODO: validate 2nd/3rd args
|
||||
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
|
||||
}
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
}
|
||||
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments"));
|
||||
}
|
||||
}
|
||||
|
||||
// Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or
|
||||
// be capped to the first/last character of the string, depending on is_slice.
|
||||
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, uint self_len,
|
||||
mp_obj_t index, bool is_slice) {
|
||||
mp_int_t i;
|
||||
// Copied from mp_get_index; I don't want bounds checking, just give me
|
||||
// the integer as-is. (I can't bounds-check without scanning the whole
|
||||
// string; an out-of-bounds index will be caught in the loops below.)
|
||||
if (MP_OBJ_IS_SMALL_INT(index)) {
|
||||
i = MP_OBJ_SMALL_INT_VALUE(index);
|
||||
} else if (!mp_obj_get_int_maybe(index, &i)) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "string indices must be integers, not %s", mp_obj_get_type_str(index)));
|
||||
}
|
||||
const byte *s, *top = self_data + self_len;
|
||||
if (i < 0)
|
||||
{
|
||||
// Negative indexing is performed by counting from the end of the string.
|
||||
for (s = top - 1; i; --s) {
|
||||
if (s < self_data) {
|
||||
if (is_slice) {
|
||||
return self_data;
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "string index out of range"));
|
||||
}
|
||||
if (!UTF8_IS_CONT(*s)) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
++s;
|
||||
} else if (!i) {
|
||||
return self_data; // Shortcut - str[0] is its base pointer
|
||||
} else {
|
||||
// Positive indexing, correspondingly, counts from the start of the string.
|
||||
// It's assumed that negative indexing will generally be used with small
|
||||
// absolute values (eg str[-1], not str[-1000000]), which means it'll be
|
||||
// more efficient this way.
|
||||
for (s = self_data; true; ++s) {
|
||||
if (s >= top) {
|
||||
if (is_slice) {
|
||||
return top;
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "string index out of range"));
|
||||
}
|
||||
while (UTF8_IS_CONT(*s)) {
|
||||
++s;
|
||||
}
|
||||
if (!i--) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
mp_obj_type_t *type = mp_obj_get_type(self_in);
|
||||
GET_STR_DATA_LEN(self_in, self_data, self_len);
|
||||
if (value == MP_OBJ_SENTINEL) {
|
||||
// load
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||
mp_obj_t ostart, ostop, ostep;
|
||||
mp_obj_slice_get(index, &ostart, &ostop, &ostep);
|
||||
if (ostep != mp_const_none && ostep != MP_OBJ_NEW_SMALL_INT(1)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
|
||||
"only slices with step=1 (aka None) are supported"));
|
||||
}
|
||||
|
||||
if (type == &mp_type_bytes) {
|
||||
mp_int_t start = 0, stop = self_len;
|
||||
if (ostart != mp_const_none) {
|
||||
start = MP_OBJ_SMALL_INT_VALUE(ostart);
|
||||
if (start < 0) {
|
||||
start = self_len + start;
|
||||
}
|
||||
}
|
||||
if (ostop != mp_const_none) {
|
||||
stop = MP_OBJ_SMALL_INT_VALUE(ostop);
|
||||
if (stop < 0) {
|
||||
stop = self_len + stop;
|
||||
}
|
||||
}
|
||||
return mp_obj_new_str_of_type(type, self_data + start, stop - start);
|
||||
}
|
||||
const byte *pstart, *pstop;
|
||||
if (ostart != mp_const_none) {
|
||||
pstart = str_index_to_ptr(type, self_data, self_len, ostart, true);
|
||||
} else {
|
||||
pstart = self_data;
|
||||
}
|
||||
if (ostop != mp_const_none) {
|
||||
// pstop will point just after the stop character. This depends on
|
||||
// the \0 at the end of the string.
|
||||
pstop = str_index_to_ptr(type, self_data, self_len, ostop, true);
|
||||
} else {
|
||||
pstop = self_data + self_len;
|
||||
}
|
||||
if (pstop < pstart) {
|
||||
return MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||
}
|
||||
return mp_obj_new_str_of_type(type, (const byte *)pstart, pstop - pstart);
|
||||
}
|
||||
#endif
|
||||
if (type == &mp_type_bytes) {
|
||||
uint index_val = mp_get_index(type, self_len, index, false);
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)self_data[index_val]);
|
||||
}
|
||||
const byte *s = str_index_to_ptr(type, self_data, self_len, index, false);
|
||||
int len = 1;
|
||||
if (UTF8_IS_NONASCII(*s)) {
|
||||
// Count the number of 1 bits (after the first)
|
||||
for (char mask = 0x40; *s & mask; mask >>= 1) {
|
||||
++len;
|
||||
}
|
||||
}
|
||||
return mp_obj_new_str((const char*)s, len, true); // This will create a one-character string
|
||||
} else {
|
||||
return MP_OBJ_NULL; // op not supported
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const mp_map_elem_t str_locals_dict_table[] = {
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_encode), (mp_obj_t)&str_encode_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&str_index_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rindex), (mp_obj_t)&str_rindex_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_join), (mp_obj_t)&str_join_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_split), (mp_obj_t)&str_split_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rsplit), (mp_obj_t)&str_rsplit_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_startswith), (mp_obj_t)&str_startswith_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_endswith), (mp_obj_t)&str_endswith_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_strip), (mp_obj_t)&str_strip_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_lstrip), (mp_obj_t)&str_lstrip_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rstrip), (mp_obj_t)&str_rstrip_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_format), (mp_obj_t)&str_format_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_replace), (mp_obj_t)&str_replace_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_count), (mp_obj_t)&str_count_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_partition), (mp_obj_t)&str_partition_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rpartition), (mp_obj_t)&str_rpartition_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_lower), (mp_obj_t)&str_lower_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_upper), (mp_obj_t)&str_upper_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isspace), (mp_obj_t)&str_isspace_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isalpha), (mp_obj_t)&str_isalpha_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isdigit), (mp_obj_t)&str_isdigit_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isupper), (mp_obj_t)&str_isupper_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_islower), (mp_obj_t)&str_islower_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(str_locals_dict, str_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t mp_type_str = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_str,
|
||||
.print = uni_print,
|
||||
.make_new = str_make_new,
|
||||
.unary_op = uni_unary_op,
|
||||
.binary_op = mp_obj_str_binary_op,
|
||||
.subscr = str_subscr,
|
||||
.getiter = mp_obj_new_str_iterator,
|
||||
.buffer_p = { .get_buffer = mp_obj_str_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&str_locals_dict,
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/* str iterator */
|
||||
|
||||
typedef struct _mp_obj_str_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t str;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_str_it_t;
|
||||
|
||||
STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
|
||||
mp_obj_str_it_t *self = self_in;
|
||||
GET_STR_DATA_LEN(self->str, str, len);
|
||||
if (self->cur < len) {
|
||||
const byte *cur = str + self->cur;
|
||||
const byte *end = utf8_next_char(str + self->cur);
|
||||
mp_obj_t o_out = mp_obj_new_str((const char*)cur, end - cur, true);
|
||||
self->cur += end - cur;
|
||||
return o_out;
|
||||
} else {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const mp_obj_type_t mp_type_str_it = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_iterator,
|
||||
.getiter = mp_identity,
|
||||
.iternext = str_it_iternext,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
|
||||
mp_obj_str_it_t *o = m_new_obj(mp_obj_str_it_t);
|
||||
o->base.type = &mp_type_str_it;
|
||||
o->str = str;
|
||||
o->cur = 0;
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
@@ -252,11 +252,11 @@ void mp_obj_tuple_del(mp_obj_t self_in) {
|
||||
m_del_var(mp_obj_tuple_t, mp_obj_t, self->len, self);
|
||||
}
|
||||
|
||||
machine_int_t mp_obj_tuple_hash(mp_obj_t self_in) {
|
||||
mp_int_t mp_obj_tuple_hash(mp_obj_t self_in) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
|
||||
mp_obj_tuple_t *self = self_in;
|
||||
// start hash with pointer to empty tuple, to make it fairly unique
|
||||
machine_int_t hash = (machine_int_t)mp_const_empty_tuple;
|
||||
mp_int_t hash = (mp_int_t)mp_const_empty_tuple;
|
||||
for (uint i = 0; i < self->len; i++) {
|
||||
hash += mp_obj_hash(self->items[i]);
|
||||
}
|
||||
@@ -269,7 +269,7 @@ machine_int_t mp_obj_tuple_hash(mp_obj_t self_in) {
|
||||
typedef struct _mp_obj_tuple_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_tuple_t *tuple;
|
||||
machine_uint_t cur;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_tuple_it_t;
|
||||
|
||||
STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
typedef struct _mp_obj_tuple_t {
|
||||
mp_obj_base_t base;
|
||||
machine_uint_t len;
|
||||
mp_uint_t len;
|
||||
mp_obj_t items[];
|
||||
} mp_obj_tuple_t;
|
||||
|
||||
|
||||
16
py/objtype.c
16
py/objtype.c
@@ -46,6 +46,8 @@
|
||||
#define DEBUG_printf(...) (void)0
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args);
|
||||
|
||||
/******************************************************************************/
|
||||
// instance object
|
||||
|
||||
@@ -101,7 +103,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t
|
||||
struct class_lookup_data {
|
||||
mp_obj_instance_t *obj;
|
||||
qstr attr;
|
||||
machine_uint_t meth_offset;
|
||||
mp_uint_t meth_offset;
|
||||
mp_obj_t *dest;
|
||||
bool is_type;
|
||||
};
|
||||
@@ -749,6 +751,8 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
|
||||
assert(MP_OBJ_IS_TYPE(bases_tuple, &mp_type_tuple)); // Micro Python restriction, for now
|
||||
assert(MP_OBJ_IS_TYPE(locals_dict, &mp_type_dict)); // Micro Python restriction, for now
|
||||
|
||||
// TODO might need to make a copy of locals_dict; at least that's how CPython does it
|
||||
|
||||
// Basic validation of base classes
|
||||
uint len;
|
||||
mp_obj_t *items;
|
||||
@@ -783,6 +787,16 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict"));
|
||||
}
|
||||
|
||||
mp_map_t *locals_map = mp_obj_dict_get_map(o->locals_dict);
|
||||
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP);
|
||||
if (elem != NULL) {
|
||||
// __new__ slot exists; check if it is a function
|
||||
if (MP_OBJ_IS_TYPE(elem->value, &mp_type_fun_native) || MP_OBJ_IS_TYPE(elem->value, &mp_type_fun_bc)) {
|
||||
// __new__ is a function, wrap it in a staticmethod decorator
|
||||
elem->value = static_class_method_make_new((mp_obj_t)&mp_type_staticmethod, 1, 0, &elem->value);
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
86
py/parse.c
86
py/parse.c
@@ -30,8 +30,8 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parsenumbase.h"
|
||||
@@ -109,20 +109,20 @@ STATIC const rule_t *rules[] = {
|
||||
};
|
||||
|
||||
typedef struct _rule_stack_t {
|
||||
unsigned int src_line : 24;
|
||||
unsigned int rule_id : 8;
|
||||
int32_t arg_i; // what should be the size and signedness?
|
||||
mp_uint_t src_line : 24;
|
||||
mp_uint_t rule_id : 8;
|
||||
mp_uint_t arg_i : 32; // what should the bit-size be?
|
||||
} rule_stack_t;
|
||||
|
||||
typedef struct _parser_t {
|
||||
bool had_memory_error;
|
||||
|
||||
uint rule_stack_alloc;
|
||||
uint rule_stack_top;
|
||||
mp_uint_t rule_stack_alloc;
|
||||
mp_uint_t rule_stack_top;
|
||||
rule_stack_t *rule_stack;
|
||||
|
||||
uint result_stack_alloc;
|
||||
uint result_stack_top;
|
||||
mp_uint_t result_stack_alloc;
|
||||
mp_uint_t result_stack_top;
|
||||
mp_parse_node_t *result_stack;
|
||||
|
||||
mp_lexer_t *lexer;
|
||||
@@ -132,7 +132,7 @@ STATIC inline void memory_error(parser_t *parser) {
|
||||
parser->had_memory_error = true;
|
||||
}
|
||||
|
||||
STATIC void push_rule(parser_t *parser, int src_line, const rule_t *rule, int arg_i) {
|
||||
STATIC void push_rule(parser_t *parser, mp_uint_t src_line, const rule_t *rule, mp_uint_t arg_i) {
|
||||
if (parser->had_memory_error) {
|
||||
return;
|
||||
}
|
||||
@@ -151,14 +151,14 @@ STATIC void push_rule(parser_t *parser, int src_line, const rule_t *rule, int ar
|
||||
rs->arg_i = arg_i;
|
||||
}
|
||||
|
||||
STATIC void push_rule_from_arg(parser_t *parser, uint arg) {
|
||||
STATIC void push_rule_from_arg(parser_t *parser, mp_uint_t arg) {
|
||||
assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);
|
||||
uint rule_id = arg & RULE_ARG_ARG_MASK;
|
||||
mp_uint_t rule_id = arg & RULE_ARG_ARG_MASK;
|
||||
assert(rule_id < RULE_maximum_number_of);
|
||||
push_rule(parser, mp_lexer_cur(parser->lexer)->src_line, rules[rule_id], 0);
|
||||
}
|
||||
|
||||
STATIC void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i, uint *src_line) {
|
||||
STATIC void pop_rule(parser_t *parser, const rule_t **rule, mp_uint_t *arg_i, mp_uint_t *src_line) {
|
||||
assert(!parser->had_memory_error);
|
||||
parser->rule_stack_top -= 1;
|
||||
*rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
|
||||
@@ -166,7 +166,7 @@ STATIC void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i, uint *s
|
||||
*src_line = parser->rule_stack[parser->rule_stack_top].src_line;
|
||||
}
|
||||
|
||||
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
|
||||
mp_parse_node_t mp_parse_node_new_leaf(mp_int_t kind, mp_int_t arg) {
|
||||
if (kind == MP_PARSE_NODE_SMALL_INT) {
|
||||
return (mp_parse_node_t)(kind | (arg << 1));
|
||||
}
|
||||
@@ -176,8 +176,8 @@ mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
|
||||
void mp_parse_node_free(mp_parse_node_t pn) {
|
||||
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
|
||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
|
||||
uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
uint rule_id = MP_PARSE_NODE_STRUCT_KIND(pns);
|
||||
mp_uint_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
mp_uint_t rule_id = MP_PARSE_NODE_STRUCT_KIND(pns);
|
||||
if (rule_id == RULE_string) {
|
||||
return;
|
||||
}
|
||||
@@ -185,7 +185,7 @@ void mp_parse_node_free(mp_parse_node_t pn) {
|
||||
if (adjust) {
|
||||
n--;
|
||||
}
|
||||
for (uint i = 0; i < n; i++) {
|
||||
for (mp_uint_t i = 0; i < n; i++) {
|
||||
mp_parse_node_free(pns->nodes[i]);
|
||||
}
|
||||
if (adjust) {
|
||||
@@ -196,22 +196,22 @@ void mp_parse_node_free(mp_parse_node_t pn) {
|
||||
}
|
||||
|
||||
#if MICROPY_DEBUG_PRINTERS
|
||||
void mp_parse_node_print(mp_parse_node_t pn, int indent) {
|
||||
void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent) {
|
||||
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
|
||||
printf("[% 4d] ", (int)((mp_parse_node_struct_t*)pn)->source_line);
|
||||
} else {
|
||||
printf(" ");
|
||||
}
|
||||
for (int i = 0; i < indent; i++) {
|
||||
for (mp_uint_t i = 0; i < indent; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
if (MP_PARSE_NODE_IS_NULL(pn)) {
|
||||
printf("NULL\n");
|
||||
} else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) {
|
||||
machine_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
|
||||
mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn);
|
||||
printf("int(" INT_FMT ")\n", arg);
|
||||
} else if (MP_PARSE_NODE_IS_LEAF(pn)) {
|
||||
machine_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
mp_uint_t arg = MP_PARSE_NODE_LEAF_ARG(pn);
|
||||
switch (MP_PARSE_NODE_LEAF_KIND(pn)) {
|
||||
case MP_PARSE_NODE_ID: printf("id(%s)\n", qstr_str(arg)); break;
|
||||
case MP_PARSE_NODE_INTEGER: printf("int(%s)\n", qstr_str(arg)); break;
|
||||
@@ -227,13 +227,13 @@ void mp_parse_node_print(mp_parse_node_t pn, int indent) {
|
||||
if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
|
||||
printf("literal str(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
|
||||
} else {
|
||||
uint n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
mp_uint_t n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
|
||||
#ifdef USE_RULE_NAME
|
||||
printf("%s(%d) (n=%d)\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, MP_PARSE_NODE_STRUCT_KIND(pns), n);
|
||||
printf("%s(" UINT_FMT ") (n=" UINT_FMT ")\n", rules[MP_PARSE_NODE_STRUCT_KIND(pns)]->rule_name, (mp_uint_t)MP_PARSE_NODE_STRUCT_KIND(pns), n);
|
||||
#else
|
||||
printf("rule(%u) (n=%d)\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns), n);
|
||||
printf("rule(" UINT_FMT ") (n=" UINT_FMT ")\n", (mp_uint_t)MP_PARSE_NODE_STRUCT_KIND(pns), n);
|
||||
#endif
|
||||
for (uint i = 0; i < n; i++) {
|
||||
for (mp_uint_t i = 0; i < n; i++) {
|
||||
mp_parse_node_print(pns->nodes[i], indent + 2);
|
||||
}
|
||||
}
|
||||
@@ -244,7 +244,7 @@ void mp_parse_node_print(mp_parse_node_t pn, int indent) {
|
||||
/*
|
||||
STATIC void result_stack_show(parser_t *parser) {
|
||||
printf("result stack, most recent first\n");
|
||||
for (int i = parser->result_stack_top - 1; i >= 0; i--) {
|
||||
for (mp_int_t i = parser->result_stack_top - 1; i >= 0; i--) {
|
||||
mp_parse_node_print(parser->result_stack[i], 0);
|
||||
}
|
||||
}
|
||||
@@ -258,7 +258,7 @@ STATIC mp_parse_node_t pop_result(parser_t *parser) {
|
||||
return parser->result_stack[--parser->result_stack_top];
|
||||
}
|
||||
|
||||
STATIC mp_parse_node_t peek_result(parser_t *parser, int pos) {
|
||||
STATIC mp_parse_node_t peek_result(parser_t *parser, mp_uint_t pos) {
|
||||
if (parser->had_memory_error) {
|
||||
return MP_PARSE_NODE_NULL;
|
||||
}
|
||||
@@ -282,7 +282,7 @@ STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
|
||||
parser->result_stack[parser->result_stack_top++] = pn;
|
||||
}
|
||||
|
||||
STATIC void push_result_string(parser_t *parser, int src_line, const char *str, uint len) {
|
||||
STATIC void push_result_string(parser_t *parser, mp_uint_t src_line, const char *str, mp_uint_t len) {
|
||||
mp_parse_node_struct_t *pn = m_new_obj_var_maybe(mp_parse_node_struct_t, mp_parse_node_t, 2);
|
||||
if (pn == NULL) {
|
||||
memory_error(parser);
|
||||
@@ -292,7 +292,7 @@ STATIC void push_result_string(parser_t *parser, int src_line, const char *str,
|
||||
pn->kind_num_nodes = RULE_string | (2 << 8);
|
||||
char *p = m_new(char, len);
|
||||
memcpy(p, str, len);
|
||||
pn->nodes[0] = (machine_int_t)p;
|
||||
pn->nodes[0] = (mp_int_t)p;
|
||||
pn->nodes[1] = len;
|
||||
push_result_node(parser, (mp_parse_node_t)pn);
|
||||
}
|
||||
@@ -305,14 +305,14 @@ STATIC void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
|
||||
} else if (tok->kind == MP_TOKEN_NUMBER) {
|
||||
bool dec = false;
|
||||
bool small_int = true;
|
||||
machine_int_t int_val = 0;
|
||||
int len = tok->len;
|
||||
mp_int_t int_val = 0;
|
||||
mp_uint_t len = tok->len;
|
||||
const char *str = tok->str;
|
||||
int base = 0;
|
||||
int i = mp_parse_num_base(str, len, &base);
|
||||
mp_uint_t base = 0;
|
||||
mp_uint_t i = mp_parse_num_base(str, len, &base);
|
||||
bool overflow = false;
|
||||
for (; i < len; i++) {
|
||||
int dig;
|
||||
mp_uint_t dig;
|
||||
if (unichar_isdigit(str[i]) && str[i] - '0' < base) {
|
||||
dig = str[i] - '0';
|
||||
} else if (base == 16 && 'a' <= str[i] && str[i] <= 'f') {
|
||||
@@ -369,7 +369,7 @@ STATIC void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
|
||||
push_result_node(parser, pn);
|
||||
}
|
||||
|
||||
STATIC void push_result_rule(parser_t *parser, int src_line, const rule_t *rule, int num_args) {
|
||||
STATIC void push_result_rule(parser_t *parser, mp_uint_t src_line, const rule_t *rule, mp_uint_t num_args) {
|
||||
mp_parse_node_struct_t *pn = m_new_obj_var_maybe(mp_parse_node_struct_t, mp_parse_node_t, num_args);
|
||||
if (pn == NULL) {
|
||||
memory_error(parser);
|
||||
@@ -377,7 +377,7 @@ STATIC void push_result_rule(parser_t *parser, int src_line, const rule_t *rule,
|
||||
}
|
||||
pn->source_line = src_line;
|
||||
pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);
|
||||
for (int i = num_args; i > 0; i--) {
|
||||
for (mp_uint_t i = num_args; i > 0; i--) {
|
||||
pn->nodes[i - 1] = pop_result(parser);
|
||||
}
|
||||
push_result_node(parser, (mp_parse_node_t)pn);
|
||||
@@ -407,7 +407,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
|
||||
}
|
||||
|
||||
// work out the top-level rule to use, and push it on the stack
|
||||
int top_level_rule;
|
||||
mp_uint_t top_level_rule;
|
||||
switch (input_kind) {
|
||||
case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;
|
||||
case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
|
||||
@@ -417,8 +417,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
|
||||
|
||||
// parse!
|
||||
|
||||
uint n, i; // state for the current rule
|
||||
uint rule_src_line; // source line for the first token matched by the current rule
|
||||
mp_uint_t n, i; // state for the current rule
|
||||
mp_uint_t rule_src_line; // source line for the first token matched by the current rule
|
||||
bool backtrack = false;
|
||||
const rule_t *rule = NULL;
|
||||
mp_token_kind_t tok_kind;
|
||||
@@ -541,7 +541,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
|
||||
// count number of arguments for the parse_node
|
||||
i = 0;
|
||||
emit_rule = false;
|
||||
for (int x = 0; x < n; ++x) {
|
||||
for (mp_uint_t x = 0; x < n; ++x) {
|
||||
if ((rule->arg[x] & RULE_ARG_KIND_MASK) == RULE_ARG_TOK) {
|
||||
tok_kind = rule->arg[x] & RULE_ARG_ARG_MASK;
|
||||
if (tok_kind >= MP_TOKEN_NAME) {
|
||||
@@ -589,8 +589,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
|
||||
i += 1;
|
||||
}
|
||||
|
||||
int num_not_nil = 0;
|
||||
for (int x = 0; x < i; ++x) {
|
||||
mp_uint_t num_not_nil = 0;
|
||||
for (mp_uint_t x = 0; x < i; ++x) {
|
||||
if (peek_result(&parser, x) != MP_PARSE_NODE_NULL) {
|
||||
num_not_nil += 1;
|
||||
}
|
||||
@@ -605,7 +605,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
|
||||
} else if (num_not_nil == 1) {
|
||||
// single result, leave it on stack
|
||||
mp_parse_node_t pn = MP_PARSE_NODE_NULL;
|
||||
for (int x = 0; x < i; ++x) {
|
||||
for (mp_uint_t x = 0; x < i; ++x) {
|
||||
mp_parse_node_t pn2 = pop_result(&parser);
|
||||
if (pn2 != MP_PARSE_NODE_NULL) {
|
||||
pn = pn2;
|
||||
@@ -653,7 +653,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, mp_p
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
uint arg = rule->arg[i & 1 & n];
|
||||
mp_uint_t arg = rule->arg[i & 1 & n];
|
||||
switch (arg & RULE_ARG_KIND_MASK) {
|
||||
case RULE_ARG_TOK:
|
||||
if (mp_lexer_is_kind(lex, arg & RULE_ARG_ARG_MASK)) {
|
||||
|
||||
10
py/parse.h
10
py/parse.h
@@ -46,7 +46,7 @@ struct _mp_lexer_t;
|
||||
#define MP_PARSE_NODE_BYTES (0x12)
|
||||
#define MP_PARSE_NODE_TOKEN (0x16)
|
||||
|
||||
typedef machine_uint_t mp_parse_node_t; // must be pointer size
|
||||
typedef mp_uint_t mp_parse_node_t; // must be pointer size
|
||||
|
||||
typedef struct _mp_parse_node_struct_t {
|
||||
uint32_t source_line; // line number in source file
|
||||
@@ -69,15 +69,15 @@ typedef struct _mp_parse_node_struct_t {
|
||||
|
||||
#define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0x1f)
|
||||
// TODO should probably have int and uint versions of this macro
|
||||
#define MP_PARSE_NODE_LEAF_ARG(pn) (((machine_uint_t)(pn)) >> 5)
|
||||
#define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((machine_int_t)(pn)) >> 1)
|
||||
#define MP_PARSE_NODE_LEAF_ARG(pn) (((mp_uint_t)(pn)) >> 5)
|
||||
#define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((mp_int_t)(pn)) >> 1)
|
||||
#define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff)
|
||||
#define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)
|
||||
|
||||
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg);
|
||||
mp_parse_node_t mp_parse_node_new_leaf(mp_int_t kind, mp_int_t arg);
|
||||
void mp_parse_node_free(mp_parse_node_t pn);
|
||||
|
||||
void mp_parse_node_print(mp_parse_node_t pn, int indent);
|
||||
void mp_parse_node_print(mp_parse_node_t pn, mp_uint_t indent);
|
||||
|
||||
typedef enum {
|
||||
MP_PARSE_SINGLE_INPUT,
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "lexer.h"
|
||||
#include "parse.h"
|
||||
@@ -43,7 +43,7 @@
|
||||
#define STR_INVALID_SYNTAX "invalid syntax"
|
||||
|
||||
void mp_parse_show_exception(mp_lexer_t *lex, mp_parse_error_kind_t parse_error_kind) {
|
||||
printf(" File \"%s\", line %d, column %d\n", qstr_str(mp_lexer_source_name(lex)), mp_lexer_cur(lex)->src_line, mp_lexer_cur(lex)->src_column);
|
||||
printf(" File \"%s\", line " UINT_FMT ", column " UINT_FMT "\n", qstr_str(mp_lexer_source_name(lex)), mp_lexer_cur(lex)->src_line, mp_lexer_cur(lex)->src_column);
|
||||
switch (parse_error_kind) {
|
||||
case MP_PARSE_ERROR_MEMORY:
|
||||
printf("MemoryError: %s\n", STR_MEMORY);
|
||||
|
||||
@@ -27,21 +27,23 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "nlr.h"
|
||||
#include "obj.h"
|
||||
#include "parsenumbase.h"
|
||||
#include "parsenum.h"
|
||||
#include "smallint.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
|
||||
const char *restrict top = str + len;
|
||||
mp_obj_t mp_parse_num_integer(const char *restrict str_, mp_uint_t len, mp_uint_t base) {
|
||||
const byte *restrict str = (const byte *)str_;
|
||||
const byte *restrict top = str + len;
|
||||
bool neg = false;
|
||||
mp_obj_t ret_val;
|
||||
|
||||
@@ -65,14 +67,14 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) {
|
||||
}
|
||||
|
||||
// parse optional base prefix
|
||||
str += mp_parse_num_base(str, top - str, &base);
|
||||
str += mp_parse_num_base((const char*)str, top - str, &base);
|
||||
|
||||
// string should be an integer number
|
||||
machine_int_t int_val = 0;
|
||||
const char *restrict str_val_start = str;
|
||||
mp_int_t int_val = 0;
|
||||
const byte *restrict str_val_start = str;
|
||||
for (; str < top; str++) {
|
||||
// get next digit as a value
|
||||
int dig = *str;
|
||||
mp_uint_t dig = *str;
|
||||
if (unichar_isdigit(dig) && dig - '0' < base) {
|
||||
// 0-9 digit
|
||||
dig = dig - '0';
|
||||
@@ -129,9 +131,9 @@ have_ret_val:
|
||||
overflow:
|
||||
// reparse using long int
|
||||
{
|
||||
const char *s2 = str_val_start;
|
||||
const char *s2 = (const char*)str_val_start;
|
||||
ret_val = mp_obj_new_int_from_str_len(&s2, top - str_val_start, neg, base);
|
||||
str = s2;
|
||||
str = (const byte*)s2;
|
||||
goto have_ret_val;
|
||||
}
|
||||
|
||||
@@ -139,11 +141,13 @@ value_error:
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid syntax for integer with base %d: '%s'", base, str));
|
||||
}
|
||||
|
||||
#define PARSE_DEC_IN_INTG (1)
|
||||
#define PARSE_DEC_IN_FRAC (2)
|
||||
#define PARSE_DEC_IN_EXP (3)
|
||||
typedef enum {
|
||||
PARSE_DEC_IN_INTG,
|
||||
PARSE_DEC_IN_FRAC,
|
||||
PARSE_DEC_IN_EXP,
|
||||
} parse_dec_in_t;
|
||||
|
||||
mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex) {
|
||||
mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, bool force_complex) {
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
const char *top = str + len;
|
||||
mp_float_t dec_val = 0;
|
||||
@@ -185,12 +189,12 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
|
||||
}
|
||||
} else {
|
||||
// string should be a decimal number
|
||||
int in = PARSE_DEC_IN_INTG;
|
||||
parse_dec_in_t in = PARSE_DEC_IN_INTG;
|
||||
bool exp_neg = false;
|
||||
int exp_val = 0;
|
||||
int exp_extra = 0;
|
||||
mp_int_t exp_val = 0;
|
||||
mp_int_t exp_extra = 0;
|
||||
for (; str < top; str++) {
|
||||
int dig = *str;
|
||||
mp_uint_t dig = *str;
|
||||
if ('0' <= dig && dig <= '9') {
|
||||
dig -= '0';
|
||||
if (in == PARSE_DEC_IN_EXP) {
|
||||
@@ -251,10 +255,15 @@ mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool f
|
||||
}
|
||||
|
||||
// return the object
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
if (imag) {
|
||||
return mp_obj_new_complex(0, dec_val);
|
||||
} else if (force_complex) {
|
||||
return mp_obj_new_complex(dec_val, 0);
|
||||
#else
|
||||
if (imag || force_complex) {
|
||||
mp_not_implemented("complex values not supported");
|
||||
#endif
|
||||
} else {
|
||||
return mp_obj_new_float(dec_val);
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base);
|
||||
mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex);
|
||||
mp_obj_t mp_parse_num_integer(const char *restrict str, mp_uint_t len, mp_uint_t base);
|
||||
mp_obj_t mp_parse_num_decimal(const char *str, mp_uint_t len, bool allow_imag, bool force_complex);
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "parsenumbase.h"
|
||||
|
||||
// find real radix base, and strip preceding '0x', '0o' and '0b'
|
||||
// puts base in *base, and returns number of bytes to skip the prefix
|
||||
int mp_parse_num_base(const char *str, uint len, int *base) {
|
||||
const char *p = str;
|
||||
int c = *(p++);
|
||||
mp_uint_t mp_parse_num_base(const char *str, mp_uint_t len, mp_uint_t *base) {
|
||||
const byte *p = (const byte*)str;
|
||||
unichar c = *(p++);
|
||||
if ((*base == 0 || *base == 16) && c == '0') {
|
||||
c = *(p++);
|
||||
if ((c | 32) == 'x') {
|
||||
@@ -63,6 +63,5 @@ int mp_parse_num_base(const char *str, uint len, int *base) {
|
||||
}
|
||||
p--;
|
||||
}
|
||||
return p - str;
|
||||
return p - (const byte*)str;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,4 +24,4 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
int mp_parse_num_base(const char *str, uint len, int *base);
|
||||
mp_uint_t mp_parse_num_base(const char *str, mp_uint_t len, mp_uint_t *base);
|
||||
|
||||
10
py/pfenv.c
10
py/pfenv.c
@@ -27,8 +27,8 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "mpz.h"
|
||||
@@ -111,14 +111,14 @@ int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, in
|
||||
|
||||
// 32-bits is 10 digits, add 3 for commas, 1 for sign, 1 for terminating null
|
||||
// We can use 16 characters for 32-bit and 32 characters for 64-bit
|
||||
#define INT_BUF_SIZE (sizeof(machine_int_t) * 4)
|
||||
#define INT_BUF_SIZE (sizeof(mp_int_t) * 4)
|
||||
|
||||
// This function is used by stmhal port to implement printf.
|
||||
// It needs to be a separate function to pfenv_print_mp_int, since converting to a mp_int looses the MSB.
|
||||
int pfenv_print_int(const pfenv_t *pfenv, machine_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {
|
||||
int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) {
|
||||
char sign = 0;
|
||||
if (sgn) {
|
||||
if ((machine_int_t)x < 0) {
|
||||
if ((mp_int_t)x < 0) {
|
||||
sign = '-';
|
||||
x = -x;
|
||||
} else if (flags & PF_FLAG_SHOW_SIGN) {
|
||||
@@ -232,7 +232,7 @@ int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int sgn, int base, int
|
||||
|
||||
// The size of this buffer is rather arbitrary. If it's not large
|
||||
// enough, a dynamic one will be allocated.
|
||||
char stack_buf[sizeof(machine_int_t) * 4];
|
||||
char stack_buf[sizeof(mp_int_t) * 4];
|
||||
char *buf = stack_buf;
|
||||
int buf_size = sizeof(stack_buf);
|
||||
int fmt_size = 0;
|
||||
|
||||
@@ -44,7 +44,7 @@ typedef struct _pfenv_t {
|
||||
void pfenv_vstr_add_strn(void *data, const char *str, unsigned int len);
|
||||
|
||||
int pfenv_print_strn(const pfenv_t *pfenv, const char *str, unsigned int len, int flags, char fill, int width);
|
||||
int pfenv_print_int(const pfenv_t *pfenv, machine_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width);
|
||||
int pfenv_print_int(const pfenv_t *pfenv, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width);
|
||||
int pfenv_print_mp_int(const pfenv_t *pfenv, mp_obj_t x, int sgn, int base, int base_char, int flags, char fill, int width, int prec);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
int pfenv_print_float(const pfenv_t *pfenv, mp_float_t f, char fmt, int flags, char fill, int width, int prec);
|
||||
|
||||
3
py/py.mk
3
py/py.mk
@@ -43,6 +43,7 @@ PY_O_BASENAME = \
|
||||
parsenum.o \
|
||||
emitglue.o \
|
||||
runtime.o \
|
||||
stackctrl.o \
|
||||
argcheck.o \
|
||||
map.o \
|
||||
obj.o \
|
||||
@@ -74,6 +75,7 @@ PY_O_BASENAME = \
|
||||
objset.o \
|
||||
objslice.o \
|
||||
objstr.o \
|
||||
objstrunicode.o \
|
||||
objstringio.o \
|
||||
objtuple.o \
|
||||
objtype.o \
|
||||
@@ -100,6 +102,7 @@ PY_O_BASENAME = \
|
||||
repl.o \
|
||||
smallint.o \
|
||||
pfenv.o \
|
||||
../extmod/moductypes.o
|
||||
|
||||
# prepend the build destination prefix to the py object files
|
||||
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
|
||||
|
||||
16
py/qstr.c
16
py/qstr.c
@@ -27,8 +27,8 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
|
||||
// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
|
||||
@@ -55,9 +55,9 @@
|
||||
#define Q_GET_DATA(q) ((q) + 4)
|
||||
|
||||
// this must match the equivalent function in makeqstrdata.py
|
||||
machine_uint_t qstr_compute_hash(const byte *data, uint len) {
|
||||
mp_uint_t qstr_compute_hash(const byte *data, uint len) {
|
||||
// djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html
|
||||
machine_uint_t hash = 5381;
|
||||
mp_uint_t hash = 5381;
|
||||
for (const byte *top = data + len; data < top; data++) {
|
||||
hash = ((hash << 5) + hash) ^ (*data); // hash * 33 ^ data
|
||||
}
|
||||
@@ -132,7 +132,7 @@ STATIC qstr qstr_add(const byte *q_ptr) {
|
||||
|
||||
qstr qstr_find_strn(const char *str, uint str_len) {
|
||||
// work out hash of str
|
||||
machine_uint_t str_hash = qstr_compute_hash((const byte*)str, str_len);
|
||||
mp_uint_t str_hash = qstr_compute_hash((const byte*)str, str_len);
|
||||
|
||||
// search pools for the data
|
||||
for (qstr_pool_t *pool = last_pool; pool != NULL; pool = pool->prev) {
|
||||
@@ -154,7 +154,7 @@ qstr qstr_from_str(const char *str) {
|
||||
qstr qstr_from_strn(const char *str, uint len) {
|
||||
qstr q = qstr_find_strn(str, len);
|
||||
if (q == 0) {
|
||||
machine_uint_t hash = qstr_compute_hash((const byte*)str, len);
|
||||
mp_uint_t hash = qstr_compute_hash((const byte*)str, len);
|
||||
byte *q_ptr = m_new(byte, 4 + len + 1);
|
||||
q_ptr[0] = hash;
|
||||
q_ptr[1] = hash >> 8;
|
||||
@@ -178,8 +178,8 @@ byte *qstr_build_start(uint len, byte **q_ptr) {
|
||||
qstr qstr_build_end(byte *q_ptr) {
|
||||
qstr q = qstr_find_strn((const char*)Q_GET_DATA(q_ptr), Q_GET_LENGTH(q_ptr));
|
||||
if (q == 0) {
|
||||
machine_uint_t len = Q_GET_LENGTH(q_ptr);
|
||||
machine_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len);
|
||||
mp_uint_t len = Q_GET_LENGTH(q_ptr);
|
||||
mp_uint_t hash = qstr_compute_hash(Q_GET_DATA(q_ptr), len);
|
||||
q_ptr[0] = hash;
|
||||
q_ptr[1] = hash >> 8;
|
||||
q_ptr[4 + len] = '\0';
|
||||
@@ -190,7 +190,7 @@ qstr qstr_build_end(byte *q_ptr) {
|
||||
return q;
|
||||
}
|
||||
|
||||
machine_uint_t qstr_hash(qstr q) {
|
||||
mp_uint_t qstr_hash(qstr q) {
|
||||
return Q_GET_HASH(find_qstr(q));
|
||||
}
|
||||
|
||||
|
||||
@@ -39,13 +39,13 @@ enum {
|
||||
MP_QSTR_number_of,
|
||||
};
|
||||
|
||||
typedef machine_uint_t qstr;
|
||||
typedef mp_uint_t qstr;
|
||||
|
||||
#define QSTR_FROM_STR_STATIC(s) (qstr_from_strn((s), strlen(s)))
|
||||
|
||||
void qstr_init(void);
|
||||
|
||||
machine_uint_t qstr_compute_hash(const byte *data, uint len);
|
||||
mp_uint_t qstr_compute_hash(const byte *data, uint len);
|
||||
qstr qstr_find_strn(const char *str, uint str_len); // returns MP_QSTR_NULL if not found
|
||||
|
||||
qstr qstr_from_str(const char *str);
|
||||
@@ -56,7 +56,7 @@ qstr qstr_from_strn(const char *str, uint len);
|
||||
byte* qstr_build_start(uint len, byte **q_ptr);
|
||||
qstr qstr_build_end(byte *q_ptr);
|
||||
|
||||
machine_uint_t qstr_hash(qstr q);
|
||||
mp_uint_t qstr_hash(qstr q);
|
||||
const char* qstr_str(qstr q);
|
||||
uint qstr_len(qstr q);
|
||||
const byte* qstr_data(qstr q, uint *len);
|
||||
|
||||
@@ -352,6 +352,9 @@ Q(stdout)
|
||||
Q(stderr)
|
||||
Q(version)
|
||||
Q(version_info)
|
||||
#if MICROPY_PY_SYS_MAXSIZE
|
||||
Q(maxsize)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_STRUCT
|
||||
@@ -360,6 +363,46 @@ Q(pack)
|
||||
Q(unpack)
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UCTYPES
|
||||
Q(uctypes)
|
||||
Q(sizeof)
|
||||
Q(addressof)
|
||||
Q(bytes_at)
|
||||
Q(bytearray_at)
|
||||
|
||||
Q(NATIVE)
|
||||
Q(LITTLE_ENDIAN)
|
||||
Q(BIG_ENDIAN)
|
||||
|
||||
Q(VOID)
|
||||
|
||||
Q(UINT8)
|
||||
Q(INT8)
|
||||
Q(UINT16)
|
||||
Q(INT16)
|
||||
Q(UINT32)
|
||||
Q(INT32)
|
||||
Q(UINT64)
|
||||
Q(INT64)
|
||||
|
||||
Q(BFUINT8)
|
||||
Q(BFINT8)
|
||||
Q(BFUINT16)
|
||||
Q(BFINT16)
|
||||
Q(BFUINT32)
|
||||
Q(BFINT32)
|
||||
|
||||
Q(FLOAT32)
|
||||
Q(FLOAT64)
|
||||
|
||||
Q(ARRAY)
|
||||
Q(PTR)
|
||||
//Q(BITFIELD)
|
||||
|
||||
Q(BF_POS)
|
||||
Q(BF_LEN)
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_IO
|
||||
Q(_io)
|
||||
Q(readall)
|
||||
@@ -377,6 +420,8 @@ Q(gc)
|
||||
Q(collect)
|
||||
Q(disable)
|
||||
Q(enable)
|
||||
Q(mem_free)
|
||||
Q(mem_alloc)
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_PROPERTY
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "repl.h"
|
||||
|
||||
#if MICROPY_HELPER_REPL
|
||||
|
||||
25
py/runtime.c
25
py/runtime.c
@@ -45,6 +45,7 @@
|
||||
#include "smallint.h"
|
||||
#include "objgenerator.h"
|
||||
#include "lexer.h"
|
||||
#include "stackctrl.h"
|
||||
|
||||
#if 0 // print debugging info
|
||||
#define DEBUG_PRINT (1)
|
||||
@@ -69,6 +70,8 @@ const mp_obj_module_t mp_module___main__ = {
|
||||
};
|
||||
|
||||
void mp_init(void) {
|
||||
mp_stack_ctrl_init();
|
||||
|
||||
// call port specific initialization if any
|
||||
#ifdef MICROPY_PORT_INIT_FUNC
|
||||
MICROPY_PORT_INIT_FUNC;
|
||||
@@ -184,7 +187,7 @@ mp_obj_t mp_unary_op(int op, mp_obj_t arg) {
|
||||
DEBUG_OP_printf("unary %d %p\n", op, arg);
|
||||
|
||||
if (MP_OBJ_IS_SMALL_INT(arg)) {
|
||||
mp_small_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
|
||||
mp_int_t val = MP_OBJ_SMALL_INT_VALUE(arg);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL:
|
||||
return MP_BOOL(val != 0);
|
||||
@@ -269,17 +272,17 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
}
|
||||
|
||||
if (MP_OBJ_IS_SMALL_INT(lhs)) {
|
||||
mp_small_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
|
||||
mp_int_t lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs);
|
||||
if (MP_OBJ_IS_SMALL_INT(rhs)) {
|
||||
mp_small_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
|
||||
mp_int_t rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs);
|
||||
// This is a binary operation: lhs_val op rhs_val
|
||||
// We need to be careful to handle overflow; see CERT INT32-C
|
||||
// Operations that can overflow:
|
||||
// + result always fits in machine_int_t, then handled by SMALL_INT check
|
||||
// - result always fits in machine_int_t, then handled by SMALL_INT check
|
||||
// + result always fits in mp_int_t, then handled by SMALL_INT check
|
||||
// - result always fits in mp_int_t, then handled by SMALL_INT check
|
||||
// * checked explicitly
|
||||
// / if lhs=MIN and rhs=-1; result always fits in machine_int_t, then handled by SMALL_INT check
|
||||
// % if lhs=MIN and rhs=-1; result always fits in machine_int_t, then handled by SMALL_INT check
|
||||
// / if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check
|
||||
// % if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check
|
||||
// << checked explicitly
|
||||
switch (op) {
|
||||
case MP_BINARY_OP_OR:
|
||||
@@ -320,7 +323,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
case MP_BINARY_OP_MULTIPLY:
|
||||
case MP_BINARY_OP_INPLACE_MULTIPLY: {
|
||||
|
||||
// If long long type exists and is larger than machine_int_t, then
|
||||
// If long long type exists and is larger than mp_int_t, then
|
||||
// we can use the following code to perform overflow-checked multiplication.
|
||||
// Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow.
|
||||
#if 0
|
||||
@@ -331,7 +334,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
return mp_obj_new_int_from_ll(res);
|
||||
} else {
|
||||
// use standard precision
|
||||
lhs_val = (mp_small_int_t)res;
|
||||
lhs_val = (mp_int_t)res;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -378,7 +381,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative power with no float support"));
|
||||
#endif
|
||||
} else {
|
||||
machine_int_t ans = 1;
|
||||
mp_int_t ans = 1;
|
||||
while (rhs_val > 0) {
|
||||
if (rhs_val & 1) {
|
||||
if (mp_small_int_mul_overflow(ans, lhs_val)) {
|
||||
@@ -426,6 +429,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
#if MICROPY_PY_BUILTINS_COMPLEX
|
||||
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_complex)) {
|
||||
mp_obj_t res = mp_obj_complex_binary_op(op, lhs_val, 0, rhs);
|
||||
if (res == MP_OBJ_NULL) {
|
||||
@@ -433,6 +437,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ typedef enum {
|
||||
|
||||
typedef union _mp_arg_val_t {
|
||||
bool u_bool;
|
||||
machine_int_t u_int;
|
||||
mp_int_t u_int;
|
||||
mp_obj_t u_obj;
|
||||
} mp_arg_val_t;
|
||||
|
||||
typedef struct _mp_arg_t {
|
||||
qstr qstr;
|
||||
machine_uint_t flags;
|
||||
mp_uint_t flags;
|
||||
mp_arg_val_t defval;
|
||||
} mp_arg_t;
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "parse.h"
|
||||
|
||||
@@ -53,9 +53,9 @@ void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void
|
||||
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
|
||||
bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) {
|
||||
bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes) {
|
||||
mp_obj_t ostart, ostop, ostep;
|
||||
machine_int_t start, stop;
|
||||
mp_int_t start, stop;
|
||||
mp_obj_slice_get(slice, &ostart, &ostop, &ostep);
|
||||
|
||||
if (ostart == mp_const_none) {
|
||||
@@ -103,8 +103,8 @@ bool mp_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, mp_bound_
|
||||
#endif
|
||||
|
||||
mp_obj_t mp_seq_extract_slice(uint len, const mp_obj_t *seq, mp_bound_slice_t *indexes) {
|
||||
machine_int_t start = indexes->start, stop = indexes->stop;
|
||||
machine_int_t step = indexes->step;
|
||||
mp_int_t start = indexes->start, stop = indexes->stop;
|
||||
mp_int_t step = indexes->step;
|
||||
|
||||
mp_obj_t res = mp_obj_new_list(0, NULL);
|
||||
|
||||
@@ -231,7 +231,7 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp
|
||||
}
|
||||
}
|
||||
|
||||
for (machine_uint_t i = start; i < stop; i++) {
|
||||
for (mp_uint_t i = start; i < stop; i++) {
|
||||
if (mp_obj_equal(items[i], value)) {
|
||||
// Common sense says this cannot overflow small int
|
||||
return MP_OBJ_NEW_SMALL_INT(i);
|
||||
@@ -242,7 +242,7 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp
|
||||
}
|
||||
|
||||
mp_obj_t mp_seq_count_obj(const mp_obj_t *items, uint len, mp_obj_t value) {
|
||||
machine_uint_t count = 0;
|
||||
mp_uint_t count = 0;
|
||||
for (uint i = 0; i < len; i++) {
|
||||
if (mp_obj_equal(items[i], value)) {
|
||||
count++;
|
||||
|
||||
20
py/showbc.c
20
py/showbc.c
@@ -49,9 +49,9 @@
|
||||
} while ((*ip++ & 0x80) != 0); \
|
||||
}
|
||||
#define DECODE_PTR do { \
|
||||
ip = (byte*)(((machine_uint_t)ip + sizeof(machine_uint_t) - 1) & (~(sizeof(machine_uint_t) - 1))); /* align ip */ \
|
||||
unum = *(machine_uint_t*)ip; \
|
||||
ip += sizeof(machine_uint_t); \
|
||||
ip = (byte*)(((mp_uint_t)ip + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1))); /* align ip */ \
|
||||
unum = *(mp_uint_t*)ip; \
|
||||
ip += sizeof(mp_uint_t); \
|
||||
} while (0)
|
||||
|
||||
void mp_bytecode_print2(const byte *ip, int len);
|
||||
@@ -60,7 +60,7 @@ void mp_bytecode_print(const void *descr, const byte *ip, int len) {
|
||||
const byte *ip_start = ip;
|
||||
|
||||
// get code info size
|
||||
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
|
||||
mp_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
|
||||
const byte *code_info = ip;
|
||||
ip += code_info_size;
|
||||
|
||||
@@ -92,8 +92,8 @@ void mp_bytecode_print(const void *descr, const byte *ip, int len) {
|
||||
|
||||
// print out line number info
|
||||
{
|
||||
machine_int_t bc = (code_info + code_info_size) - ip;
|
||||
machine_uint_t source_line = 1;
|
||||
mp_int_t bc = (code_info + code_info_size) - ip;
|
||||
mp_uint_t source_line = 1;
|
||||
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
|
||||
for (const byte* ci = code_info + 12; *ci; ci++) {
|
||||
bc += *ci & 31;
|
||||
@@ -106,7 +106,7 @@ void mp_bytecode_print(const void *descr, const byte *ip, int len) {
|
||||
|
||||
void mp_bytecode_print2(const byte *ip, int len) {
|
||||
const byte *ip_start = ip;
|
||||
machine_uint_t unum;
|
||||
mp_uint_t unum;
|
||||
qstr qstr;
|
||||
while (ip - ip_start < len) {
|
||||
printf("%02u ", (uint)(ip - ip_start));
|
||||
@@ -129,7 +129,7 @@ void mp_bytecode_print2(const byte *ip, int len) {
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_CONST_SMALL_INT: {
|
||||
machine_int_t num = 0;
|
||||
mp_int_t num = 0;
|
||||
if ((ip[0] & 0x40) != 0) {
|
||||
// Number is negative
|
||||
num--;
|
||||
@@ -445,14 +445,14 @@ void mp_bytecode_print2(const byte *ip, int len) {
|
||||
|
||||
case MP_BC_MAKE_CLOSURE: {
|
||||
DECODE_PTR;
|
||||
machine_uint_t n_closed_over = *ip++;
|
||||
mp_uint_t n_closed_over = *ip++;
|
||||
printf("MAKE_CLOSURE %p " UINT_FMT, (void*)unum, n_closed_over);
|
||||
break;
|
||||
}
|
||||
|
||||
case MP_BC_MAKE_CLOSURE_DEFARGS: {
|
||||
DECODE_PTR;
|
||||
machine_uint_t n_closed_over = *ip++;
|
||||
mp_uint_t n_closed_over = *ip++;
|
||||
printf("MAKE_CLOSURE_DEFARGS %p " UINT_FMT, (void*)unum, n_closed_over);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "smallint.h"
|
||||
|
||||
bool mp_small_int_mul_overflow(machine_int_t x, machine_int_t y) {
|
||||
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {
|
||||
// Check for multiply overflow; see CERT INT32-C
|
||||
if (x > 0) { // x is positive
|
||||
if (y > 0) { // x and y are positive
|
||||
@@ -56,20 +56,19 @@ bool mp_small_int_mul_overflow(machine_int_t x, machine_int_t y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
machine_int_t mp_small_int_modulo(machine_int_t dividend, machine_int_t divisor) {
|
||||
machine_int_t lsign = (dividend >= 0) ? 1 :-1;
|
||||
machine_int_t rsign = (divisor >= 0) ? 1 :-1;
|
||||
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) {
|
||||
mp_int_t lsign = (dividend >= 0) ? 1 :-1;
|
||||
mp_int_t rsign = (divisor >= 0) ? 1 :-1;
|
||||
dividend %= divisor;
|
||||
if (lsign != rsign) {
|
||||
dividend += divisor;
|
||||
}
|
||||
return dividend;
|
||||
return dividend;
|
||||
}
|
||||
|
||||
|
||||
machine_int_t mp_small_int_floor_divide(machine_int_t num, machine_int_t denom) {
|
||||
machine_int_t lsign = num > 0 ? 1 : -1;
|
||||
machine_int_t rsign = denom > 0 ? 1 : -1;
|
||||
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom) {
|
||||
mp_int_t lsign = num > 0 ? 1 : -1;
|
||||
mp_int_t rsign = denom > 0 ? 1 : -1;
|
||||
if (lsign == -1) {num *= -1;}
|
||||
if (rsign == -1) {denom *= -1;}
|
||||
if (lsign != rsign){
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
// Functions for small integer arithmetic
|
||||
|
||||
// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range
|
||||
#define MP_SMALL_INT_MIN ((mp_small_int_t)(((machine_int_t)WORD_MSBIT_HIGH) >> 1))
|
||||
#define MP_SMALL_INT_MAX ((mp_small_int_t)(~(MP_SMALL_INT_MIN)))
|
||||
#define MP_SMALL_INT_MIN ((mp_int_t)(((mp_int_t)WORD_MSBIT_HIGH) >> 1))
|
||||
#define MP_SMALL_INT_MAX ((mp_int_t)(~(MP_SMALL_INT_MIN)))
|
||||
#define MP_SMALL_INT_FITS(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)
|
||||
|
||||
bool mp_small_int_mul_overflow(machine_int_t x, machine_int_t y);
|
||||
machine_int_t mp_small_int_modulo(machine_int_t dividend, machine_int_t divisor);
|
||||
machine_int_t mp_small_int_floor_divide(machine_int_t num, machine_int_t denom);
|
||||
bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y);
|
||||
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor);
|
||||
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom);
|
||||
|
||||
63
py/stackctrl.c
Normal file
63
py/stackctrl.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "nlr.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "runtime.h"
|
||||
#include "stackctrl.h"
|
||||
|
||||
// Stack top at the start of program
|
||||
char *stack_top;
|
||||
|
||||
void mp_stack_ctrl_init() {
|
||||
volatile int stack_dummy;
|
||||
stack_top = (char*)&stack_dummy;
|
||||
}
|
||||
|
||||
uint mp_stack_usage() {
|
||||
// Assumes descending stack
|
||||
volatile int stack_dummy;
|
||||
return stack_top - (char*)&stack_dummy;
|
||||
}
|
||||
|
||||
#if MICROPY_STACK_CHECK
|
||||
|
||||
static uint stack_limit = 10240;
|
||||
|
||||
void mp_stack_set_limit(uint limit) {
|
||||
stack_limit = limit;
|
||||
}
|
||||
|
||||
void mp_stack_check() {
|
||||
if (mp_stack_usage() >= stack_limit) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "maximum recursion depth exceeded"));
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MICROPY_STACK_CHECK
|
||||
41
py/stackctrl.h
Normal file
41
py/stackctrl.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
void mp_stack_ctrl_init();
|
||||
uint mp_stack_usage();
|
||||
|
||||
#if MICROPY_STACK_CHECK
|
||||
|
||||
void mp_stack_set_limit(uint limit);
|
||||
void mp_stack_check();
|
||||
#define MP_STACK_CHECK() mp_stack_check()
|
||||
|
||||
#else
|
||||
|
||||
#define mp_stack_set_limit(limit)
|
||||
#define MP_STACK_CHECK()
|
||||
|
||||
#endif
|
||||
40
py/stream.c
40
py/stream.c
@@ -33,9 +33,13 @@
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "objstr.h"
|
||||
#include "runtime.h"
|
||||
#include "stream.h"
|
||||
#if MICROPY_STREAMS_NON_BLOCK
|
||||
#include <errno.h>
|
||||
#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
#define EWOULDBLOCK 140
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// This file defines generic Python stream read/write methods which
|
||||
@@ -63,13 +67,20 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
|
||||
}
|
||||
|
||||
machine_int_t sz;
|
||||
mp_int_t sz;
|
||||
if (n_args == 1 || ((sz = mp_obj_get_int(args[1])) == -1)) {
|
||||
return stream_readall(args[0]);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
if (!o->type->stream_p->is_bytes) {
|
||||
mp_not_implemented("Reading from unicode text streams by character count");
|
||||
}
|
||||
#endif
|
||||
|
||||
byte *buf = m_new(byte, sz);
|
||||
int error;
|
||||
machine_int_t out_sz = o->type->stream_p->read(o, buf, sz, &error);
|
||||
mp_int_t out_sz = o->type->stream_p->read(o, buf, sz, &error);
|
||||
if (out_sz == -1) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
// https://docs.python.org/3.4/library/io.html#io.RawIOBase.read
|
||||
@@ -87,18 +98,15 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t len) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
|
||||
if (o->type->stream_p == NULL || o->type->stream_p->write == NULL) {
|
||||
// CPython: io.UnsupportedOperation, OSError subclass
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
|
||||
}
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
int error;
|
||||
machine_int_t out_sz = o->type->stream_p->write(self_in, bufinfo.buf, bufinfo.len, &error);
|
||||
mp_int_t out_sz = o->type->stream_p->write(self_in, buf, len, &error);
|
||||
if (out_sz == -1) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
// http://docs.python.org/3/library/io.html#io.RawIOBase.write
|
||||
@@ -114,6 +122,12 @@ STATIC mp_obj_t stream_write(mp_obj_t self_in, mp_obj_t arg) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t stream_write_method(mp_obj_t self_in, mp_obj_t arg) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
|
||||
return mp_stream_write(self_in, bufinfo.buf, bufinfo.len);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
|
||||
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
|
||||
@@ -128,7 +142,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
|
||||
int error;
|
||||
int current_read = DEFAULT_BUFFER_SIZE;
|
||||
while (true) {
|
||||
machine_int_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error);
|
||||
mp_int_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error);
|
||||
if (out_sz == -1) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
// With non-blocking streams, we read as much as we can.
|
||||
@@ -171,7 +185,7 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
|
||||
}
|
||||
|
||||
machine_int_t max_size = -1;
|
||||
mp_int_t max_size = -1;
|
||||
if (n_args > 1) {
|
||||
max_size = MP_OBJ_SMALL_INT_VALUE(args[1]);
|
||||
}
|
||||
@@ -190,7 +204,7 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory"));
|
||||
}
|
||||
|
||||
machine_int_t out_sz = o->type->stream_p->read(o, p, 1, &error);
|
||||
mp_int_t out_sz = o->type->stream_p->read(o, p, 1, &error);
|
||||
if (out_sz == -1) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error));
|
||||
}
|
||||
@@ -217,7 +231,7 @@ STATIC mp_obj_t stream_unbuffered_readlines(mp_obj_t self) {
|
||||
mp_obj_t lines = mp_obj_new_list(0, NULL);
|
||||
for (;;) {
|
||||
mp_obj_t line = stream_unbuffered_readline(1, &self);
|
||||
if (mp_obj_str_get_len(line) == 0) {
|
||||
if (!mp_obj_is_true(line)) {
|
||||
break;
|
||||
}
|
||||
mp_obj_list_append(lines, line);
|
||||
@@ -228,7 +242,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj, stream_unbuffered_
|
||||
|
||||
mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
|
||||
mp_obj_t l_in = stream_unbuffered_readline(1, &self);
|
||||
if (mp_obj_str_get_len(l_in) != 0) {
|
||||
if (mp_obj_is_true(l_in)) {
|
||||
return l_in;
|
||||
}
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
@@ -237,4 +251,4 @@ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write_method);
|
||||
|
||||
@@ -32,3 +32,5 @@ MP_DECLARE_CONST_FUN_OBJ(mp_stream_write_obj);
|
||||
|
||||
// Iterator which uses mp_stream_unbuffered_readline_obj
|
||||
mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self);
|
||||
|
||||
mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t len);
|
||||
|
||||
59
py/unicode.c
59
py/unicode.c
@@ -26,8 +26,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
|
||||
// attribute flags
|
||||
#define FL_PRINT (0x01)
|
||||
@@ -65,14 +65,65 @@ STATIC const uint8_t attr[] = {
|
||||
AT_LO, AT_LO, AT_LO, AT_PR, AT_PR, AT_PR, AT_PR, 0
|
||||
};
|
||||
|
||||
unichar utf8_get_char(const char *s) {
|
||||
// TODO: Rename to str_get_char
|
||||
unichar utf8_get_char(const byte *s) {
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
unichar ord = *s++;
|
||||
if (!UTF8_IS_NONASCII(ord)) return ord;
|
||||
ord &= 0x7F;
|
||||
for (unichar mask = 0x40; ord & mask; mask >>= 1) {
|
||||
ord &= ~mask;
|
||||
}
|
||||
while (UTF8_IS_CONT(*s)) {
|
||||
ord = (ord << 6) | (*s++ & 0x3F);
|
||||
}
|
||||
return ord;
|
||||
#else
|
||||
return *s;
|
||||
#endif
|
||||
}
|
||||
|
||||
char *utf8_next_char(const char *s) {
|
||||
return (char*)(s + 1);
|
||||
// TODO: Rename to str_next_char
|
||||
const byte *utf8_next_char(const byte *s) {
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
++s;
|
||||
while (UTF8_IS_CONT(*s)) {
|
||||
++s;
|
||||
}
|
||||
return s;
|
||||
#else
|
||||
return s + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
mp_uint_t utf8_ptr_to_index(const char *s, const char *ptr) {
|
||||
mp_uint_t i = 0;
|
||||
while (ptr > s) {
|
||||
if (!UTF8_IS_CONT(*--ptr)) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
// TODO: Rename to str_charlen
|
||||
mp_uint_t unichar_charlen(const char *str, mp_uint_t len)
|
||||
{
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
mp_uint_t charlen = 0;
|
||||
for (const char *top = str + len; str < top; ++str) {
|
||||
if (!UTF8_IS_CONT(*str)) {
|
||||
++charlen;
|
||||
}
|
||||
}
|
||||
return charlen;
|
||||
#else
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Be aware: These unichar_is* functions are actually ASCII-only!
|
||||
bool unichar_isspace(unichar c) {
|
||||
return c < 128 && (attr[c] & FL_SPACE) != 0;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user