Merge branch 'master' into nrf52

This commit is contained in:
Glenn Ruben Bakke 2017-02-19 19:02:29 +01:00
commit 05ec4f64e2
201 changed files with 2347 additions and 1225 deletions

3
.gitattributes vendored
View File

@ -10,11 +10,11 @@
*.png binary
*.jpg binary
*.dxf binary
*.mpy binary
# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text
tests/basics/string_crlf_conversion.py -text
stmhal/startup_stm32f40xx.s -text
stmhal/pybcdc.inf_template -text
stmhal/usbd_* -text
stmhal/boards/*/stm32f4xx_hal_conf.h -text
@ -28,4 +28,3 @@ cc3200/hal/des.c -text
cc3200/hal/i2s.c -text
cc3200/hal/i2s.h -text
cc3200/version.h -text
lib/fatfs/** -text

View File

@ -664,7 +664,7 @@ const mp_obj_type_t pyb_uart_type = {
.name = MP_QSTR_UART,
.print = pyb_uart_print,
.make_new = pyb_uart_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &uart_stream_p,
.locals_dict = (mp_obj_t)&pyb_uart_locals_dict,

View File

@ -103,7 +103,8 @@ Setup commands
.. method:: LCD160CR.set_power(on)
Turn the display on or off, depending on the given value.
Turn the display on or off, depending on the given value of `on`: 0 or `False`
will turn the display off, and 1 or `True` will turn it on.
.. method:: LCD160CR.set_orient(orient)

View File

@ -156,7 +156,22 @@ Constants
Classes
-------
.. toctree::
.. only:: not port_wipy
.. toctree::
:maxdepth: 1
machine.I2C.rst
machine.Pin.rst
machine.RTC.rst
machine.SPI.rst
machine.Timer.rst
machine.UART.rst
machine.WDT.rst
.. only:: port_wipy
.. toctree::
:maxdepth: 1
machine.ADC.rst

View File

@ -21,7 +21,7 @@ Usage Model:
CPU pins which correspond to the board pins are available
as ``pyb.cpu.Name``. For the CPU pins, the names are the port letter
followed by the pin number. On the PYBv1.0, ``pyb.Pin.board.X1`` and
``pyb.Pin.cpu.B6`` are the same pin.
``pyb.Pin.cpu.A0`` are the same pin.
You can also use strings::

View File

@ -116,10 +116,3 @@ Functions
Duplicate the terminal (the REPL) on the passed stream-like object.
The given object must at least implement the ``.read()`` and ``.write()`` methods.
Constants
---------
.. data:: sep
separation character used in paths

View File

@ -203,7 +203,7 @@ class LCD160CR:
#### SETUP COMMANDS ####
def set_power(self, on):
self.pwr(value)
self.pwr(on)
sleep_ms(15)
def set_orient(self, orient):

View File

@ -285,7 +285,7 @@ const mp_obj_type_t pyb_uart_type = {
.name = MP_QSTR_UART,
.print = pyb_uart_print,
.make_new = pyb_uart_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &uart_stream_p,
.locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict,

View File

@ -58,10 +58,9 @@ STATIC mp_obj_tuple_t os_uname_info_obj = {
};
STATIC mp_obj_t os_uname(void) {
if (os_uname_info_obj.items[2] == NULL) {
const char *ver = system_get_sdk_version();
os_uname_info_obj.items[2] = mp_obj_new_str(ver, strlen(ver), false);
}
// We must populate the "release" field each time in case it was GC'd since the last call.
const char *ver = system_get_sdk_version();
os_uname_info_obj.items[2] = mp_obj_new_str(ver, strlen(ver), false);
return (mp_obj_t)&os_uname_info_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);

View File

@ -11,7 +11,7 @@ Python statement which prints to the standard output.
Building the example
--------------------
Build the example is as simple as running:
Building the example is as simple as running:
make
@ -20,37 +20,38 @@ It's worth to trace what's happening behind the scenes though:
1. As a first step, a MicroPython library is built. This is handled by a
seperate makefile, Makefile.upylib. It is more or less complex, but the
good news is that you won't need to change anything in it, just use it
as is, the main Makefile shows how. What may need editing though is
MicroPython configuration file. MicroPython is highly configurable, so
as is, the main Makefile shows how. What may require editing though is
a MicroPython configuration file. MicroPython is highly configurable, so
you would need to build a library suiting your application well, while
not bloating its size. Check the options in the file "mpconfigport.h".
Included is a copy of "minimal" Unix port, which should be good start
for minimal embedding. For list of all available options, see py/mpconfig.h.
Included is a copy of the "minimal" Unix port, which should be a good start
for minimal embedding. For the list of all available options, see
py/mpconfig.h.
2. Once the library is built, your application is compiled and linked with
the MicroPython library produced in the previous step. The main Makefile
is very simple and shows that changes you would need to do to your
application's Makefile (or other build configuration) are also simple:
2. Once the MicroPython library is built, your application is compiled
and linked it. The main Makefile is very simple and shows that the changes
you would need to do to your application's Makefile (or other build
configuration) are also simple:
a) You would need to use C99 standard (you're using 15+ years old standard
already, not a 25+ years old one, right?).
a) You would need to use C99 standard (you're using this 15+ years old
standard already, not a 25+ years old one, right?).
b) You need to provide path to MicroPython's top-level dir, for includes.
b) You need to provide a path to MicroPython's top-level dir, for includes.
c) You need to include -DNO_QSTR compile-time flag.
d) Otherwise, just link with micropython library produced in step 1.
d) Otherwise, just link with the MicroPython library produced in step 1.
Out of tree build
-----------------
This example set up to work out of the box, being part of the MicroPython
This example is set up to work out of the box, being part of the MicroPython
tree. Your application of course will be outside of its tree, but the
only thing you need to do is to pass MPTOP variable pointing to
MicroPython directory to both Makefiles (in this example, the main Makefile
automatically pass it to Makefile.upylib; in your own Makefile, don't forget
to use suitable value).
automatically passes it to Makefile.upylib; in your own Makefile, don't forget
to use a suitable value).
A practical way to embed MicroPython in your application is to include it
as a git submodule. Suppose you included it as libs/micropython. Then in

View File

@ -1,4 +1,4 @@
from machine import Pin
from machine import Pin, Signal
# 96Boards/Qualcomm DragonBoard 410c
#

View File

@ -0,0 +1,13 @@
from machine import Pin, Signal
# Red LED on pin LED_RED also kown as A13
LED = Signal(Pin('LED_RED', Pin.OUT))
# Green LED on pin LED_GREEN also known as A14
LED2 = Signal(Pin('LED_GREEN', Pin.OUT))
# Yellow LED on pin LED_YELLOW also known as A15
LED3 = Signal(Pin('LED_YELLOW', Pin.OUT))
# Blue LED on pin LED_BLUE also known as B4
LED4 = Signal(Pin('LED_BLUE', Pin.OUT))

View File

@ -1,4 +1,4 @@
from machine import Pin
from machine import Pin, Signal
# Freescale/NXP FRDM-K64F board
# Blue LED on port B, pin 21

View File

@ -14,10 +14,10 @@ def pwm_cycle(led, duty, cycles):
duty_off = 20 - duty
for i in range(cycles):
if duty:
led.value(1)
led.on()
utime.sleep_ms(duty)
if duty_off:
led.value(0)
led.off()
utime.sleep_ms(duty_off)

View File

@ -92,8 +92,22 @@ STATIC mp_obj_t signal_value(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(signal_value_obj, 1, 2, signal_value);
STATIC mp_obj_t signal_on(mp_obj_t self_in) {
mp_virtual_pin_write(self_in, 1);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(signal_on_obj, signal_on);
STATIC mp_obj_t signal_off(mp_obj_t self_in) {
mp_virtual_pin_write(self_in, 0);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(signal_off_obj, signal_off);
STATIC const mp_rom_map_elem_t signal_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&signal_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&signal_on_obj) },
{ MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&signal_off_obj) },
};
STATIC MP_DEFINE_CONST_DICT(signal_locals_dict, signal_locals_dict_table);

View File

@ -184,7 +184,8 @@ STATIC mp_obj_t btree_items(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_items_obj, 1, 4, btree_items);
STATIC mp_obj_t btree_getiter(mp_obj_t self_in) {
STATIC mp_obj_t btree_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
(void)iter_buf;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
if (self->next_flags != 0) {
// If we're called immediately after keys(), values(), or items(),

View File

@ -1,10 +1,11 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Galen Hazelwood
* Copyright (c) 2015-2016 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

View File

@ -132,11 +132,24 @@ mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
mp_uint_t mnt_len;
const char *mnt_str = mp_obj_str_get_data(pos_args[1], &mnt_len);
// see if we need to auto-detect and create the filesystem
mp_obj_t vfs_obj = pos_args[0];
mp_obj_t dest[2];
mp_load_method_maybe(vfs_obj, MP_QSTR_mount, dest);
if (dest[0] == MP_OBJ_NULL) {
// Input object has no mount method, assume it's a block device and try to
// auto-detect the filesystem and create the corresponding VFS entity.
// (At the moment we only support FAT filesystems.)
#if MICROPY_VFS_FAT
vfs_obj = mp_fat_vfs_type.make_new(&mp_fat_vfs_type, 1, 0, &vfs_obj);
#endif
}
// create new object
mp_vfs_mount_t *vfs = m_new_obj(mp_vfs_mount_t);
vfs->str = mnt_str;
vfs->len = mnt_len;
vfs->obj = pos_args[0];
vfs->obj = vfs_obj;
vfs->next = NULL;
// call the underlying object to do any mounting operation
@ -262,6 +275,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj, 0, 1, mp_vfs_listdir);
mp_obj_t mp_vfs_mkdir(mp_obj_t path_in) {
mp_obj_t path_out;
mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out);
if (vfs == MP_VFS_ROOT || (vfs != MP_VFS_NONE && !strcmp(mp_obj_str_get_str(path_out), "/"))) {
mp_raise_OSError(MP_EEXIST);
}
return mp_vfs_proxy_call(vfs, MP_QSTR_mkdir, 1, &path_out);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_mkdir_obj, mp_vfs_mkdir);
@ -295,6 +311,14 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_rmdir_obj, mp_vfs_rmdir);
mp_obj_t mp_vfs_stat(mp_obj_t path_in) {
mp_obj_t path_out;
mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out);
if (vfs == MP_VFS_ROOT) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
t->items[0] = MP_OBJ_NEW_SMALL_INT(0x4000); // st_mode = stat.S_IFDIR
for (int i = 1; i <= 9; ++i) {
t->items[i] = MP_OBJ_NEW_SMALL_INT(0); // dev, nlink, uid, gid, size, atime, mtime, ctime
}
return MP_OBJ_FROM_PTR(t);
}
return mp_vfs_proxy_call(vfs, MP_QSTR_stat, 1, &path_out);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_stat_obj, mp_vfs_stat);

View File

@ -264,7 +264,7 @@ const mp_obj_type_t mp_type_fileio = {
.name = MP_QSTR_FileIO,
.print = file_obj_print,
.make_new = file_obj_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &fileio_stream_p,
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
@ -283,7 +283,7 @@ const mp_obj_type_t mp_type_textio = {
.name = MP_QSTR_TextIOWrapper,
.print = file_obj_print,
.make_new = file_obj_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &textio_stream_p,
.locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,

Binary file not shown.

View File

@ -73,11 +73,11 @@
// macros for encoding instructions (little endian versions)
#define ASM_XTENSA_ENCODE_RRR(op0, op1, op2, r, s, t) \
(((op2) << 20) | ((op1) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))
((((uint32_t)op2) << 20) | (((uint32_t)op1) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))
#define ASM_XTENSA_ENCODE_RRI4(op0, op1, r, s, t, imm4) \
(((imm4) << 20) | ((op1) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))
#define ASM_XTENSA_ENCODE_RRI8(op0, r, s, t, imm8) \
(((imm8) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))
((((uint32_t)imm8) << 16) | ((r) << 12) | ((s) << 8) | ((t) << 4) | (op0))
#define ASM_XTENSA_ENCODE_RI16(op0, t, imm16) \
(((imm16) << 8) | ((t) << 4) | (op0))
#define ASM_XTENSA_ENCODE_RSR(op0, op1, op2, rs, t) \
@ -85,7 +85,7 @@
#define ASM_XTENSA_ENCODE_CALL(op0, n, offset) \
(((offset) << 6) | ((n) << 4) | (op0))
#define ASM_XTENSA_ENCODE_CALLX(op0, op1, op2, r, s, m, n) \
(((op2) << 20) | ((op1) << 16) | ((r) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0))
((((uint32_t)op2) << 20) | (((uint32_t)op1) << 16) | ((r) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0))
#define ASM_XTENSA_ENCODE_BRI8(op0, r, s, m, n, imm8) \
(((imm8) << 16) | ((r) << 12) | ((s) << 8) | ((m) << 6) | ((n) << 4) | (op0))
#define ASM_XTENSA_ENCODE_BRI12(op0, s, m, n, imm12) \

View File

@ -79,6 +79,7 @@
#define MP_BC_POP_BLOCK (0x44)
#define MP_BC_POP_EXCEPT (0x45)
#define MP_BC_UNWIND_JUMP (0x46) // rel byte code offset, 16-bit signed, in excess; then a byte
#define MP_BC_GET_ITER_STACK (0x47)
#define MP_BC_BUILD_TUPLE (0x50) // uint
#define MP_BC_BUILD_LIST (0x51) // uint

View File

@ -41,13 +41,21 @@
// TODO need to mangle __attr names
typedef enum {
// define rules with a compile function
#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
PN_maximum_number_of,
#undef DEF_RULE_NC
PN_string, // special node for non-interned string
PN_bytes, // special node for non-interned bytes
PN_const_object, // special node for a constant, generic Python object
// define rules without a compile function
#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) PN_##rule,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
} pn_kind_t;
#define NEED_METHOD_TABLE MICROPY_EMIT_NATIVE
@ -1475,7 +1483,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
uint pop_label = comp_next_label(comp);
compile_node(comp, pns->nodes[1]); // iterator
EMIT(get_iter);
EMIT_ARG(get_iter, true);
EMIT_ARG(label_assign, continue_label);
EMIT_ARG(for_iter, pop_label);
c_assign(comp, pns->nodes[0], ASSIGN_STORE); // variable
@ -1680,7 +1688,7 @@ STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
STATIC void compile_yield_from(compiler_t *comp) {
EMIT(get_iter);
EMIT_ARG(get_iter, false);
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
EMIT(yield_from);
}
@ -2293,65 +2301,6 @@ STATIC void compile_atom_expr_trailers(compiler_t *comp, mp_parse_node_struct_t
}
}
STATIC void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
// a list of strings
// check type of list (string or bytes) and count total number of bytes
int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
size_t n_bytes = 0;
int string_kind = MP_PARSE_NODE_NULL;
for (int i = 0; i < n; i++) {
int pn_kind;
if (MP_PARSE_NODE_IS_LEAF(pns->nodes[i])) {
pn_kind = MP_PARSE_NODE_LEAF_KIND(pns->nodes[i]);
assert(pn_kind == MP_PARSE_NODE_STRING || pn_kind == MP_PARSE_NODE_BYTES);
n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
} else {
assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[i]));
mp_parse_node_struct_t *pns_string = (mp_parse_node_struct_t*)pns->nodes[i];
if (MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_string) {
pn_kind = MP_PARSE_NODE_STRING;
} else {
assert(MP_PARSE_NODE_STRUCT_KIND(pns_string) == PN_bytes);
pn_kind = MP_PARSE_NODE_BYTES;
}
n_bytes += pns_string->nodes[1];
}
if (i == 0) {
string_kind = pn_kind;
} else if (pn_kind != string_kind) {
compile_syntax_error(comp, (mp_parse_node_t)pns, "cannot mix bytes and nonbytes literals");
return;
}
}
// if we are not in the last pass, just load a dummy object
if (comp->pass != MP_PASS_EMIT) {
EMIT_ARG(load_const_obj, mp_const_none);
return;
}
// concatenate string/bytes
vstr_t vstr;
vstr_init_len(&vstr, n_bytes);
byte *s_dest = (byte*)vstr.buf;
for (int i = 0; i < n; i++) {
if (MP_PARSE_NODE_IS_LEAF(pns->nodes[i])) {
size_t s_len;
const byte *s = qstr_data(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]), &s_len);
memcpy(s_dest, s, s_len);
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], pns_string->nodes[1]);
s_dest += pns_string->nodes[1];
}
}
// load the object
EMIT_ARG(load_const_obj, mp_obj_new_str_from_vstr(string_kind == MP_PARSE_NODE_STRING ? &mp_type_str : &mp_type_bytes, &vstr));
}
// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
@ -2372,7 +2321,9 @@ STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns,
close_over_variables_etc(comp, this_scope, 0, 0);
compile_node(comp, pns_comp_for->nodes[1]); // source of the iterator
EMIT(get_iter);
if (kind == SCOPE_GEN_EXPR) {
EMIT_ARG(get_iter, false);
}
EMIT_ARG(call_function, 1, 0, 0);
}
@ -2678,14 +2629,14 @@ STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns)
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
STATIC const compile_function_t compile_function[] = {
#define nc NULL
// only define rules with a compile function
#define c(f) compile_##f
#define DEF_RULE(rule, comp, kind, ...) comp,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef nc
#undef c
#undef DEF_RULE
NULL,
#undef DEF_RULE_NC
compile_string,
compile_bytes,
compile_const_object,
@ -2741,8 +2692,8 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) {
} else {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
EMIT_ARG(set_source_line, pns->source_line);
assert(MP_PARSE_NODE_STRUCT_KIND(pns) <= PN_const_object);
compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
assert(f != NULL);
f(comp, pns);
}
}
@ -2887,7 +2838,7 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn
EMIT(yield_value);
EMIT(pop_top);
} else {
EMIT_ARG(store_comp, comp->scope_cur->kind, for_depth + 2);
EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5);
}
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
// if condition
@ -2900,7 +2851,7 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn
// for loop
mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
compile_node(comp, pns_comp_for2->nodes[1]);
EMIT(get_iter);
EMIT_ARG(get_iter, true);
compile_scope_comp_iter(comp, pns_comp_for2, pn_inner_expr, for_depth + 1);
}
@ -3070,7 +3021,18 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
#endif
}
compile_load_id(comp, qstr_arg);
// There are 4 slots on the stack for the iterator, and the first one is
// NULL to indicate that the second one points to the iterator object.
if (scope->kind == SCOPE_GEN_EXPR) {
EMIT(load_null);
compile_load_id(comp, qstr_arg);
EMIT(load_null);
EMIT(load_null);
} else {
compile_load_id(comp, qstr_arg);
EMIT_ARG(get_iter, true);
}
compile_scope_comp_iter(comp, pns_comp_for, pns->nodes[0], 0);
if (scope->kind == SCOPE_GEN_EXPR) {

View File

@ -110,7 +110,7 @@ typedef struct _emit_method_table_t {
void (*setup_except)(emit_t *emit, mp_uint_t label);
void (*setup_finally)(emit_t *emit, mp_uint_t label);
void (*end_finally)(emit_t *emit);
void (*get_iter)(emit_t *emit);
void (*get_iter)(emit_t *emit, bool use_stack);
void (*for_iter)(emit_t *emit, mp_uint_t label);
void (*for_iter_end)(emit_t *emit);
void (*pop_block)(emit_t *emit);
@ -228,7 +228,7 @@ void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label);
void mp_emit_bc_setup_except(emit_t *emit, mp_uint_t label);
void mp_emit_bc_setup_finally(emit_t *emit, mp_uint_t label);
void mp_emit_bc_end_finally(emit_t *emit);
void mp_emit_bc_get_iter(emit_t *emit);
void mp_emit_bc_get_iter(emit_t *emit, bool use_stack);
void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label);
void mp_emit_bc_for_iter_end(emit_t *emit);
void mp_emit_bc_pop_block(emit_t *emit);

View File

@ -144,10 +144,15 @@ STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_sk
//printf(" %d %d\n", bytes_to_skip, lines_to_skip);
while (bytes_to_skip > 0 || lines_to_skip > 0) {
mp_uint_t b, l;
if (lines_to_skip <= 6) {
if (lines_to_skip <= 6 || bytes_to_skip > 0xf) {
// use 0b0LLBBBBB encoding
b = MIN(bytes_to_skip, 0x1f);
l = MIN(lines_to_skip, 0x3);
if (b < bytes_to_skip) {
// we can't skip any lines until we skip all the bytes
l = 0;
} else {
l = MIN(lines_to_skip, 0x3);
}
*emit_get_cur_to_write_code_info(emit, 1) = b | (l << 5);
} else {
// use 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte)
@ -729,6 +734,10 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept
if (label & MP_EMIT_BREAK_FROM_FOR) {
// need to pop the iterator if we are breaking out of a for loop
emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
// also pop the iter_buf
for (size_t i = 0; i < sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1; ++i) {
emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
}
}
emit_write_bytecode_byte_signed_label(emit, MP_BC_JUMP, label & ~MP_EMIT_BREAK_FROM_FOR);
} else {
@ -768,9 +777,9 @@ void mp_emit_bc_end_finally(emit_t *emit) {
emit_write_bytecode_byte(emit, MP_BC_END_FINALLY);
}
void mp_emit_bc_get_iter(emit_t *emit) {
emit_bc_pre(emit, 0);
emit_write_bytecode_byte(emit, MP_BC_GET_ITER);
void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) {
emit_bc_pre(emit, use_stack ? sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1 : 0);
emit_write_bytecode_byte(emit, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER);
}
void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
@ -779,7 +788,7 @@ void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
}
void mp_emit_bc_for_iter_end(emit_t *emit) {
emit_bc_pre(emit, -1);
emit_bc_pre(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)));
}
void mp_emit_bc_pop_block(emit_t *emit) {

View File

@ -36,10 +36,21 @@
#if MICROPY_EMIT_INLINE_THUMB
typedef enum {
// define rules with a compile function
#define DEF_RULE(rule, comp, kind, ...) PN_##rule,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
PN_maximum_number_of,
#undef DEF_RULE_NC
PN_string, // special node for non-interned string
PN_bytes, // special node for non-interned bytes
PN_const_object, // special node for a constant, generic Python object
// define rules without a compile function
#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) PN_##rule,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
} pn_kind_t;
struct _emit_inline_asm_t {

View File

@ -105,8 +105,8 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
[MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3,
[MP_F_CALL_METHOD_N_KW] = 3,
[MP_F_CALL_METHOD_N_KW_VAR] = 3,
[MP_F_GETITER] = 1,
[MP_F_ITERNEXT] = 1,
[MP_F_NATIVE_GETITER] = 2,
[MP_F_NATIVE_ITERNEXT] = 1,
[MP_F_NLR_PUSH] = 1,
[MP_F_NLR_POP] = 0,
[MP_F_NATIVE_RAISE] = 1,
@ -1799,23 +1799,29 @@ STATIC void emit_native_end_finally(emit_t *emit) {
emit_post(emit);
}
STATIC void emit_native_get_iter(emit_t *emit) {
STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {
// perhaps the difficult one, as we want to rewrite for loops using native code
// in cases where we iterate over a Python object, can we use normal runtime calls?
vtype_kind_t vtype;
emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
assert(vtype == VTYPE_PYOBJ);
emit_call(emit, MP_F_GETITER);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
if (use_stack) {
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t));
emit_call(emit, MP_F_NATIVE_GETITER);
} else {
// mp_getiter will allocate the iter_buf on the heap
ASM_MOV_IMM_TO_REG(emit->as, 0, REG_ARG_2);
emit_call(emit, MP_F_NATIVE_GETITER);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
}
STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
emit_native_pre(emit);
vtype_kind_t vtype;
emit_access_stack(emit, 1, &vtype, REG_ARG_1);
assert(vtype == VTYPE_PYOBJ);
emit_call(emit, MP_F_ITERNEXT);
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t));
adjust_stack(emit, 4);
emit_call(emit, MP_F_NATIVE_ITERNEXT);
ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label);
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
@ -1824,7 +1830,7 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
STATIC void emit_native_for_iter_end(emit_t *emit) {
// adjust stack counter (we get here from for_iter ending, which popped the value for us)
emit_native_pre(emit);
adjust_stack(emit, -1);
adjust_stack(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)));
emit_post(emit);
}

View File

@ -37,12 +37,12 @@
// file_input: (NEWLINE | stmt)* ENDMARKER
// eval_input: testlist NEWLINE* ENDMARKER
DEF_RULE(single_input, nc, or(3), tok(NEWLINE), rule(simple_stmt), rule(compound_stmt))
DEF_RULE_NC(single_input, or(3), tok(NEWLINE), rule(simple_stmt), rule(compound_stmt))
DEF_RULE(file_input, c(generic_all_nodes), and_ident(1), opt_rule(file_input_2))
DEF_RULE(file_input_2, c(generic_all_nodes), one_or_more, rule(file_input_3))
DEF_RULE(file_input_3, nc, or(2), tok(NEWLINE), rule(stmt))
DEF_RULE(eval_input, nc, and_ident(2), rule(testlist), opt_rule(eval_input_2))
DEF_RULE(eval_input_2, nc, and(1), tok(NEWLINE))
DEF_RULE_NC(file_input_3, or(2), tok(NEWLINE), rule(stmt))
DEF_RULE_NC(eval_input, and_ident(2), rule(testlist), opt_rule(eval_input_2))
DEF_RULE_NC(eval_input_2, and(1), tok(NEWLINE))
// decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
// decorators: decorator+
@ -55,42 +55,42 @@ DEF_RULE(eval_input_2, nc, and(1), tok(NEWLINE))
// varargslist: vfpdef ['=' test] (',' vfpdef ['=' test])* [',' ['*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef]] | '*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef
// vfpdef: NAME
DEF_RULE(decorator, nc, and(4), tok(DEL_AT), rule(dotted_name), opt_rule(trailer_paren), tok(NEWLINE))
DEF_RULE(decorators, nc, one_or_more, rule(decorator))
DEF_RULE_NC(decorator, and(4), tok(DEL_AT), rule(dotted_name), opt_rule(trailer_paren), tok(NEWLINE))
DEF_RULE_NC(decorators, one_or_more, rule(decorator))
DEF_RULE(decorated, c(decorated), and_ident(2), rule(decorators), rule(decorated_body))
#if MICROPY_PY_ASYNC_AWAIT
DEF_RULE(decorated_body, nc, or(3), rule(classdef), rule(funcdef), rule(async_funcdef))
DEF_RULE(async_funcdef, nc, and(2), tok(KW_ASYNC), rule(funcdef))
DEF_RULE_NC(decorated_body, or(3), rule(classdef), rule(funcdef), rule(async_funcdef))
DEF_RULE_NC(async_funcdef, and(2), tok(KW_ASYNC), rule(funcdef))
#else
DEF_RULE(decorated_body, nc, or(2), rule(classdef), rule(funcdef))
DEF_RULE_NC(decorated_body, or(2), rule(classdef), rule(funcdef))
#endif
DEF_RULE(funcdef, c(funcdef), and_blank(8), tok(KW_DEF), tok(NAME), tok(DEL_PAREN_OPEN), opt_rule(typedargslist), tok(DEL_PAREN_CLOSE), opt_rule(funcdefrettype), tok(DEL_COLON), rule(suite))
DEF_RULE(funcdefrettype, nc, and_ident(2), tok(DEL_MINUS_MORE), rule(test))
DEF_RULE_NC(funcdefrettype, and_ident(2), tok(DEL_MINUS_MORE), rule(test))
// note: typedargslist lets through more than is allowed, compiler does further checks
DEF_RULE(typedargslist, nc, list_with_end, rule(typedargslist_item), tok(DEL_COMMA))
DEF_RULE(typedargslist_item, nc, or(3), rule(typedargslist_name), rule(typedargslist_star), rule(typedargslist_dbl_star))
DEF_RULE(typedargslist_name, nc, and_ident(3), tok(NAME), opt_rule(typedargslist_colon), opt_rule(typedargslist_equal))
DEF_RULE(typedargslist_star, nc, and(2), tok(OP_STAR), opt_rule(tfpdef))
DEF_RULE(typedargslist_dbl_star, nc, and(3), tok(OP_DBL_STAR), tok(NAME), opt_rule(typedargslist_colon))
DEF_RULE(typedargslist_colon, nc, and_ident(2), tok(DEL_COLON), rule(test))
DEF_RULE(typedargslist_equal, nc, and_ident(2), tok(DEL_EQUAL), rule(test))
DEF_RULE(tfpdef, nc, and(2), tok(NAME), opt_rule(typedargslist_colon))
DEF_RULE_NC(typedargslist, list_with_end, rule(typedargslist_item), tok(DEL_COMMA))
DEF_RULE_NC(typedargslist_item, or(3), rule(typedargslist_name), rule(typedargslist_star), rule(typedargslist_dbl_star))
DEF_RULE_NC(typedargslist_name, and_ident(3), tok(NAME), opt_rule(typedargslist_colon), opt_rule(typedargslist_equal))
DEF_RULE_NC(typedargslist_star, and(2), tok(OP_STAR), opt_rule(tfpdef))
DEF_RULE_NC(typedargslist_dbl_star, and(3), tok(OP_DBL_STAR), tok(NAME), opt_rule(typedargslist_colon))
DEF_RULE_NC(typedargslist_colon, and_ident(2), tok(DEL_COLON), rule(test))
DEF_RULE_NC(typedargslist_equal, and_ident(2), tok(DEL_EQUAL), rule(test))
DEF_RULE_NC(tfpdef, and(2), tok(NAME), opt_rule(typedargslist_colon))
// note: varargslist lets through more than is allowed, compiler does further checks
DEF_RULE(varargslist, nc, list_with_end, rule(varargslist_item), tok(DEL_COMMA))
DEF_RULE(varargslist_item, nc, or(3), rule(varargslist_name), rule(varargslist_star), rule(varargslist_dbl_star))
DEF_RULE(varargslist_name, nc, and_ident(2), tok(NAME), opt_rule(varargslist_equal))
DEF_RULE(varargslist_star, nc, and(2), tok(OP_STAR), opt_rule(vfpdef))
DEF_RULE(varargslist_dbl_star, nc, and(2), tok(OP_DBL_STAR), tok(NAME))
DEF_RULE(varargslist_equal, nc, and_ident(2), tok(DEL_EQUAL), rule(test))
DEF_RULE(vfpdef, nc, and_ident(1), tok(NAME))
DEF_RULE_NC(varargslist, list_with_end, rule(varargslist_item), tok(DEL_COMMA))
DEF_RULE_NC(varargslist_item, or(3), rule(varargslist_name), rule(varargslist_star), rule(varargslist_dbl_star))
DEF_RULE_NC(varargslist_name, and_ident(2), tok(NAME), opt_rule(varargslist_equal))
DEF_RULE_NC(varargslist_star, and(2), tok(OP_STAR), opt_rule(vfpdef))
DEF_RULE_NC(varargslist_dbl_star, and(2), tok(OP_DBL_STAR), tok(NAME))
DEF_RULE_NC(varargslist_equal, and_ident(2), tok(DEL_EQUAL), rule(test))
DEF_RULE_NC(vfpdef, and_ident(1), tok(NAME))
// stmt: compound_stmt | simple_stmt
DEF_RULE(stmt, nc, or(2), rule(compound_stmt), rule(simple_stmt))
DEF_RULE_NC(stmt, or(2), rule(compound_stmt), rule(simple_stmt))
// simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
DEF_RULE(simple_stmt, nc, and_ident(2), rule(simple_stmt_2), tok(NEWLINE))
DEF_RULE_NC(simple_stmt, and_ident(2), rule(simple_stmt_2), tok(NEWLINE))
DEF_RULE(simple_stmt_2, c(generic_all_nodes), list_with_end, rule(small_stmt), tok(DEL_SEMICOLON))
// small_stmt: expr_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | nonlocal_stmt | assert_stmt
@ -99,16 +99,16 @@ DEF_RULE(simple_stmt_2, c(generic_all_nodes), list_with_end, rule(small_stmt), t
// augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//='
// # For normal assignments, additional restrictions enforced by the interpreter
DEF_RULE(small_stmt, nc, or(8), rule(del_stmt), rule(pass_stmt), rule(flow_stmt), rule(import_stmt), rule(global_stmt), rule(nonlocal_stmt), rule(assert_stmt), rule(expr_stmt))
DEF_RULE_NC(small_stmt, or(8), rule(del_stmt), rule(pass_stmt), rule(flow_stmt), rule(import_stmt), rule(global_stmt), rule(nonlocal_stmt), rule(assert_stmt), rule(expr_stmt))
DEF_RULE(expr_stmt, c(expr_stmt), and(2), rule(testlist_star_expr), opt_rule(expr_stmt_2))
DEF_RULE(expr_stmt_2, nc, or(2), rule(expr_stmt_augassign), rule(expr_stmt_assign_list))
DEF_RULE(expr_stmt_augassign, nc, and_ident(2), rule(augassign), rule(expr_stmt_6))
DEF_RULE(expr_stmt_assign_list, nc, one_or_more, rule(expr_stmt_assign))
DEF_RULE(expr_stmt_assign, nc, and_ident(2), tok(DEL_EQUAL), rule(expr_stmt_6))
DEF_RULE(expr_stmt_6, nc, or(2), rule(yield_expr), rule(testlist_star_expr))
DEF_RULE_NC(expr_stmt_2, or(2), rule(expr_stmt_augassign), rule(expr_stmt_assign_list))
DEF_RULE_NC(expr_stmt_augassign, and_ident(2), rule(augassign), rule(expr_stmt_6))
DEF_RULE_NC(expr_stmt_assign_list, one_or_more, rule(expr_stmt_assign))
DEF_RULE_NC(expr_stmt_assign, and_ident(2), tok(DEL_EQUAL), rule(expr_stmt_6))
DEF_RULE_NC(expr_stmt_6, or(2), rule(yield_expr), rule(testlist_star_expr))
DEF_RULE(testlist_star_expr, c(generic_tuple), list_with_end, rule(testlist_star_expr_2), tok(DEL_COMMA))
DEF_RULE(testlist_star_expr_2, nc, or(2), rule(star_expr), rule(test))
DEF_RULE(augassign, nc, or(12), tok(DEL_PLUS_EQUAL), tok(DEL_MINUS_EQUAL), tok(DEL_STAR_EQUAL), tok(DEL_SLASH_EQUAL), tok(DEL_PERCENT_EQUAL), tok(DEL_AMPERSAND_EQUAL), tok(DEL_PIPE_EQUAL), tok(DEL_CARET_EQUAL), tok(DEL_DBL_LESS_EQUAL), tok(DEL_DBL_MORE_EQUAL), tok(DEL_DBL_STAR_EQUAL), tok(DEL_DBL_SLASH_EQUAL))
DEF_RULE_NC(testlist_star_expr_2, or(2), rule(star_expr), rule(test))
DEF_RULE_NC(augassign, or(12), tok(DEL_PLUS_EQUAL), tok(DEL_MINUS_EQUAL), tok(DEL_STAR_EQUAL), tok(DEL_SLASH_EQUAL), tok(DEL_PERCENT_EQUAL), tok(DEL_AMPERSAND_EQUAL), tok(DEL_PIPE_EQUAL), tok(DEL_CARET_EQUAL), tok(DEL_DBL_LESS_EQUAL), tok(DEL_DBL_MORE_EQUAL), tok(DEL_DBL_STAR_EQUAL), tok(DEL_DBL_SLASH_EQUAL))
// del_stmt: 'del' exprlist
// pass_stmt: 'pass'
@ -121,14 +121,14 @@ DEF_RULE(augassign, nc, or(12), tok(DEL_PLUS_EQUAL), tok(DEL_MINUS_EQUAL), tok(D
DEF_RULE(del_stmt, c(del_stmt), and(2), tok(KW_DEL), rule(exprlist))
DEF_RULE(pass_stmt, c(generic_all_nodes), and(1), tok(KW_PASS))
DEF_RULE(flow_stmt, nc, or(5), rule(break_stmt), rule(continue_stmt), rule(return_stmt), rule(raise_stmt), rule(yield_stmt))
DEF_RULE_NC(flow_stmt, or(5), rule(break_stmt), rule(continue_stmt), rule(return_stmt), rule(raise_stmt), rule(yield_stmt))
DEF_RULE(break_stmt, c(break_stmt), and(1), tok(KW_BREAK))
DEF_RULE(continue_stmt, c(continue_stmt), and(1), tok(KW_CONTINUE))
DEF_RULE(return_stmt, c(return_stmt), and(2), tok(KW_RETURN), opt_rule(testlist))
DEF_RULE(yield_stmt, c(yield_stmt), and(1), rule(yield_expr))
DEF_RULE(raise_stmt, c(raise_stmt), and(2), tok(KW_RAISE), opt_rule(raise_stmt_arg))
DEF_RULE(raise_stmt_arg, nc, and_ident(2), rule(test), opt_rule(raise_stmt_from))
DEF_RULE(raise_stmt_from, nc, and_ident(2), tok(KW_FROM), rule(test))
DEF_RULE_NC(raise_stmt_arg, and_ident(2), rule(test), opt_rule(raise_stmt_from))
DEF_RULE_NC(raise_stmt_from, and_ident(2), tok(KW_FROM), rule(test))
// import_stmt: import_name | import_from
// import_name: 'import' dotted_as_names
@ -142,26 +142,26 @@ DEF_RULE(raise_stmt_from, nc, and_ident(2), tok(KW_FROM), rule(test))
// nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
// assert_stmt: 'assert' test [',' test]
DEF_RULE(import_stmt, nc, or(2), rule(import_name), rule(import_from))
DEF_RULE_NC(import_stmt, or(2), rule(import_name), rule(import_from))
DEF_RULE(import_name, c(import_name), and(2), tok(KW_IMPORT), rule(dotted_as_names))
DEF_RULE(import_from, c(import_from), and(4), tok(KW_FROM), rule(import_from_2), tok(KW_IMPORT), rule(import_from_3))
DEF_RULE(import_from_2, nc, or(2), rule(dotted_name), rule(import_from_2b))
DEF_RULE(import_from_2b, nc, and_ident(2), rule(one_or_more_period_or_ellipsis), opt_rule(dotted_name))
DEF_RULE(import_from_3, nc, or(3), tok(OP_STAR), rule(import_as_names_paren), rule(import_as_names))
DEF_RULE(import_as_names_paren, nc, and_ident(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE))
DEF_RULE(one_or_more_period_or_ellipsis, nc, one_or_more, rule(period_or_ellipsis))
DEF_RULE(period_or_ellipsis, nc, or(2), tok(DEL_PERIOD), tok(ELLIPSIS))
DEF_RULE(import_as_name, nc, and(2), tok(NAME), opt_rule(as_name))
DEF_RULE(dotted_as_name, nc, and_ident(2), rule(dotted_name), opt_rule(as_name))
DEF_RULE(as_name, nc, and_ident(2), tok(KW_AS), tok(NAME))
DEF_RULE(import_as_names, nc, list_with_end, rule(import_as_name), tok(DEL_COMMA))
DEF_RULE(dotted_as_names, nc, list, rule(dotted_as_name), tok(DEL_COMMA))
DEF_RULE(dotted_name, nc, list, tok(NAME), tok(DEL_PERIOD))
DEF_RULE_NC(import_from_2, or(2), rule(dotted_name), rule(import_from_2b))
DEF_RULE_NC(import_from_2b, and_ident(2), rule(one_or_more_period_or_ellipsis), opt_rule(dotted_name))
DEF_RULE_NC(import_from_3, or(3), tok(OP_STAR), rule(import_as_names_paren), rule(import_as_names))
DEF_RULE_NC(import_as_names_paren, and_ident(3), tok(DEL_PAREN_OPEN), rule(import_as_names), tok(DEL_PAREN_CLOSE))
DEF_RULE_NC(one_or_more_period_or_ellipsis, one_or_more, rule(period_or_ellipsis))
DEF_RULE_NC(period_or_ellipsis, or(2), tok(DEL_PERIOD), tok(ELLIPSIS))
DEF_RULE_NC(import_as_name, and(2), tok(NAME), opt_rule(as_name))
DEF_RULE_NC(dotted_as_name, and_ident(2), rule(dotted_name), opt_rule(as_name))
DEF_RULE_NC(as_name, and_ident(2), tok(KW_AS), tok(NAME))
DEF_RULE_NC(import_as_names, list_with_end, rule(import_as_name), tok(DEL_COMMA))
DEF_RULE_NC(dotted_as_names, list, rule(dotted_as_name), tok(DEL_COMMA))
DEF_RULE_NC(dotted_name, list, tok(NAME), tok(DEL_PERIOD))
DEF_RULE(global_stmt, c(global_stmt), and(2), tok(KW_GLOBAL), rule(name_list))
DEF_RULE(nonlocal_stmt, c(nonlocal_stmt), and(2), tok(KW_NONLOCAL), rule(name_list))
DEF_RULE(name_list, nc, list, tok(NAME), tok(DEL_COMMA))
DEF_RULE_NC(name_list, list, tok(NAME), tok(DEL_COMMA))
DEF_RULE(assert_stmt, c(assert_stmt), and(3), tok(KW_ASSERT), rule(test), opt_rule(assert_stmt_extra))
DEF_RULE(assert_stmt_extra, nc, and_ident(2), tok(DEL_COMMA), rule(test))
DEF_RULE_NC(assert_stmt_extra, and_ident(2), tok(DEL_COMMA), rule(test))
// compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt
// if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
@ -176,31 +176,31 @@ DEF_RULE(assert_stmt_extra, nc, and_ident(2), tok(DEL_COMMA), rule(test))
// async_stmt: 'async' (funcdef | with_stmt | for_stmt)
#if MICROPY_PY_ASYNC_AWAIT
DEF_RULE(compound_stmt, nc, or(9), rule(if_stmt), rule(while_stmt), rule(for_stmt), rule(try_stmt), rule(with_stmt), rule(funcdef), rule(classdef), rule(decorated), rule(async_stmt))
DEF_RULE_NC(compound_stmt, or(9), rule(if_stmt), rule(while_stmt), rule(for_stmt), rule(try_stmt), rule(with_stmt), rule(funcdef), rule(classdef), rule(decorated), rule(async_stmt))
DEF_RULE(async_stmt, c(async_stmt), and(2), tok(KW_ASYNC), rule(async_stmt_2))
DEF_RULE(async_stmt_2, nc, or(3), rule(funcdef), rule(with_stmt), rule(for_stmt))
DEF_RULE_NC(async_stmt_2, or(3), rule(funcdef), rule(with_stmt), rule(for_stmt))
#else
DEF_RULE(compound_stmt, nc, or(8), rule(if_stmt), rule(while_stmt), rule(for_stmt), rule(try_stmt), rule(with_stmt), rule(funcdef), rule(classdef), rule(decorated))
DEF_RULE_NC(compound_stmt, or(8), rule(if_stmt), rule(while_stmt), rule(for_stmt), rule(try_stmt), rule(with_stmt), rule(funcdef), rule(classdef), rule(decorated))
#endif
DEF_RULE(if_stmt, c(if_stmt), and(6), tok(KW_IF), rule(test), tok(DEL_COLON), rule(suite), opt_rule(if_stmt_elif_list), opt_rule(else_stmt))
DEF_RULE(if_stmt_elif_list, nc, one_or_more, rule(if_stmt_elif))
DEF_RULE(if_stmt_elif, nc, and(4), tok(KW_ELIF), rule(test), tok(DEL_COLON), rule(suite))
DEF_RULE_NC(if_stmt_elif_list, one_or_more, rule(if_stmt_elif))
DEF_RULE_NC(if_stmt_elif, and(4), tok(KW_ELIF), rule(test), tok(DEL_COLON), rule(suite))
DEF_RULE(while_stmt, c(while_stmt), and(5), tok(KW_WHILE), rule(test), tok(DEL_COLON), rule(suite), opt_rule(else_stmt))
DEF_RULE(for_stmt, c(for_stmt), and(7), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(testlist), tok(DEL_COLON), rule(suite), opt_rule(else_stmt))
DEF_RULE(try_stmt, c(try_stmt), and(4), tok(KW_TRY), tok(DEL_COLON), rule(suite), rule(try_stmt_2))
DEF_RULE(try_stmt_2, nc, or(2), rule(try_stmt_except_and_more), rule(try_stmt_finally))
DEF_RULE(try_stmt_except_and_more, nc, and_ident(3), rule(try_stmt_except_list), opt_rule(else_stmt), opt_rule(try_stmt_finally))
DEF_RULE(try_stmt_except, nc, and(4), tok(KW_EXCEPT), opt_rule(try_stmt_as_name), tok(DEL_COLON), rule(suite))
DEF_RULE(try_stmt_as_name, nc, and_ident(2), rule(test), opt_rule(as_name))
DEF_RULE(try_stmt_except_list, nc, one_or_more, rule(try_stmt_except))
DEF_RULE(try_stmt_finally, nc, and(3), tok(KW_FINALLY), tok(DEL_COLON), rule(suite))
DEF_RULE(else_stmt, nc, and_ident(3), tok(KW_ELSE), tok(DEL_COLON), rule(suite))
DEF_RULE_NC(try_stmt_2, or(2), rule(try_stmt_except_and_more), rule(try_stmt_finally))
DEF_RULE_NC(try_stmt_except_and_more, and_ident(3), rule(try_stmt_except_list), opt_rule(else_stmt), opt_rule(try_stmt_finally))
DEF_RULE_NC(try_stmt_except, and(4), tok(KW_EXCEPT), opt_rule(try_stmt_as_name), tok(DEL_COLON), rule(suite))
DEF_RULE_NC(try_stmt_as_name, and_ident(2), rule(test), opt_rule(as_name))
DEF_RULE_NC(try_stmt_except_list, one_or_more, rule(try_stmt_except))
DEF_RULE_NC(try_stmt_finally, and(3), tok(KW_FINALLY), tok(DEL_COLON), rule(suite))
DEF_RULE_NC(else_stmt, and_ident(3), tok(KW_ELSE), tok(DEL_COLON), rule(suite))
DEF_RULE(with_stmt, c(with_stmt), and(4), tok(KW_WITH), rule(with_stmt_list), tok(DEL_COLON), rule(suite))
DEF_RULE(with_stmt_list, nc, list, rule(with_item), tok(DEL_COMMA))
DEF_RULE(with_item, nc, and_ident(2), rule(test), opt_rule(with_item_as))
DEF_RULE(with_item_as, nc, and_ident(2), tok(KW_AS), rule(expr))
DEF_RULE(suite, nc, or(2), rule(suite_block), rule(simple_stmt))
DEF_RULE(suite_block, nc, and_ident(4), tok(NEWLINE), tok(INDENT), rule(suite_block_stmts), tok(DEDENT))
DEF_RULE_NC(with_stmt_list, list, rule(with_item), tok(DEL_COMMA))
DEF_RULE_NC(with_item, and_ident(2), rule(test), opt_rule(with_item_as))
DEF_RULE_NC(with_item_as, and_ident(2), tok(KW_AS), rule(expr))
DEF_RULE_NC(suite, or(2), rule(suite_block), rule(simple_stmt))
DEF_RULE_NC(suite_block, and_ident(4), tok(NEWLINE), tok(INDENT), rule(suite_block_stmts), tok(DEDENT))
DEF_RULE(suite_block_stmts, c(generic_all_nodes), one_or_more, rule(stmt))
// test: or_test ['if' or_test 'else' test] | lambdef
@ -208,10 +208,10 @@ DEF_RULE(suite_block_stmts, c(generic_all_nodes), one_or_more, rule(stmt))
// lambdef: 'lambda' [varargslist] ':' test
// lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
DEF_RULE(test, nc, or(2), rule(lambdef), rule(test_if_expr))
DEF_RULE_NC(test, or(2), rule(lambdef), rule(test_if_expr))
DEF_RULE(test_if_expr, c(test_if_expr), and_ident(2), rule(or_test), opt_rule(test_if_else))
DEF_RULE(test_if_else, nc, and(4), tok(KW_IF), rule(or_test), tok(KW_ELSE), rule(test))
DEF_RULE(test_nocond, nc, or(2), rule(lambdef_nocond), rule(or_test))
DEF_RULE_NC(test_if_else, and(4), tok(KW_IF), rule(or_test), tok(KW_ELSE), rule(test))
DEF_RULE_NC(test_nocond, or(2), rule(lambdef_nocond), rule(or_test))
DEF_RULE(lambdef, c(lambdef), and_blank(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test))
DEF_RULE(lambdef_nocond, c(lambdef), and_blank(4), tok(KW_LAMBDA), opt_rule(varargslist), tok(DEL_COLON), rule(test_nocond))
@ -233,54 +233,52 @@ DEF_RULE(lambdef_nocond, c(lambdef), and_blank(4), tok(KW_LAMBDA), opt_rule(vara
DEF_RULE(or_test, c(or_test), list, rule(and_test), tok(KW_OR))
DEF_RULE(and_test, c(and_test), list, rule(not_test), tok(KW_AND))
DEF_RULE(not_test, nc, or(2), rule(not_test_2), rule(comparison))
DEF_RULE_NC(not_test, or(2), rule(not_test_2), rule(comparison))
DEF_RULE(not_test_2, c(not_test_2), and(2), tok(KW_NOT), rule(not_test))
DEF_RULE(comparison, c(comparison), list, rule(expr), rule(comp_op))
DEF_RULE(comp_op, nc, or(9), tok(OP_LESS), tok(OP_MORE), tok(OP_DBL_EQUAL), tok(OP_LESS_EQUAL), tok(OP_MORE_EQUAL), tok(OP_NOT_EQUAL), tok(KW_IN), rule(comp_op_not_in), rule(comp_op_is))
DEF_RULE(comp_op_not_in, nc, and(2), tok(KW_NOT), tok(KW_IN))
DEF_RULE(comp_op_is, nc, and(2), tok(KW_IS), opt_rule(comp_op_is_not))
DEF_RULE(comp_op_is_not, nc, and(1), tok(KW_NOT))
DEF_RULE_NC(comp_op, or(9), tok(OP_LESS), tok(OP_MORE), tok(OP_DBL_EQUAL), tok(OP_LESS_EQUAL), tok(OP_MORE_EQUAL), tok(OP_NOT_EQUAL), tok(KW_IN), rule(comp_op_not_in), rule(comp_op_is))
DEF_RULE_NC(comp_op_not_in, and(2), tok(KW_NOT), tok(KW_IN))
DEF_RULE_NC(comp_op_is, and(2), tok(KW_IS), opt_rule(comp_op_is_not))
DEF_RULE_NC(comp_op_is_not, and(1), tok(KW_NOT))
DEF_RULE(star_expr, c(star_expr), and(2), tok(OP_STAR), rule(expr))
DEF_RULE(expr, c(expr), list, rule(xor_expr), tok(OP_PIPE))
DEF_RULE(xor_expr, c(xor_expr), list, rule(and_expr), tok(OP_CARET))
DEF_RULE(and_expr, c(and_expr), list, rule(shift_expr), tok(OP_AMPERSAND))
DEF_RULE(shift_expr, c(shift_expr), list, rule(arith_expr), rule(shift_op))
DEF_RULE(shift_op, nc, or(2), tok(OP_DBL_LESS), tok(OP_DBL_MORE))
DEF_RULE_NC(shift_op, or(2), tok(OP_DBL_LESS), tok(OP_DBL_MORE))
DEF_RULE(arith_expr, c(arith_expr), list, rule(term), rule(arith_op))
DEF_RULE(arith_op, nc, or(2), tok(OP_PLUS), tok(OP_MINUS))
DEF_RULE_NC(arith_op, or(2), tok(OP_PLUS), tok(OP_MINUS))
DEF_RULE(term, c(term), list, rule(factor), rule(term_op))
DEF_RULE(term_op, nc, or(4), tok(OP_STAR), tok(OP_SLASH), tok(OP_PERCENT), tok(OP_DBL_SLASH))
DEF_RULE(factor, nc, or(2), rule(factor_2), rule(power))
DEF_RULE_NC(term_op, or(4), tok(OP_STAR), tok(OP_SLASH), tok(OP_PERCENT), tok(OP_DBL_SLASH))
DEF_RULE_NC(factor, or(2), rule(factor_2), rule(power))
DEF_RULE(factor_2, c(factor_2), and_ident(2), rule(factor_op), rule(factor))
DEF_RULE(factor_op, nc, or(3), tok(OP_PLUS), tok(OP_MINUS), tok(OP_TILDE))
DEF_RULE_NC(factor_op, or(3), tok(OP_PLUS), tok(OP_MINUS), tok(OP_TILDE))
DEF_RULE(power, c(power), and_ident(2), rule(atom_expr), opt_rule(power_dbl_star))
#if MICROPY_PY_ASYNC_AWAIT
DEF_RULE(atom_expr, nc, or(2), rule(atom_expr_await), rule(atom_expr_normal))
DEF_RULE_NC(atom_expr, or(2), rule(atom_expr_await), rule(atom_expr_normal))
DEF_RULE(atom_expr_await, c(atom_expr_await), and(3), tok(KW_AWAIT), rule(atom), opt_rule(atom_expr_trailers))
#else
DEF_RULE(atom_expr, nc, or(1), rule(atom_expr_normal))
DEF_RULE_NC(atom_expr, or(1), rule(atom_expr_normal))
#endif
DEF_RULE(atom_expr_normal, c(atom_expr_normal), and_ident(2), rule(atom), opt_rule(atom_expr_trailers))
DEF_RULE(atom_expr_trailers, c(atom_expr_trailers), one_or_more, rule(trailer))
DEF_RULE(power_dbl_star, nc, and_ident(2), tok(OP_DBL_STAR), rule(factor))
DEF_RULE_NC(power_dbl_star, and_ident(2), tok(OP_DBL_STAR), rule(factor))
// atom: '(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False'
// testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
// trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
DEF_RULE(atom, nc, or(11), tok(NAME), tok(INTEGER), tok(FLOAT_OR_IMAG), rule(atom_string), tok(ELLIPSIS), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))
DEF_RULE(atom_string, c(atom_string), one_or_more, rule(string_or_bytes))
DEF_RULE(string_or_bytes, nc, or(2), tok(STRING), tok(BYTES))
DEF_RULE_NC(atom, or(12), tok(NAME), tok(INTEGER), tok(FLOAT_OR_IMAG), tok(STRING), tok(BYTES), tok(ELLIPSIS), tok(KW_NONE), tok(KW_TRUE), tok(KW_FALSE), rule(atom_paren), rule(atom_bracket), rule(atom_brace))
DEF_RULE(atom_paren, c(atom_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(atom_2b), tok(DEL_PAREN_CLOSE))
DEF_RULE(atom_2b, nc, or(2), rule(yield_expr), rule(testlist_comp))
DEF_RULE_NC(atom_2b, or(2), rule(yield_expr), rule(testlist_comp))
DEF_RULE(atom_bracket, c(atom_bracket), and(3), tok(DEL_BRACKET_OPEN), opt_rule(testlist_comp), tok(DEL_BRACKET_CLOSE))
DEF_RULE(atom_brace, c(atom_brace), and(3), tok(DEL_BRACE_OPEN), opt_rule(dictorsetmaker), tok(DEL_BRACE_CLOSE))
DEF_RULE(testlist_comp, nc, and_ident(2), rule(testlist_comp_2), opt_rule(testlist_comp_3))
DEF_RULE(testlist_comp_2, nc, or(2), rule(star_expr), rule(test))
DEF_RULE(testlist_comp_3, nc, or(2), rule(comp_for), rule(testlist_comp_3b))
DEF_RULE(testlist_comp_3b, nc, and_ident(2), tok(DEL_COMMA), opt_rule(testlist_comp_3c))
DEF_RULE(testlist_comp_3c, nc, list_with_end, rule(testlist_comp_2), tok(DEL_COMMA))
DEF_RULE(trailer, nc, or(3), rule(trailer_paren), rule(trailer_bracket), rule(trailer_period))
DEF_RULE_NC(testlist_comp, and_ident(2), rule(testlist_comp_2), opt_rule(testlist_comp_3))
DEF_RULE_NC(testlist_comp_2, or(2), rule(star_expr), rule(test))
DEF_RULE_NC(testlist_comp_3, or(2), rule(comp_for), rule(testlist_comp_3b))
DEF_RULE_NC(testlist_comp_3b, and_ident(2), tok(DEL_COMMA), opt_rule(testlist_comp_3c))
DEF_RULE_NC(testlist_comp_3c, list_with_end, rule(testlist_comp_2), tok(DEL_COMMA))
DEF_RULE_NC(trailer, or(3), rule(trailer_paren), rule(trailer_bracket), rule(trailer_period))
DEF_RULE(trailer_paren, c(trailer_paren), and(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE))
DEF_RULE(trailer_bracket, c(trailer_bracket), and(3), tok(DEL_BRACKET_OPEN), rule(subscriptlist), tok(DEL_BRACKET_CLOSE))
DEF_RULE(trailer_period, c(trailer_period), and(2), tok(DEL_PERIOD), tok(NAME))
@ -291,13 +289,13 @@ DEF_RULE(trailer_period, c(trailer_period), and(2), tok(DEL_PERIOD), tok(NAME))
#if MICROPY_PY_BUILTINS_SLICE
DEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(subscript), tok(DEL_COMMA))
DEF_RULE(subscript, nc, or(2), rule(subscript_3), rule(subscript_2))
DEF_RULE_NC(subscript, or(2), rule(subscript_3), rule(subscript_2))
DEF_RULE(subscript_2, c(subscript_2), and_ident(2), rule(test), opt_rule(subscript_3))
DEF_RULE(subscript_3, c(subscript_3), and(2), tok(DEL_COLON), opt_rule(subscript_3b))
DEF_RULE(subscript_3b, nc, or(2), rule(subscript_3c), rule(subscript_3d))
DEF_RULE(subscript_3c, nc, and(2), tok(DEL_COLON), opt_rule(test))
DEF_RULE(subscript_3d, nc, and_ident(2), rule(test), opt_rule(sliceop))
DEF_RULE(sliceop, nc, and(2), tok(DEL_COLON), opt_rule(test))
DEF_RULE_NC(subscript_3b, or(2), rule(subscript_3c), rule(subscript_3d))
DEF_RULE_NC(subscript_3c, and(2), tok(DEL_COLON), opt_rule(test))
DEF_RULE_NC(subscript_3d, and_ident(2), rule(test), opt_rule(sliceop))
DEF_RULE_NC(sliceop, and(2), tok(DEL_COLON), opt_rule(test))
#else
DEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COMMA))
#endif
@ -306,33 +304,33 @@ DEF_RULE(subscriptlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COM
// testlist: test (',' test)* [',']
// dictorsetmaker: (test ':' test (comp_for | (',' test ':' test)* [','])) | (test (comp_for | (',' test)* [',']))
DEF_RULE(exprlist, nc, list_with_end, rule(exprlist_2), tok(DEL_COMMA))
DEF_RULE(exprlist_2, nc, or(2), rule(star_expr), rule(expr))
DEF_RULE_NC(exprlist, list_with_end, rule(exprlist_2), tok(DEL_COMMA))
DEF_RULE_NC(exprlist_2, or(2), rule(star_expr), rule(expr))
DEF_RULE(testlist, c(generic_tuple), list_with_end, rule(test), tok(DEL_COMMA))
// TODO dictorsetmaker lets through more than is allowed
DEF_RULE(dictorsetmaker, nc, and_ident(2), rule(dictorsetmaker_item), opt_rule(dictorsetmaker_tail))
DEF_RULE_NC(dictorsetmaker, and_ident(2), rule(dictorsetmaker_item), opt_rule(dictorsetmaker_tail))
#if MICROPY_PY_BUILTINS_SET
DEF_RULE(dictorsetmaker_item, c(dictorsetmaker_item), and_ident(2), rule(test), opt_rule(dictorsetmaker_colon))
DEF_RULE(dictorsetmaker_colon, nc, and_ident(2), tok(DEL_COLON), rule(test))
DEF_RULE_NC(dictorsetmaker_colon, and_ident(2), tok(DEL_COLON), rule(test))
#else
DEF_RULE(dictorsetmaker_item, c(dictorsetmaker_item), and(3), rule(test), tok(DEL_COLON), rule(test))
#endif
DEF_RULE(dictorsetmaker_tail, nc, or(2), rule(comp_for), rule(dictorsetmaker_list))
DEF_RULE(dictorsetmaker_list, nc, and(2), tok(DEL_COMMA), opt_rule(dictorsetmaker_list2))
DEF_RULE(dictorsetmaker_list2, nc, list_with_end, rule(dictorsetmaker_item), tok(DEL_COMMA))
DEF_RULE_NC(dictorsetmaker_tail, or(2), rule(comp_for), rule(dictorsetmaker_list))
DEF_RULE_NC(dictorsetmaker_list, and(2), tok(DEL_COMMA), opt_rule(dictorsetmaker_list2))
DEF_RULE_NC(dictorsetmaker_list2, list_with_end, rule(dictorsetmaker_item), tok(DEL_COMMA))
// classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
DEF_RULE(classdef, c(classdef), and_blank(5), tok(KW_CLASS), tok(NAME), opt_rule(classdef_2), tok(DEL_COLON), rule(suite))
DEF_RULE(classdef_2, nc, and_ident(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE))
DEF_RULE_NC(classdef_2, and_ident(3), tok(DEL_PAREN_OPEN), opt_rule(arglist), tok(DEL_PAREN_CLOSE))
// arglist: (argument ',')* (argument [','] | '*' test (',' argument)* [',' '**' test] | '**' test)
// TODO arglist lets through more than is allowed, compiler needs to do further verification
DEF_RULE(arglist, nc, list_with_end, rule(arglist_2), tok(DEL_COMMA))
DEF_RULE(arglist_2, nc, or(3), rule(arglist_star), rule(arglist_dbl_star), rule(argument))
DEF_RULE(arglist_star, nc, and(2), tok(OP_STAR), rule(test))
DEF_RULE(arglist_dbl_star, nc, and(2), tok(OP_DBL_STAR), rule(test))
DEF_RULE_NC(arglist, list_with_end, rule(arglist_2), tok(DEL_COMMA))
DEF_RULE_NC(arglist_2, or(3), rule(arglist_star), rule(arglist_dbl_star), rule(argument))
DEF_RULE_NC(arglist_star, and(2), tok(OP_STAR), rule(test))
DEF_RULE_NC(arglist_dbl_star, and(2), tok(OP_DBL_STAR), rule(test))
// # The reason that keywords are test nodes instead of NAME is that using NAME
// # results in an ambiguity. ast.c makes sure it's a NAME.
@ -341,12 +339,12 @@ DEF_RULE(arglist_dbl_star, nc, and(2), tok(OP_DBL_STAR), rule(test))
// comp_for: 'for' exprlist 'in' or_test [comp_iter]
// comp_if: 'if' test_nocond [comp_iter]
DEF_RULE(argument, nc, and_ident(2), rule(test), opt_rule(argument_2))
DEF_RULE(argument_2, nc, or(2), rule(comp_for), rule(argument_3))
DEF_RULE(argument_3, nc, and_ident(2), tok(DEL_EQUAL), rule(test))
DEF_RULE(comp_iter, nc, or(2), rule(comp_for), rule(comp_if))
DEF_RULE(comp_for, nc, and_blank(5), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(or_test), opt_rule(comp_iter))
DEF_RULE(comp_if, nc, and(3), tok(KW_IF), rule(test_nocond), opt_rule(comp_iter))
DEF_RULE_NC(argument, and_ident(2), rule(test), opt_rule(argument_2))
DEF_RULE_NC(argument_2, or(2), rule(comp_for), rule(argument_3))
DEF_RULE_NC(argument_3, and_ident(2), tok(DEL_EQUAL), rule(test))
DEF_RULE_NC(comp_iter, or(2), rule(comp_for), rule(comp_if))
DEF_RULE_NC(comp_for, and_blank(5), tok(KW_FOR), rule(exprlist), tok(KW_IN), rule(or_test), opt_rule(comp_iter))
DEF_RULE_NC(comp_if, and(3), tok(KW_IF), rule(test_nocond), opt_rule(comp_iter))
// # not used in grammar, but may appear in "node" passed from Parser to Compiler
// encoding_decl: NAME
@ -355,5 +353,5 @@ DEF_RULE(comp_if, nc, and(3), tok(KW_IF), rule(test_nocond), opt_rule(comp_iter)
// yield_arg: 'from' test | testlist
DEF_RULE(yield_expr, c(yield_expr), and(2), tok(KW_YIELD), opt_rule(yield_arg))
DEF_RULE(yield_arg, nc, or(2), rule(yield_arg_from), rule(testlist))
DEF_RULE(yield_arg_from, nc, and(2), tok(KW_FROM), rule(test))
DEF_RULE_NC(yield_arg, or(2), rule(yield_arg_from), rule(testlist))
DEF_RULE_NC(yield_arg_from, and(2), tok(KW_FROM), rule(test))

View File

@ -25,6 +25,7 @@
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "py/mpstate.h"
@ -39,19 +40,6 @@
// TODO seems that CPython allows NULL byte in the input stream
// don't know if that's intentional or not, but we don't allow it
// TODO replace with a call to a standard function
STATIC 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;
++str;
++strn;
}
return i == len && *str == 0;
}
#define MP_LEXER_EOF ((unichar)MP_READER_EOF)
#define CUR_CHAR(lex) ((lex)->chr0)
@ -75,11 +63,9 @@ STATIC bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) {
return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3;
}
/*
STATIC bool is_char_following(mp_lexer_t *lex, byte c) {
return lex->chr1 == c;
}
*/
STATIC bool is_char_following_or(mp_lexer_t *lex, byte c1, byte c2) {
return lex->chr1 == c1 || lex->chr1 == c2;
@ -118,6 +104,13 @@ STATIC bool is_following_odigit(mp_lexer_t *lex) {
return lex->chr1 >= '0' && lex->chr1 <= '7';
}
STATIC bool is_string_or_bytes(mp_lexer_t *lex) {
return is_char_or(lex, '\'', '\"')
|| (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"'))
|| ((is_char_and(lex, 'r', 'b') || is_char_and(lex, 'b', 'r'))
&& is_char_following_following_or(lex, '\'', '\"'));
}
// to easily parse utf-8 identifiers we allow any raw byte with high bit set
STATIC bool is_head_of_identifier(mp_lexer_t *lex) {
return is_letter(lex) || lex->chr0 == '_' || lex->chr0 >= 0x80;
@ -164,7 +157,7 @@ STATIC void next_char(mp_lexer_t *lex) {
}
}
STATIC void indent_push(mp_lexer_t *lex, mp_uint_t indent) {
STATIC void indent_push(mp_lexer_t *lex, size_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);
@ -173,7 +166,7 @@ STATIC void indent_push(mp_lexer_t *lex, mp_uint_t indent) {
lex->indent_level[lex->num_indent_level++] = indent;
}
STATIC mp_uint_t indent_top(mp_lexer_t *lex) {
STATIC size_t indent_top(mp_lexer_t *lex) {
return lex->indent_level[lex->num_indent_level - 1];
}
@ -225,10 +218,12 @@ STATIC const uint8_t tok_enc_kind[] = {
};
// must have the same order as enum in lexer.h
// must be sorted according to strcmp
STATIC const char *const tok_kw[] = {
"False",
"None",
"True",
"__debug__",
"and",
"as",
"assert",
@ -263,13 +258,12 @@ STATIC const char *const tok_kw[] = {
"while",
"with",
"yield",
"__debug__",
};
// This is called with CUR_CHAR() before first hex digit, and should return with
// it pointing to last hex digit
// num_digits must be greater than zero
STATIC bool get_hex(mp_lexer_t *lex, mp_uint_t num_digits, mp_uint_t *result) {
STATIC bool get_hex(mp_lexer_t *lex, size_t num_digits, mp_uint_t *result) {
mp_uint_t num = 0;
while (num_digits-- != 0) {
next_char(lex);
@ -283,14 +277,144 @@ STATIC bool get_hex(mp_lexer_t *lex, mp_uint_t num_digits, mp_uint_t *result) {
return true;
}
STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
// start new token text
vstr_reset(&lex->vstr);
STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw) {
// get first quoting character
char quote_char = '\'';
if (is_char(lex, '\"')) {
quote_char = '\"';
}
next_char(lex);
// skip white space and comments
// work out if it's a single or triple quoted literal
size_t num_quotes;
if (is_char_and(lex, quote_char, quote_char)) {
// triple quotes
next_char(lex);
next_char(lex);
num_quotes = 3;
} else {
// single quotes
num_quotes = 1;
}
size_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;
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
} else {
n_closing = 0;
if (is_char(lex, '\\')) {
next_char(lex);
unichar c = CUR_CHAR(lex);
if (is_raw) {
// raw strings allow escaping of quotes, but the backslash is also emitted
vstr_add_char(&lex->vstr, '\\');
} else {
switch (c) {
// note: "c" can never be MP_LEXER_EOF because next_char
// always inserts a newline at the end of the input stream
case '\n': c = MP_LEXER_EOF; break; // backslash escape the newline, just ignore it
case '\\': break;
case '\'': break;
case '"': break;
case 'a': c = 0x07; break;
case 'b': c = 0x08; break;
case 't': c = 0x09; break;
case 'n': c = 0x0a; break;
case 'v': c = 0x0b; break;
case 'f': c = 0x0c; break;
case 'r': c = 0x0d; break;
case 'u':
case 'U':
if (lex->tok_kind == MP_TOKEN_BYTES) {
// b'\u1234' == b'\\u1234'
vstr_add_char(&lex->vstr, '\\');
break;
}
// Otherwise fall through.
case 'x':
{
mp_uint_t num = 0;
if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {
// not enough hex chars for escape sequence
lex->tok_kind = MP_TOKEN_INVALID;
}
c = num;
break;
}
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
mp_not_implemented("unicode name escapes");
break;
default:
if (c >= '0' && c <= '7') {
// Octal sequence, 1-3 chars
size_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');
}
c = num;
} else {
// unrecognised escape character; CPython lets this through verbatim as '\' and then the character
vstr_add_char(&lex->vstr, '\\');
}
break;
}
}
if (c != MP_LEXER_EOF) {
if (MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) {
if (c < 0x110000 && lex->tok_kind == MP_TOKEN_STRING) {
vstr_add_char(&lex->vstr, c);
} else if (c < 0x100 && lex->tok_kind == MP_TOKEN_BYTES) {
vstr_add_byte(&lex->vstr, c);
} else {
// unicode character out of range
// this raises a generic SyntaxError; could provide more info
lex->tok_kind = MP_TOKEN_INVALID;
}
} else {
// without unicode everything is just added as an 8-bit byte
if (c < 0x100) {
vstr_add_byte(&lex->vstr, c);
} else {
// 8-bit character out of range
// this raises a generic SyntaxError; could provide more info
lex->tok_kind = MP_TOKEN_INVALID;
}
}
}
} else {
// Add the "character" as a byte so that we remain 8-bit clean.
// This way, strings are parsed correctly whether or not they contain utf-8 chars.
vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
}
}
next_char(lex);
}
// check we got the required end quotes
if (n_closing < num_quotes) {
lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN;
}
// cut off the end quotes from the token text
vstr_cut_tail_bytes(&lex->vstr, n_closing);
}
STATIC bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) {
bool had_physical_newline = false;
while (!is_end(lex)) {
if (is_physical_newline(lex)) {
if (stop_at_newline && lex->nested_bracket_level == 0) {
break;
}
had_physical_newline = true;
next_char(lex);
} else if (is_whitespace(lex)) {
@ -301,35 +425,29 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
next_char(lex);
}
// had_physical_newline will be set on next loop
} else if (is_char(lex, '\\')) {
// backslash (outside string literals) must appear just before a physical newline
} else if (is_char_and(lex, '\\', '\n')) {
// line-continuation, so don't set had_physical_newline
next_char(lex);
next_char(lex);
if (!is_physical_newline(lex)) {
// SyntaxError: unexpected character after line continuation character
lex->tok_line = lex->line;
lex->tok_column = lex->column;
lex->tok_kind = MP_TOKEN_BAD_LINE_CONTINUATION;
return;
} else {
next_char(lex);
}
} else {
break;
}
}
return had_physical_newline;
}
void mp_lexer_to_next(mp_lexer_t *lex) {
// start new token text
vstr_reset(&lex->vstr);
// skip white space and comments
bool had_physical_newline = skip_whitespace(lex, false);
// set token source information
lex->tok_line = lex->line;
lex->tok_column = lex->column;
if (first_token && lex->line == 1 && lex->column != 1) {
// check that the first token is in the first column
// if first token is not on first line, we get a physical newline and
// this check is done as part of normal indent/dedent checking below
// (done to get equivalence with CPython)
lex->tok_kind = MP_TOKEN_INDENT;
} else if (lex->emit_dent < 0) {
if (lex->emit_dent < 0) {
lex->tok_kind = MP_TOKEN_DEDENT;
lex->emit_dent += 1;
@ -340,7 +458,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
} else if (had_physical_newline && lex->nested_bracket_level == 0) {
lex->tok_kind = MP_TOKEN_NEWLINE;
mp_uint_t num_spaces = lex->column - 1;
size_t num_spaces = lex->column - 1;
if (num_spaces == indent_top(lex)) {
} else if (num_spaces > indent_top(lex)) {
indent_push(lex, num_spaces);
@ -358,168 +476,65 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
} else if (is_end(lex)) {
lex->tok_kind = MP_TOKEN_END;
} else if (is_char_or(lex, '\'', '\"')
|| (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"'))
|| ((is_char_and(lex, 'r', 'b') || is_char_and(lex, 'b', 'r')) && is_char_following_following_or(lex, '\'', '\"'))) {
} else if (is_string_or_bytes(lex)) {
// a string or bytes literal
// parse type codes
bool is_raw = false;
bool is_bytes = false;
if (is_char(lex, 'u')) {
next_char(lex);
} else if (is_char(lex, 'b')) {
is_bytes = true;
next_char(lex);
if (is_char(lex, 'r')) {
// Python requires adjacent string/bytes literals to be automatically
// concatenated. We do it here in the tokeniser to make efficient use of RAM,
// because then the lexer's vstr can be used to accumulate the string literal,
// in contrast to creating a parse tree of strings and then joining them later
// in the compiler. It's also more compact in code size to do it here.
// MP_TOKEN_END is used to indicate that this is the first string token
lex->tok_kind = MP_TOKEN_END;
// Loop to accumulate string/bytes literals
do {
// parse type codes
bool is_raw = false;
mp_token_kind_t kind = MP_TOKEN_STRING;
int n_char = 0;
if (is_char(lex, 'u')) {
n_char = 1;
} else if (is_char(lex, 'b')) {
kind = MP_TOKEN_BYTES;
n_char = 1;
if (is_char_following(lex, 'r')) {
is_raw = true;
n_char = 2;
}
} else if (is_char(lex, 'r')) {
is_raw = true;
next_char(lex);
}
} else if (is_char(lex, 'r')) {
is_raw = true;
next_char(lex);
if (is_char(lex, 'b')) {
is_bytes = true;
next_char(lex);
}
}
// set token kind
if (is_bytes) {
lex->tok_kind = MP_TOKEN_BYTES;
} else {
lex->tok_kind = MP_TOKEN_STRING;
}
// get first quoting character
char quote_char = '\'';
if (is_char(lex, '\"')) {
quote_char = '\"';
}
next_char(lex);
// work out if it's a single or triple quoted literal
mp_uint_t num_quotes;
if (is_char_and(lex, quote_char, quote_char)) {
// triple quotes
next_char(lex);
next_char(lex);
num_quotes = 3;
} else {
// single quotes
num_quotes = 1;
}
// parse the literal
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;
vstr_add_char(&lex->vstr, CUR_CHAR(lex));
} else {
n_closing = 0;
if (is_char(lex, '\\')) {
next_char(lex);
unichar c = CUR_CHAR(lex);
if (is_raw) {
// raw strings allow escaping of quotes, but the backslash is also emitted
vstr_add_char(&lex->vstr, '\\');
} else {
switch (c) {
// note: "c" can never be MP_LEXER_EOF because next_char
// always inserts a newline at the end of the input stream
case '\n': c = MP_LEXER_EOF; break; // backslash escape the newline, just ignore it
case '\\': break;
case '\'': break;
case '"': break;
case 'a': c = 0x07; break;
case 'b': c = 0x08; break;
case 't': c = 0x09; break;
case 'n': c = 0x0a; break;
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':
{
mp_uint_t num = 0;
if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {
// not enough hex chars for escape sequence
lex->tok_kind = MP_TOKEN_INVALID;
}
c = num;
break;
}
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
mp_not_implemented("unicode name escapes");
break;
default:
if (c >= '0' && c <= '7') {
// Octal sequence, 1-3 chars
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');
}
c = num;
} else {
// unrecognised escape character; CPython lets this through verbatim as '\' and then the character
vstr_add_char(&lex->vstr, '\\');
}
break;
}
}
if (c != MP_LEXER_EOF) {
if (MICROPY_PY_BUILTINS_STR_UNICODE_DYNAMIC) {
if (c < 0x110000 && !is_bytes) {
vstr_add_char(&lex->vstr, c);
} else if (c < 0x100 && is_bytes) {
vstr_add_byte(&lex->vstr, c);
} else {
// unicode character out of range
// this raises a generic SyntaxError; could provide more info
lex->tok_kind = MP_TOKEN_INVALID;
}
} else {
// without unicode everything is just added as an 8-bit byte
if (c < 0x100) {
vstr_add_byte(&lex->vstr, c);
} else {
// 8-bit character out of range
// this raises a generic SyntaxError; could provide more info
lex->tok_kind = MP_TOKEN_INVALID;
}
}
}
} else {
// Add the "character" as a byte so that we remain 8-bit clean.
// This way, strings are parsed correctly whether or not they contain utf-8 chars.
vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
n_char = 1;
if (is_char_following(lex, 'b')) {
kind = MP_TOKEN_BYTES;
n_char = 2;
}
}
next_char(lex);
}
// check we got the required end quotes
if (n_closing < num_quotes) {
lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN;
}
// Set or check token kind
if (lex->tok_kind == MP_TOKEN_END) {
lex->tok_kind = kind;
} else if (lex->tok_kind != kind) {
// Can't concatenate string with bytes
break;
}
// cut off the end quotes from the token text
vstr_cut_tail_bytes(&lex->vstr, n_closing);
// Skip any type code characters
if (n_char != 0) {
next_char(lex);
if (n_char == 2) {
next_char(lex);
}
}
// Parse the literal
parse_string_literal(lex, is_raw);
// Skip whitespace so we can check if there's another string following
skip_whitespace(lex, true);
} while (is_string_or_bytes(lex));
} else if (is_head_of_identifier(lex)) {
lex->tok_kind = MP_TOKEN_NAME;
@ -534,6 +549,25 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
next_char(lex);
}
// Check if the name is a keyword.
// We also check for __debug__ here and convert it to its value. This is
// so 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.
const char *s = vstr_null_terminated_str(&lex->vstr);
for (size_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
int cmp = strcmp(s, tok_kw[i]);
if (cmp == 0) {
lex->tok_kind = MP_TOKEN_KW_FALSE + i;
if (lex->tok_kind == MP_TOKEN_KW___DEBUG__) {
lex->tok_kind = (MP_STATE_VM(mp_optimise_value) == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
}
break;
} else if (cmp < 0) {
// Table is sorted and comparison was less-than, so stop searching
break;
}
}
} else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) {
bool forced_integer = false;
if (is_char(lex, '.')) {
@ -574,12 +608,9 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
// special handling for . and ... operators, because .. is not a valid operator
// get first char
vstr_add_char(&lex->vstr, '.');
next_char(lex);
if (is_char_and(lex, '.', '.')) {
vstr_add_char(&lex->vstr, '.');
vstr_add_char(&lex->vstr, '.');
next_char(lex);
next_char(lex);
lex->tok_kind = MP_TOKEN_ELLIPSIS;
@ -591,7 +622,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
// search for encoded delimiter or operator
const char *t = tok_enc;
mp_uint_t tok_enc_index = 0;
size_t tok_enc_index = 0;
for (; *t != 0 && !is_char(lex, *t); t += 1) {
if (*t == 'e' || *t == 'c') {
t += 1;
@ -613,7 +644,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
// get the maximum characters for a valid token
t += 1;
mp_uint_t t_index = tok_enc_index;
size_t t_index = tok_enc_index;
for (;;) {
for (; *t == 'e'; t += 1) {
t += 1;
@ -665,26 +696,6 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) {
}
}
}
// check for keywords
if (lex->tok_kind == MP_TOKEN_NAME) {
// We check for __debug__ here and convert it to its value. This is so
// 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 (mp_int_t i = 0; tok_kw[i] != NULL; i++) {
for (size_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
if (str_strn_equal(tok_kw[i], lex->vstr.buf, lex->vstr.len)) {
if (i == MP_ARRAY_SIZE(tok_kw) - 1) {
// tok_kw[MP_ARRAY_SIZE(tok_kw) - 1] == "__debug__"
lex->tok_kind = (MP_STATE_VM(mp_optimise_value) == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
} else {
lex->tok_kind = MP_TOKEN_KW_FALSE + i;
}
break;
}
}
}
}
mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
@ -708,7 +719,7 @@ mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
vstr_init(&lex->vstr, 32);
// check for memory allocation error
// note: vstr_init above may fail on malloc, but so may mp_lexer_next_token_into below
// note: vstr_init above may fail on malloc, but so may mp_lexer_to_next below
if (lex->indent_level == NULL) {
mp_lexer_free(lex);
return NULL;
@ -740,12 +751,18 @@ mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
}
// preload first token
mp_lexer_next_token_into(lex, true);
mp_lexer_to_next(lex);
// Check that the first token is in the first column. If it's not then we
// convert the token kind to INDENT so that the parser gives a syntax error.
if (lex->tok_column != 1) {
lex->tok_kind = MP_TOKEN_INDENT;
}
return lex;
}
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_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len) {
mp_reader_t reader;
if (!mp_reader_new_mem(&reader, (const byte*)str, len, free_len)) {
return NULL;
@ -788,10 +805,6 @@ void mp_lexer_free(mp_lexer_t *lex) {
}
}
void mp_lexer_to_next(mp_lexer_t *lex) {
mp_lexer_next_token_into(lex, false);
}
#if 0
// This function is used to print the current token and should only be
// needed to debug the lexer, so it's not available via a config option.

View File

@ -39,18 +39,17 @@
*/
typedef enum _mp_token_kind_t {
MP_TOKEN_END, // 0
MP_TOKEN_END,
MP_TOKEN_INVALID,
MP_TOKEN_DEDENT_MISMATCH,
MP_TOKEN_LONELY_STRING_OPEN,
MP_TOKEN_BAD_LINE_CONTINUATION,
MP_TOKEN_NEWLINE, // 5
MP_TOKEN_INDENT, // 6
MP_TOKEN_DEDENT, // 7
MP_TOKEN_NEWLINE,
MP_TOKEN_INDENT,
MP_TOKEN_DEDENT,
MP_TOKEN_NAME, // 8
MP_TOKEN_NAME,
MP_TOKEN_INTEGER,
MP_TOKEN_FLOAT_OR_IMAG,
MP_TOKEN_STRING,
@ -58,9 +57,10 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_ELLIPSIS,
MP_TOKEN_KW_FALSE, // 14
MP_TOKEN_KW_FALSE,
MP_TOKEN_KW_NONE,
MP_TOKEN_KW_TRUE,
MP_TOKEN_KW___DEBUG__,
MP_TOKEN_KW_AND,
MP_TOKEN_KW_AS,
MP_TOKEN_KW_ASSERT,
@ -71,7 +71,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_KW_BREAK,
MP_TOKEN_KW_CLASS,
MP_TOKEN_KW_CONTINUE,
MP_TOKEN_KW_DEF, // 23
MP_TOKEN_KW_DEF,
MP_TOKEN_KW_DEL,
MP_TOKEN_KW_ELIF,
MP_TOKEN_KW_ELSE,
@ -81,7 +81,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_KW_FROM,
MP_TOKEN_KW_GLOBAL,
MP_TOKEN_KW_IF,
MP_TOKEN_KW_IMPORT, // 33
MP_TOKEN_KW_IMPORT,
MP_TOKEN_KW_IN,
MP_TOKEN_KW_IS,
MP_TOKEN_KW_LAMBDA,
@ -91,12 +91,12 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_KW_PASS,
MP_TOKEN_KW_RAISE,
MP_TOKEN_KW_RETURN,
MP_TOKEN_KW_TRY, // 43
MP_TOKEN_KW_TRY,
MP_TOKEN_KW_WHILE,
MP_TOKEN_KW_WITH,
MP_TOKEN_KW_YIELD,
MP_TOKEN_OP_PLUS, // 47
MP_TOKEN_OP_PLUS,
MP_TOKEN_OP_MINUS,
MP_TOKEN_OP_STAR,
MP_TOKEN_OP_DBL_STAR,
@ -106,7 +106,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_OP_LESS,
MP_TOKEN_OP_DBL_LESS,
MP_TOKEN_OP_MORE,
MP_TOKEN_OP_DBL_MORE, // 57
MP_TOKEN_OP_DBL_MORE,
MP_TOKEN_OP_AMPERSAND,
MP_TOKEN_OP_PIPE,
MP_TOKEN_OP_CARET,
@ -116,7 +116,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_OP_DBL_EQUAL,
MP_TOKEN_OP_NOT_EQUAL,
MP_TOKEN_DEL_PAREN_OPEN, // 66
MP_TOKEN_DEL_PAREN_OPEN,
MP_TOKEN_DEL_PAREN_CLOSE,
MP_TOKEN_DEL_BRACKET_OPEN,
MP_TOKEN_DEL_BRACKET_CLOSE,
@ -126,7 +126,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_DEL_COLON,
MP_TOKEN_DEL_PERIOD,
MP_TOKEN_DEL_SEMICOLON,
MP_TOKEN_DEL_AT, // 76
MP_TOKEN_DEL_AT,
MP_TOKEN_DEL_EQUAL,
MP_TOKEN_DEL_PLUS_EQUAL,
MP_TOKEN_DEL_MINUS_EQUAL,
@ -136,7 +136,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_DEL_PERCENT_EQUAL,
MP_TOKEN_DEL_AMPERSAND_EQUAL,
MP_TOKEN_DEL_PIPE_EQUAL,
MP_TOKEN_DEL_CARET_EQUAL, // 86
MP_TOKEN_DEL_CARET_EQUAL,
MP_TOKEN_DEL_DBL_MORE_EQUAL,
MP_TOKEN_DEL_DBL_LESS_EQUAL,
MP_TOKEN_DEL_DBL_STAR_EQUAL,
@ -151,24 +151,24 @@ typedef struct _mp_lexer_t {
unichar chr0, chr1, chr2; // current cached characters from source
mp_uint_t line; // current source line
mp_uint_t column; // current source column
size_t line; // current source line
size_t column; // current source column
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
mp_uint_t alloc_indent_level;
mp_uint_t num_indent_level;
size_t alloc_indent_level;
size_t num_indent_level;
uint16_t *indent_level;
mp_uint_t tok_line; // token source line
mp_uint_t tok_column; // token source column
size_t tok_line; // token source line
size_t tok_column; // token source column
mp_token_kind_t tok_kind; // token kind
vstr_t vstr; // token data
} mp_lexer_t;
mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader);
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_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len);
void mp_lexer_free(mp_lexer_t *lex);
void mp_lexer_to_next(mp_lexer_t *lex);

View File

@ -56,7 +56,7 @@ STATIC const uint16_t hash_allocation_sizes[] = {
3229, 4831, 7243, 10861, 16273, 24407, 36607, 54907, // *1.5
};
STATIC mp_uint_t get_hash_alloc_greater_or_equal_to(mp_uint_t x) {
STATIC size_t get_hash_alloc_greater_or_equal_to(size_t x) {
for (size_t i = 0; i < MP_ARRAY_SIZE(hash_allocation_sizes); i++) {
if (hash_allocation_sizes[i] >= x) {
return hash_allocation_sizes[i];
@ -70,7 +70,7 @@ STATIC mp_uint_t get_hash_alloc_greater_or_equal_to(mp_uint_t x) {
/******************************************************************************/
/* map */
void mp_map_init(mp_map_t *map, mp_uint_t n) {
void mp_map_init(mp_map_t *map, size_t n) {
if (n == 0) {
map->alloc = 0;
map->table = NULL;
@ -84,7 +84,7 @@ void mp_map_init(mp_map_t *map, mp_uint_t n) {
map->is_ordered = 0;
}
void mp_map_init_fixed_table(mp_map_t *map, mp_uint_t n, const mp_obj_t *table) {
void mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table) {
map->alloc = n;
map->used = n;
map->all_keys_are_qstrs = 1;
@ -93,7 +93,7 @@ void mp_map_init_fixed_table(mp_map_t *map, mp_uint_t n, const mp_obj_t *table)
map->table = (mp_map_elem_t*)table;
}
mp_map_t *mp_map_new(mp_uint_t n) {
mp_map_t *mp_map_new(size_t n) {
mp_map_t *map = m_new(mp_map_t, 1);
mp_map_init(map, n);
return map;
@ -124,8 +124,8 @@ void mp_map_clear(mp_map_t *map) {
}
STATIC void mp_map_rehash(mp_map_t *map) {
mp_uint_t old_alloc = map->alloc;
mp_uint_t new_alloc = get_hash_alloc_greater_or_equal_to(map->alloc + 1);
size_t old_alloc = map->alloc;
size_t new_alloc = get_hash_alloc_greater_or_equal_to(map->alloc + 1);
mp_map_elem_t *old_table = map->table;
mp_map_elem_t *new_table = m_new0(mp_map_elem_t, new_alloc);
// If we reach this point, table resizing succeeded, now we can edit the old map.
@ -133,7 +133,7 @@ STATIC void mp_map_rehash(mp_map_t *map) {
map->used = 0;
map->all_keys_are_qstrs = 1;
map->table = new_table;
for (mp_uint_t i = 0; i < old_alloc; i++) {
for (size_t i = 0; i < old_alloc; i++) {
if (old_table[i].key != MP_OBJ_NULL && old_table[i].key != MP_OBJ_SENTINEL) {
mp_map_lookup(map, old_table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = old_table[i].value;
}
@ -220,8 +220,8 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
hash = MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, index));
}
mp_uint_t pos = hash % map->alloc;
mp_uint_t start_pos = pos;
size_t pos = hash % map->alloc;
size_t start_pos = pos;
mp_map_elem_t *avail_slot = NULL;
for (;;) {
mp_map_elem_t *slot = &map->table[pos];
@ -296,19 +296,19 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
#if MICROPY_PY_BUILTINS_SET
void mp_set_init(mp_set_t *set, mp_uint_t n) {
void mp_set_init(mp_set_t *set, size_t n) {
set->alloc = n;
set->used = 0;
set->table = m_new0(mp_obj_t, set->alloc);
}
STATIC void mp_set_rehash(mp_set_t *set) {
mp_uint_t old_alloc = set->alloc;
size_t old_alloc = set->alloc;
mp_obj_t *old_table = set->table;
set->alloc = get_hash_alloc_greater_or_equal_to(set->alloc + 1);
set->used = 0;
set->table = m_new0(mp_obj_t, set->alloc);
for (mp_uint_t i = 0; i < old_alloc; i++) {
for (size_t i = 0; i < old_alloc; i++) {
if (old_table[i] != MP_OBJ_NULL && old_table[i] != MP_OBJ_SENTINEL) {
mp_set_lookup(set, old_table[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}
@ -328,8 +328,8 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t looku
}
}
mp_uint_t hash = MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, index));
mp_uint_t pos = hash % set->alloc;
mp_uint_t start_pos = pos;
size_t pos = hash % set->alloc;
size_t start_pos = pos;
mp_obj_t *avail_slot = NULL;
for (;;) {
mp_obj_t elem = set->table[pos];
@ -390,7 +390,7 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t looku
}
mp_obj_t mp_set_remove_first(mp_set_t *set) {
for (mp_uint_t pos = 0; pos < set->alloc; pos++) {
for (size_t pos = 0; pos < set->alloc; pos++) {
if (MP_SET_SLOT_IS_FILLED(set, pos)) {
mp_obj_t elem = set->table[pos];
// delete element
@ -418,7 +418,7 @@ void mp_set_clear(mp_set_t *set) {
#if defined(DEBUG_PRINT) && DEBUG_PRINT
void mp_map_dump(mp_map_t *map) {
for (mp_uint_t i = 0; i < map->alloc; i++) {
for (size_t i = 0; i < map->alloc; i++) {
if (map->table[i].key != NULL) {
mp_obj_print(map->table[i].key, PRINT_REPR);
} else {

View File

@ -117,7 +117,8 @@ STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs);
STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) {
mp_obj_t iterable = mp_getiter(o_in);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(o_in, &iter_buf);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (!mp_obj_is_true(item)) {
@ -129,7 +130,8 @@ STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all);
STATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) {
mp_obj_t iterable = mp_getiter(o_in);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(o_in, &iter_buf);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (mp_obj_is_true(item)) {
@ -258,7 +260,7 @@ STATIC mp_obj_t mp_builtin_hex(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hex_obj, mp_builtin_hex);
STATIC mp_obj_t mp_builtin_iter(mp_obj_t o_in) {
return mp_getiter(o_in);
return mp_getiter(o_in, NULL);
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter);
@ -270,7 +272,8 @@ STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t
mp_obj_t key_fn = key_elem == NULL ? MP_OBJ_NULL : key_elem->value;
if (n_args == 1) {
// given an iterable
mp_obj_t iterable = mp_getiter(args[0]);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(args[0], &iter_buf);
mp_obj_t best_key = MP_OBJ_NULL;
mp_obj_t best_obj = MP_OBJ_NULL;
mp_obj_t item;
@ -495,7 +498,8 @@ STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) {
case 1: value = MP_OBJ_NEW_SMALL_INT(0); break;
default: value = args[1]; break;
}
mp_obj_t iterable = mp_getiter(args[0]);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(args[0], &iter_buf);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
value = mp_binary_op(MP_BINARY_OP_ADD, value, item);

View File

@ -44,24 +44,19 @@
/****************************************************************/
// Lock object
// Note: with the GIL enabled we can easily synthesise a lock object
STATIC const mp_obj_type_t mp_type_thread_lock;
typedef struct _mp_obj_thread_lock_t {
mp_obj_base_t base;
#if !MICROPY_PY_THREAD_GIL
mp_thread_mutex_t mutex;
#endif
volatile bool locked;
} mp_obj_thread_lock_t;
STATIC mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) {
mp_obj_thread_lock_t *self = m_new_obj(mp_obj_thread_lock_t);
self->base.type = &mp_type_thread_lock;
#if !MICROPY_PY_THREAD_GIL
mp_thread_mutex_init(&self->mutex);
#endif
self->locked = false;
return self;
}
@ -73,20 +68,9 @@ STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) {
wait = mp_obj_get_int(args[1]);
// TODO support timeout arg
}
#if MICROPY_PY_THREAD_GIL
if (self->locked) {
if (!wait) {
return mp_const_false;
}
do {
MP_THREAD_GIL_EXIT();
MP_THREAD_GIL_ENTER();
} while (self->locked);
}
self->locked = true;
return mp_const_true;
#else
MP_THREAD_GIL_EXIT();
int ret = mp_thread_mutex_lock(&self->mutex, wait);
MP_THREAD_GIL_ENTER();
if (ret == 0) {
return mp_const_false;
} else if (ret == 1) {
@ -95,7 +79,6 @@ STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) {
} else {
mp_raise_OSError(-ret);
}
#endif
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock_acquire_obj, 1, 3, thread_lock_acquire);
@ -103,9 +86,9 @@ STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) {
mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in);
// TODO check if already unlocked
self->locked = false;
#if !MICROPY_PY_THREAD_GIL
MP_THREAD_GIL_EXIT();
mp_thread_mutex_unlock(&self->mutex);
#endif
MP_THREAD_GIL_ENTER();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_release_obj, thread_lock_release);

View File

@ -635,6 +635,12 @@ typedef double mp_float_t;
#define MICROPY_PY_DESCRIPTORS (0)
#endif
// Whether to support class __delattr__ and __setattr__ methods
// This costs some code size and makes all del attrs and store attrs slow
#ifndef MICROPY_PY_DELATTR_SETATTR
#define MICROPY_PY_DELATTR_SETATTR (0)
#endif
// Support for async/await/async for/async with
#ifndef MICROPY_PY_ASYNC_AWAIT
#define MICROPY_PY_ASYNC_AWAIT (1)
@ -943,6 +949,12 @@ typedef double mp_float_t;
#define MICROPY_PY_THREAD_GIL (MICROPY_PY_THREAD)
#endif
// Number of VM jump-loops to do before releasing the GIL.
// Set this to 0 to disable the divisor.
#ifndef MICROPY_PY_THREAD_GIL_VM_DIVISOR
#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32)
#endif
// Extended modules
#ifndef MICROPY_PY_UCTYPES

View File

@ -53,7 +53,7 @@
returns sign(i - j)
assumes i, j are normalised
*/
STATIC int mpn_cmp(const mpz_dig_t *idig, mp_uint_t ilen, const mpz_dig_t *jdig, mp_uint_t jlen) {
STATIC int mpn_cmp(const mpz_dig_t *idig, size_t ilen, const mpz_dig_t *jdig, size_t jlen) {
if (ilen < jlen) { return -1; }
if (ilen > jlen) { return 1; }
@ -71,7 +71,7 @@ STATIC int mpn_cmp(const mpz_dig_t *idig, mp_uint_t ilen, const mpz_dig_t *jdig,
assumes enough memory in i; assumes normalised j; assumes n > 0
can have i, j pointing to same memory
*/
STATIC mp_uint_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mp_uint_t n) {
STATIC size_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) {
mp_uint_t n_whole = (n + DIG_SIZE - 1) / DIG_SIZE;
mp_uint_t n_part = n % DIG_SIZE;
if (n_part == 0) {
@ -84,7 +84,7 @@ STATIC mp_uint_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mp_ui
// shift the digits
mpz_dbl_dig_t d = 0;
for (mp_uint_t i = jlen; i > 0; i--, idig--, jdig--) {
for (size_t i = jlen; i > 0; i--, idig--, jdig--) {
d |= *jdig;
*idig = (d >> (DIG_SIZE - n_part)) & DIG_MASK;
d <<= DIG_SIZE;
@ -110,7 +110,7 @@ STATIC mp_uint_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mp_ui
assumes enough memory in i; assumes normalised j; assumes n > 0
can have i, j pointing to same memory
*/
STATIC mp_uint_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mp_uint_t n) {
STATIC size_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) {
mp_uint_t n_whole = n / DIG_SIZE;
mp_uint_t n_part = n % DIG_SIZE;
@ -121,7 +121,7 @@ STATIC mp_uint_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mp_ui
jdig += n_whole;
jlen -= n_whole;
for (mp_uint_t i = jlen; i > 0; i--, idig++, jdig++) {
for (size_t i = jlen; i > 0; i--, idig++, jdig++) {
mpz_dbl_dig_t d = *jdig;
if (i > 1) {
d |= (mpz_dbl_dig_t)jdig[1] << DIG_SIZE;
@ -142,7 +142,7 @@ STATIC mp_uint_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mp_ui
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen
can have i, j, k pointing to same memory
*/
STATIC mp_uint_t mpn_add(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen) {
STATIC size_t mpn_add(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) {
mpz_dig_t *oidig = idig;
mpz_dbl_dig_t carry = 0;
@ -172,7 +172,7 @@ STATIC mp_uint_t mpn_add(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen,
assumes enough memory in i; assumes normalised j, k; assumes j >= k
can have i, j, k pointing to same memory
*/
STATIC mp_uint_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen) {
STATIC size_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) {
mpz_dig_t *oidig = idig;
mpz_dbl_dig_signed_t borrow = 0;
@ -196,7 +196,7 @@ STATIC mp_uint_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen,
return idig + 1 - oidig;
}
STATIC mp_uint_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) {
STATIC size_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) {
for (--idig; idig >= oidig && *idig == 0; --idig) {
}
return idig + 1 - oidig;
@ -209,7 +209,7 @@ STATIC mp_uint_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) {
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen (jlen argument not needed)
can have i, j, k pointing to same memory
*/
STATIC mp_uint_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *kdig, mp_uint_t klen) {
STATIC size_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *kdig, size_t klen) {
mpz_dig_t *oidig = idig;
for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) {
@ -230,7 +230,7 @@ STATIC mp_uint_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t
assumes enough memory in i; assumes normalised j, k; assumes length j >= length k
can have i, j, k pointing to same memory
*/
STATIC mp_uint_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen,
STATIC size_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen,
mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) {
mpz_dig_t *oidig = idig;
mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK;
@ -261,7 +261,7 @@ STATIC mp_uint_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen
can have i, j, k pointing to same memory
*/
STATIC mp_uint_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen) {
STATIC size_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) {
mpz_dig_t *oidig = idig;
jlen -= klen;
@ -291,7 +291,7 @@ STATIC mp_uint_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen,
#if MICROPY_OPT_MPZ_BITWISE
STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen,
STATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen,
mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) {
mpz_dig_t *oidig = idig;
mpz_dbl_dig_t carryi = 1;
@ -321,7 +321,7 @@ STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jl
#else
STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen,
STATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen,
mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) {
mpz_dig_t *oidig = idig;
mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK;
@ -353,7 +353,7 @@ STATIC mp_uint_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jl
assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen
can have i, j, k pointing to same memory
*/
STATIC mp_uint_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen) {
STATIC size_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) {
mpz_dig_t *oidig = idig;
jlen -= klen;
@ -380,7 +380,7 @@ STATIC mp_uint_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen,
assumes enough memory in i; assumes normalised j, k; assumes length j >= length k
can have i, j, k pointing to same memory
*/
STATIC mp_uint_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t jlen, const mpz_dig_t *kdig, mp_uint_t klen,
STATIC size_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen,
mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) {
mpz_dig_t *oidig = idig;
@ -405,7 +405,7 @@ STATIC mp_uint_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, mp_uint_t j
returns number of digits in i
assumes enough memory in i; assumes normalised i; assumes dmul != 0
*/
STATIC mp_uint_t mpn_mul_dig_add_dig(mpz_dig_t *idig, mp_uint_t ilen, mpz_dig_t dmul, mpz_dig_t dadd) {
STATIC size_t mpn_mul_dig_add_dig(mpz_dig_t *idig, size_t ilen, mpz_dig_t dmul, mpz_dig_t dadd) {
mpz_dig_t *oidig = idig;
mpz_dbl_dig_t carry = dadd;
@ -427,15 +427,15 @@ STATIC mp_uint_t mpn_mul_dig_add_dig(mpz_dig_t *idig, mp_uint_t ilen, mpz_dig_t
assumes enough memory in i; assumes i is zeroed; assumes normalised j, k
can have j, k point to same memory
*/
STATIC mp_uint_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mpz_dig_t *kdig, mp_uint_t klen) {
STATIC size_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mpz_dig_t *kdig, size_t klen) {
mpz_dig_t *oidig = idig;
mp_uint_t ilen = 0;
size_t ilen = 0;
for (; klen > 0; --klen, ++idig, ++kdig) {
mpz_dig_t *id = idig;
mpz_dbl_dig_t carry = 0;
mp_uint_t jl = jlen;
size_t jl = jlen;
for (mpz_dig_t *jd = jdig; jl > 0; --jl, ++jd, ++id) {
carry += (mpz_dbl_dig_t)*id + (mpz_dbl_dig_t)*jd * (mpz_dbl_dig_t)*kdig; // will never overflow so long as DIG_SIZE <= 8*sizeof(mpz_dbl_dig_t)/2
*id = carry & DIG_MASK;
@ -458,7 +458,7 @@ STATIC mp_uint_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mpz_d
assumes quo_dig has enough memory (as many digits as num)
assumes quo_dig is filled with zeros
*/
STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, const mpz_dig_t *den_dig, mp_uint_t den_len, mpz_dig_t *quo_dig, mp_uint_t *quo_len) {
STATIC void mpn_div(mpz_dig_t *num_dig, size_t *num_len, const mpz_dig_t *den_dig, size_t den_len, mpz_dig_t *quo_dig, size_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;
@ -661,7 +661,7 @@ void mpz_init_from_int(mpz_t *z, mp_int_t val) {
mpz_set_from_int(z, val);
}
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, mp_uint_t alloc, mp_int_t val) {
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, size_t alloc, mp_int_t val) {
z->neg = 0;
z->fixed_dig = 1;
z->alloc = alloc;
@ -705,7 +705,7 @@ mpz_t *mpz_from_float(mp_float_t val) {
}
#endif
mpz_t *mpz_from_str(const char *str, mp_uint_t len, bool neg, mp_uint_t base) {
mpz_t *mpz_from_str(const char *str, size_t len, bool neg, unsigned int base) {
mpz_t *z = mpz_zero();
mpz_set_from_str(z, str, len, neg, base);
return z;
@ -719,7 +719,7 @@ STATIC void mpz_free(mpz_t *z) {
}
}
STATIC void mpz_need_dig(mpz_t *z, mp_uint_t need) {
STATIC void mpz_need_dig(mpz_t *z, size_t need) {
if (need < MIN_ALLOC) {
need = MIN_ALLOC;
}
@ -873,7 +873,7 @@ typedef uint32_t mp_float_int_t;
#endif
// returns number of bytes from str that were processed
mp_uint_t mpz_set_from_str(mpz_t *z, const char *str, mp_uint_t len, bool neg, mp_uint_t base) {
size_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigned int base) {
assert(base <= 36);
const char *cur = str;
@ -909,7 +909,7 @@ mp_uint_t mpz_set_from_str(mpz_t *z, const char *str, mp_uint_t len, bool neg, m
return cur - str;
}
void mpz_set_from_bytes(mpz_t *z, bool big_endian, mp_uint_t len, const byte *buf) {
void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf) {
int delta = 1;
if (big_endian) {
buf += len - 1;
@ -1151,7 +1151,7 @@ void mpz_shr_inpl(mpz_t *dest, const mpz_t *lhs, mp_uint_t rhs) {
mp_uint_t n_whole = rhs / DIG_SIZE;
mp_uint_t n_part = rhs % DIG_SIZE;
mpz_dig_t round_up = 0;
for (mp_uint_t i = 0; i < lhs->len && i < n_whole; i++) {
for (size_t i = 0; i < lhs->len && i < n_whole; i++) {
if (lhs->dig[i] != 0) {
round_up = 1;
break;
@ -1624,7 +1624,7 @@ bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) {
}
// writes at most len bytes to buf (so buf should be zeroed before calling)
void mpz_as_bytes(const mpz_t *z, bool big_endian, mp_uint_t len, byte *buf) {
void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) {
byte *b = buf;
if (big_endian) {
b += len;
@ -1633,7 +1633,7 @@ void mpz_as_bytes(const mpz_t *z, bool big_endian, mp_uint_t len, byte *buf) {
int bits = 0;
mpz_dbl_dig_t d = 0;
mpz_dbl_dig_t carry = 1;
for (mp_uint_t zlen = z->len; zlen > 0; --zlen) {
for (size_t zlen = z->len; zlen > 0; --zlen) {
bits += DIG_SIZE;
d = (d << DIG_SIZE) | *zdig++;
for (; bits >= 8; bits -= 8, d >>= 8) {
@ -1676,8 +1676,8 @@ mp_float_t mpz_as_float(const mpz_t *i) {
#if 0
this function is unused
char *mpz_as_str(const mpz_t *i, mp_uint_t base) {
char *s = m_new(char, mpz_as_str_size(i, base, NULL, '\0'));
char *mpz_as_str(const mpz_t *i, unsigned int base) {
char *s = m_new(char, mp_int_format_size(mpz_max_num_bits(i), base, NULL, '\0'));
mpz_as_str_inpl(i, base, NULL, 'a', '\0', s);
return s;
}
@ -1685,7 +1685,7 @@ char *mpz_as_str(const mpz_t *i, mp_uint_t base) {
// assumes enough space as calculated by mp_int_format_size
// returns length of string, not including null byte
mp_uint_t mpz_as_str_inpl(const mpz_t *i, mp_uint_t base, const char *prefix, char base_char, char comma, char *str) {
size_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, char base_char, char comma, char *str) {
if (str == NULL) {
return 0;
}
@ -1694,7 +1694,7 @@ mp_uint_t mpz_as_str_inpl(const mpz_t *i, mp_uint_t base, const char *prefix, ch
return 0;
}
mp_uint_t ilen = i->len;
size_t ilen = i->len;
char *s = str;
if (ilen == 0) {

View File

@ -87,10 +87,10 @@ typedef int8_t mpz_dbl_dig_signed_t;
#define MPZ_NUM_DIG_FOR_LL ((sizeof(long long) * 8 + MPZ_DIG_SIZE - 1) / MPZ_DIG_SIZE)
typedef struct _mpz_t {
mp_uint_t neg : 1;
mp_uint_t fixed_dig : 1;
mp_uint_t alloc : BITS_PER_WORD - 2;
mp_uint_t len;
size_t neg : 1;
size_t fixed_dig : 1;
size_t alloc : 8 * sizeof(size_t) - 2;
size_t len;
mpz_dig_t *dig;
} mpz_t;
@ -99,7 +99,7 @@ typedef struct _mpz_t {
void mpz_init_zero(mpz_t *z);
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, mp_uint_t dig_alloc, mp_int_t val);
void mpz_init_fixed_from_int(mpz_t *z, mpz_dig_t *dig, size_t dig_alloc, mp_int_t val);
void mpz_deinit(mpz_t *z);
void mpz_set(mpz_t *dest, const mpz_t *src);
@ -108,8 +108,8 @@ void mpz_set_from_ll(mpz_t *z, long long i, bool is_signed);
#if MICROPY_PY_BUILTINS_FLOAT
void mpz_set_from_float(mpz_t *z, mp_float_t src);
#endif
mp_uint_t mpz_set_from_str(mpz_t *z, const char *str, mp_uint_t len, bool neg, mp_uint_t base);
void mpz_set_from_bytes(mpz_t *z, bool big_endian, mp_uint_t len, const byte *buf);
size_t mpz_set_from_str(mpz_t *z, const char *str, size_t len, bool neg, unsigned int base);
void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf);
bool mpz_is_zero(const mpz_t *z);
int mpz_cmp(const mpz_t *lhs, const mpz_t *rhs);
@ -133,11 +133,10 @@ static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_
mp_int_t mpz_hash(const mpz_t *z);
bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);
bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value);
void mpz_as_bytes(const mpz_t *z, bool big_endian, mp_uint_t len, byte *buf);
void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf);
#if MICROPY_PY_BUILTINS_FLOAT
mp_float_t mpz_as_float(const mpz_t *z);
#endif
mp_uint_t mpz_as_str_size(const mpz_t *i, mp_uint_t base, const char *prefix, char comma);
mp_uint_t mpz_as_str_inpl(const mpz_t *z, mp_uint_t base, const char *prefix, char base_char, char comma, char *str);
size_t mpz_as_str_inpl(const mpz_t *z, unsigned int base, const char *prefix, char base_char, char comma, char *str);
#endif // __MICROPY_INCLUDED_PY_MPZ_H__

View File

@ -86,7 +86,7 @@ mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type) {
// wrapper that accepts n_args and n_kw in one argument
// (native emitter can only pass at most 3 arguments to a function)
mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, const mp_obj_t *args) {
mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) {
return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args);
}
@ -98,6 +98,32 @@ void mp_native_raise(mp_obj_t o) {
}
}
// wrapper that handles iterator buffer
STATIC mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) {
if (iter == NULL) {
return mp_getiter(obj, NULL);
} else {
obj = mp_getiter(obj, iter);
if (obj != MP_OBJ_FROM_PTR(iter)) {
// Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
iter->base.type = MP_OBJ_NULL;
iter->buf[0] = obj;
}
return NULL;
}
}
// wrapper that handles iterator buffer
STATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) {
mp_obj_t obj;
if (iter->base.type == MP_OBJ_NULL) {
obj = iter->buf[0];
} else {
obj = MP_OBJ_FROM_PTR(iter);
}
return mp_iternext(obj);
}
// these must correspond to the respective enum in runtime0.h
void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_convert_obj_to_native,
@ -127,8 +153,8 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_native_call_function_n_kw,
mp_call_method_n_kw,
mp_call_method_n_kw_var,
mp_getiter,
mp_iternext,
mp_native_getiter,
mp_native_iternext,
nlr_push,
nlr_pop,
mp_native_raise,

View File

@ -258,5 +258,5 @@ nlr_jump:
#endif // defined(__x86_64__) && !MICROPY_NLR_SETJMP
#if defined(linux)
.section .note.GNU-stack,"",@progbits
.section .note.GNU-stack,"",%progbits
#endif

View File

@ -191,5 +191,5 @@ nlr_jump:
#endif // defined(__i386__) && !MICROPY_NLR_SETJMP
#if defined(linux)
.section .note.GNU-stack,"",@progbits
.section .note.GNU-stack,"",%progbits
#endif

View File

@ -115,5 +115,5 @@ nlr_jump:
#endif // defined(__xtensa__)
#if defined(linux)
.section .note.GNU-stack,"",@progbits
.section .note.GNU-stack,"",%progbits
#endif

View File

@ -481,6 +481,11 @@ mp_obj_t mp_identity(mp_obj_t self) {
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity);
mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf) {
(void)iter_buf;
return self;
}
bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
mp_obj_type_t *type = mp_obj_get_type(obj);
if (type->buffer_p.get_buffer == NULL) {

View File

@ -353,11 +353,11 @@ typedef struct _mp_rom_map_elem_t {
// would also need a trucated dict structure
typedef struct _mp_map_t {
mp_uint_t all_keys_are_qstrs : 1;
mp_uint_t is_fixed : 1; // a fixed array that can't be modified; must also be ordered
mp_uint_t is_ordered : 1; // an ordered array
mp_uint_t used : (8 * sizeof(mp_uint_t) - 3);
mp_uint_t alloc;
size_t all_keys_are_qstrs : 1;
size_t is_fixed : 1; // a fixed array that can't be modified; must also be ordered
size_t is_ordered : 1; // an ordered array
size_t used : (8 * sizeof(size_t) - 3);
size_t alloc;
mp_map_elem_t *table;
} mp_map_t;
@ -371,11 +371,11 @@ typedef enum _mp_map_lookup_kind_t {
extern const mp_map_t mp_const_empty_map;
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); }
static inline bool MP_MAP_SLOT_IS_FILLED(const mp_map_t *map, size_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, mp_uint_t n);
void mp_map_init_fixed_table(mp_map_t *map, mp_uint_t n, const mp_obj_t *table);
mp_map_t *mp_map_new(mp_uint_t n);
void mp_map_init(mp_map_t *map, size_t n);
void mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table);
mp_map_t *mp_map_new(size_t n);
void mp_map_deinit(mp_map_t *map);
void mp_map_free(mp_map_t *map);
mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);
@ -385,14 +385,14 @@ void mp_map_dump(mp_map_t *map);
// Underlying set implementation (not set object)
typedef struct _mp_set_t {
mp_uint_t alloc;
mp_uint_t used;
size_t alloc;
size_t used;
mp_obj_t *table;
} mp_set_t;
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); }
static inline bool MP_SET_SLOT_IS_FILLED(const mp_set_t *set, size_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); }
void mp_set_init(mp_set_t *set, mp_uint_t n);
void mp_set_init(mp_set_t *set, size_t n);
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);
mp_obj_t mp_set_remove_first(mp_set_t *set);
void mp_set_clear(mp_set_t *set);
@ -417,6 +417,11 @@ typedef enum {
PRINT_EXC_SUBCLASS = 0x80, // Internal flag for printing exception subclasses
} mp_print_kind_t;
typedef struct _mp_obj_iter_buf_t {
mp_obj_base_t base;
mp_obj_t buf[3];
} mp_obj_iter_buf_t;
typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);
typedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);
@ -424,6 +429,7 @@ typedef mp_obj_t (*mp_unary_op_fun_t)(mp_uint_t op, mp_obj_t);
typedef mp_obj_t (*mp_binary_op_fun_t)(mp_uint_t op, mp_obj_t, mp_obj_t);
typedef void (*mp_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
typedef mp_obj_t (*mp_subscr_fun_t)(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
typedef mp_obj_t (*mp_getiter_fun_t)(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf);
// Buffer protocol
typedef struct _mp_buffer_info_t {
@ -486,7 +492,11 @@ struct _mp_obj_type_t {
// value=MP_OBJ_NULL means delete, value=MP_OBJ_SENTINEL means load, else store
// can return MP_OBJ_NULL if op not supported
mp_fun_1_t getiter; // corresponds to __iter__ special method
// corresponds to __iter__ special method
// can use given mp_obj_iter_buf_t to store iterator
// otherwise can return a pointer to an object on the heap
mp_getiter_fun_t getiter;
mp_fun_1_t iternext; // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raising StopIteration() (with no args)
mp_buffer_p_t buffer_p;
@ -607,39 +617,39 @@ static inline mp_obj_t mp_obj_new_bool(mp_int_t x) { return x ? mp_const_true :
mp_obj_t mp_obj_new_cell(mp_obj_t obj);
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, mp_uint_t len, bool neg, mp_uint_t base);
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int 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_int_from_ull(unsigned 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, mp_uint_t len, bool make_qstr_if_not_already);
mp_obj_t mp_obj_new_str(const char* data, size_t len, bool make_qstr_if_not_already);
mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr);
mp_obj_t mp_obj_new_bytes(const byte* data, mp_uint_t len);
mp_obj_t mp_obj_new_bytearray(mp_uint_t n, void *items);
mp_obj_t mp_obj_new_bytearray_by_ref(mp_uint_t n, void *items);
mp_obj_t mp_obj_new_bytes(const byte* data, size_t len);
mp_obj_t mp_obj_new_bytearray(size_t n, void *items);
mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items);
#if MICROPY_PY_BUILTINS_FLOAT
mp_obj_t mp_obj_new_int_from_float(mp_float_t val);
mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag);
#endif
mp_obj_t mp_obj_new_exception(const mp_obj_type_t *exc_type);
mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg);
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, mp_uint_t n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg);
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!)
mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table);
mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const void *fun_data, const mp_uint_t *const_table);
mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig);
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig);
mp_obj_t mp_obj_new_fun_viper(size_t n_args, void *fun_data, mp_uint_t type_sig);
mp_obj_t mp_obj_new_fun_asm(size_t n_args, void *fun_data, mp_uint_t type_sig);
mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun);
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_uint_t n_closed, const mp_obj_t *closed);
mp_obj_t mp_obj_new_tuple(mp_uint_t n, const mp_obj_t *items);
mp_obj_t mp_obj_new_list(mp_uint_t n, mp_obj_t *items);
mp_obj_t mp_obj_new_dict(mp_uint_t n_args);
mp_obj_t mp_obj_new_set(mp_uint_t n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed, const mp_obj_t *closed);
mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items);
mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items);
mp_obj_t mp_obj_new_dict(size_t n_args);
mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj);
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args);
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf);
mp_obj_t mp_obj_new_module(qstr module_name);
mp_obj_t mp_obj_new_memoryview(byte typecode, mp_uint_t nitems, void *items);
mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items);
mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in);
const char *mp_obj_get_type_str(mp_const_obj_t o_in);
@ -700,7 +710,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, mp_uint_t *len);
mp_obj_t mp_obj_str_intern(mp_obj_t str);
void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, mp_uint_t str_len, bool is_bytes);
void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes);
#if MICROPY_PY_BUILTINS_FLOAT
// float
@ -720,11 +730,11 @@ mp_int_t mp_obj_tuple_hash(mp_obj_t self_in);
// list
struct _mp_obj_list_t;
void mp_obj_list_init(struct _mp_obj_list_t *o, mp_uint_t n);
void mp_obj_list_init(struct _mp_obj_list_t *o, size_t n);
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value);
void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items);
void mp_obj_list_set_len(mp_obj_t self_in, mp_uint_t len);
void mp_obj_list_set_len(mp_obj_t self_in, size_t len);
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
@ -733,8 +743,8 @@ typedef struct _mp_obj_dict_t {
mp_obj_base_t base;
mp_map_t map;
} mp_obj_dict_t;
void mp_obj_dict_init(mp_obj_dict_t *dict, mp_uint_t n_args);
mp_uint_t mp_obj_dict_len(mp_obj_t self_in);
void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args);
size_t mp_obj_dict_len(mp_obj_t self_in);
mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index);
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value);
mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key);
@ -775,6 +785,7 @@ qstr mp_obj_code_get_name(const byte *code_info);
mp_obj_t mp_identity(mp_obj_t self);
MP_DECLARE_CONST_FUN_OBJ_1(mp_identity_obj);
mp_obj_t mp_identity_getiter(mp_obj_t self, mp_obj_iter_buf_t *iter_buf);
// module
typedef struct _mp_obj_module_t {

View File

@ -56,10 +56,10 @@
#if MICROPY_PY_BUILTINS_MEMORYVIEW
#define TYPECODE_MASK (0x7f)
#else
#define TYPECODE_MASK (~(mp_uint_t)0)
#define TYPECODE_MASK (~(size_t)0)
#endif
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in);
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf);
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);
STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in);
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
@ -78,7 +78,7 @@ STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
mp_printf(print, "array('%c'", o->typecode);
if (o->len > 0) {
mp_print_str(print, ", [");
for (mp_uint_t i = 0; i < o->len; i++) {
for (size_t i = 0; i < o->len; i++) {
if (i > 0) {
mp_print_str(print, ", ");
}
@ -92,7 +92,7 @@ STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
#endif
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) {
STATIC mp_obj_array_t *array_new(char typecode, size_t n) {
int typecode_size = mp_binary_get_size('@', typecode, NULL);
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
#if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY
@ -124,13 +124,13 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
// construct array from raw bytes
// we round-down the len to make it a multiple of sz (CPython raises error)
size_t sz = mp_binary_get_size('@', typecode, NULL);
mp_uint_t len = bufinfo.len / sz;
size_t len = bufinfo.len / sz;
mp_obj_array_t *o = array_new(typecode, len);
memcpy(o->items, bufinfo.buf, len * sz);
return MP_OBJ_FROM_PTR(o);
}
mp_uint_t len;
size_t len;
// Try to create array of exact len if initializer len is known
mp_obj_t len_in = mp_obj_len_maybe(initializer);
if (len_in == MP_OBJ_NULL) {
@ -141,9 +141,9 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
mp_obj_array_t *array = array_new(typecode, len);
mp_obj_t iterable = mp_getiter(initializer);
mp_obj_t iterable = mp_getiter(initializer, NULL);
mp_obj_t item;
mp_uint_t i = 0;
size_t i = 0;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (len == 0) {
array_append(MP_OBJ_FROM_PTR(array), item);
@ -198,7 +198,7 @@ STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args,
#if MICROPY_PY_BUILTINS_MEMORYVIEW
mp_obj_t mp_obj_new_memoryview(byte typecode, mp_uint_t nitems, void *items) {
mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items) {
mp_obj_array_t *self = m_new_obj(mp_obj_array_t);
self->base.type = &mp_type_memoryview;
self->typecode = typecode;
@ -254,7 +254,7 @@ STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
size_t sz = mp_binary_get_size('@', lhs_bufinfo.typecode, NULL);
// convert byte count to element count (in case rhs is not multiple of sz)
mp_uint_t rhs_len = rhs_bufinfo.len / sz;
size_t rhs_len = rhs_bufinfo.len / sz;
// note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count
mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len);
@ -345,7 +345,7 @@ STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) {
size_t sz = mp_binary_get_size('@', self->typecode, NULL);
// convert byte count to element count
mp_uint_t len = arg_bufinfo.len / sz;
size_t len = arg_bufinfo.len / sz;
// make sure we have enough room to extend
// TODO: alloc policy; at the moment we go conservative
@ -384,7 +384,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
if (value != MP_OBJ_SENTINEL) {
#if MICROPY_PY_ARRAY_SLICE_ASSIGN
// Assign
mp_uint_t src_len;
size_t src_len;
void *src_items;
size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
if (MP_OBJ_IS_OBJ(value) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(value))->type->subscr == array_subscr) {
@ -501,7 +501,7 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui
// read-only memoryview
return 1;
}
bufinfo->buf = (uint8_t*)bufinfo->buf + (mp_uint_t)o->free * sz;
bufinfo->buf = (uint8_t*)bufinfo->buf + (size_t)o->free * sz;
}
#else
(void)flags;
@ -562,20 +562,20 @@ const mp_obj_type_t mp_type_memoryview = {
#endif
/* unused
mp_uint_t mp_obj_array_len(mp_obj_t self_in) {
size_t mp_obj_array_len(mp_obj_t self_in) {
return ((mp_obj_array_t *)self_in)->len;
}
*/
#if MICROPY_PY_BUILTINS_BYTEARRAY
mp_obj_t mp_obj_new_bytearray(mp_uint_t n, void *items) {
mp_obj_t mp_obj_new_bytearray(size_t n, void *items) {
mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n);
memcpy(o->items, items, n);
return MP_OBJ_FROM_PTR(o);
}
// Create bytearray which references specified memory area
mp_obj_t mp_obj_new_bytearray_by_ref(mp_uint_t n, void *items) {
mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items) {
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
o->base.type = &mp_type_bytearray;
o->typecode = BYTEARRAY_TYPECODE;
@ -592,8 +592,8 @@ mp_obj_t mp_obj_new_bytearray_by_ref(mp_uint_t n, void *items) {
typedef struct _mp_obj_array_it_t {
mp_obj_base_t base;
mp_obj_array_t *array;
mp_uint_t offset;
mp_uint_t cur;
size_t offset;
size_t cur;
} mp_obj_array_it_t;
STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
@ -608,15 +608,18 @@ STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
STATIC const mp_obj_type_t array_it_type = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = array_it_iternext,
};
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_array_t *array = MP_OBJ_TO_PTR(array_in);
mp_obj_array_it_t *o = m_new0(mp_obj_array_it_t, 1);
mp_obj_array_it_t *o = (mp_obj_array_it_t*)iter_buf;
o->base.type = &array_it_type;
o->array = array;
o->offset = 0;
o->cur = 0;
#if MICROPY_PY_BUILTINS_MEMORYVIEW
if (array->base.type == &mp_type_memoryview) {
o->offset = array->free;

View File

@ -32,11 +32,11 @@
typedef struct _mp_obj_array_t {
mp_obj_base_t base;
mp_uint_t typecode : 8;
size_t typecode : 8;
// free is number of unused elements after len used elements
// alloc size = len + free
mp_uint_t free : (8 * sizeof(mp_uint_t) - 8);
mp_uint_t len; // in elements
size_t free : (8 * sizeof(size_t) - 8);
size_t len; // in elements
void *items;
} mp_obj_array_t;

View File

@ -34,7 +34,7 @@ STATIC
#endif
void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o) {
mp_print_str(print, "(");
for (mp_uint_t i = 0; i < o->len; i++) {
for (size_t i = 0; i < o->len; i++) {
if (i > 0) {
mp_print_str(print, ", ");
}
@ -59,9 +59,9 @@ STATIC void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
if (dest[0] == MP_OBJ_NULL) {
// load attribute
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
mp_uint_t len = self->len;
size_t len = self->len;
const qstr *fields = (const qstr*)MP_OBJ_TO_PTR(self->items[len]);
for (mp_uint_t i = 0; i < len; i++) {
for (size_t i = 0; i < len; i++) {
if (fields[i] == attr) {
dest[0] = self->items[i];
return;
@ -70,11 +70,11 @@ STATIC void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
}
}
mp_obj_t mp_obj_new_attrtuple(const qstr *fields, mp_uint_t n, const mp_obj_t *items) {
mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items) {
mp_obj_tuple_t *o = m_new_obj_var(mp_obj_tuple_t, mp_obj_t, n + 1);
o->base.type = &mp_type_attrtuple;
o->len = n;
for (mp_uint_t i = 0; i < n; i++) {
for (size_t i = 0; i < n; i++) {
o->items[i] = items[i];
}
o->items[n] = MP_OBJ_FROM_PTR(fields);

View File

@ -32,7 +32,7 @@
typedef struct _mp_obj_closure_t {
mp_obj_base_t base;
mp_obj_t fun;
mp_uint_t n_closed;
size_t n_closed;
mp_obj_t closed[];
} mp_obj_closure_t;
@ -41,7 +41,7 @@ STATIC mp_obj_t closure_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
// need to concatenate closed-over-vars and args
mp_uint_t n_total = self->n_closed + n_args + 2 * n_kw;
size_t n_total = self->n_closed + n_args + 2 * n_kw;
if (n_total <= 5) {
// use stack to allocate temporary args array
mp_obj_t args2[5];
@ -66,7 +66,7 @@ STATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_
mp_print_str(print, "<closure ");
mp_obj_print_helper(print, o->fun, PRINT_REPR);
mp_printf(print, " at %p, n_closed=%u ", o, (int)o->n_closed);
for (mp_uint_t i = 0; i < o->n_closed; i++) {
for (size_t i = 0; i < o->n_closed; i++) {
if (o->closed[i] == MP_OBJ_NULL) {
mp_print_str(print, "(nil)");
} else {
@ -87,7 +87,7 @@ const mp_obj_type_t closure_type = {
.call = closure_call,
};
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_uint_t n_closed_over, const mp_obj_t *closed) {
mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed_over, const mp_obj_t *closed) {
mp_obj_closure_t *o = m_new_obj_var(mp_obj_closure_t, mp_obj_t, n_closed_over);
o->base.type = &closure_type;
o->fun = fun;

View File

@ -41,11 +41,11 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg
// This is a helper function to iterate through a dictionary. The state of
// the iteration is held in *cur and should be initialised with zero for the
// first call. Will return NULL when no more elements are available.
STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, mp_uint_t *cur) {
mp_uint_t max = dict->map.alloc;
STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) {
size_t max = dict->map.alloc;
mp_map_t *map = &dict->map;
for (mp_uint_t i = *cur; i < max; i++) {
for (size_t i = *cur; i < max; i++) {
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
*cur = i + 1;
return &(map->table[i]);
@ -65,7 +65,7 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_
mp_printf(print, "%q(", self->base.type->name);
}
mp_print_str(print, "{");
mp_uint_t cur = 0;
size_t cur = 0;
mp_map_elem_t *next = NULL;
while ((next = dict_iter_next(self, &cur)) != NULL) {
if (!first) {
@ -121,7 +121,7 @@ STATIC mp_obj_t dict_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
if (MP_UNLIKELY(MP_OBJ_IS_TYPE(lhs_in, &mp_type_ordereddict) && MP_OBJ_IS_TYPE(rhs_in, &mp_type_ordereddict))) {
// Iterate through both dictionaries simultaneously and compare keys and values.
mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in);
mp_uint_t c1 = 0, c2 = 0;
size_t c1 = 0, c2 = 0;
mp_map_elem_t *e1 = dict_iter_next(o, &c1), *e2 = dict_iter_next(rhs, &c2);
for (; e1 != NULL && e2 != NULL; e1 = dict_iter_next(o, &c1), e2 = dict_iter_next(rhs, &c2)) {
if (!mp_obj_equal(e1->key, e2->key) || !mp_obj_equal(e1->value, e2->value)) {
@ -137,7 +137,7 @@ STATIC mp_obj_t dict_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
return mp_const_false;
}
mp_uint_t cur = 0;
size_t cur = 0;
mp_map_elem_t *next = NULL;
while ((next = dict_iter_next(o, &cur)) != NULL) {
mp_map_elem_t *elem = mp_map_lookup(&rhs->map, next->key, MP_MAP_LOOKUP);
@ -196,7 +196,7 @@ typedef struct _mp_obj_dict_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
mp_obj_t dict;
mp_uint_t cur;
size_t cur;
} mp_obj_dict_it_t;
STATIC mp_obj_t dict_it_iternext(mp_obj_t self_in) {
@ -210,8 +210,9 @@ STATIC mp_obj_t dict_it_iternext(mp_obj_t self_in) {
}
}
STATIC mp_obj_t dict_getiter(mp_obj_t self_in) {
mp_obj_dict_it_t *o = m_new_obj(mp_obj_dict_it_t);
STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_dict_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_dict_it_t *o = (mp_obj_dict_it_t*)iter_buf;
o->base.type = &mp_type_polymorph_iter;
o->iternext = dict_it_iternext;
o->dict = self_in;
@ -249,7 +250,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy);
// this is a classmethod
STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) {
mp_obj_t iter = mp_getiter(args[1]);
mp_obj_t iter = mp_getiter(args[1], NULL);
mp_obj_t value = mp_const_none;
mp_obj_t next = MP_OBJ_NULL;
@ -340,7 +341,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde
STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
mp_check_self(MP_OBJ_IS_DICT_TYPE(self_in));
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
mp_uint_t cur = 0;
size_t cur = 0;
mp_map_elem_t *next = dict_iter_next(self, &cur);
if (next == NULL) {
mp_raise_msg(&mp_type_KeyError, "popitem(): dictionary is empty");
@ -367,7 +368,7 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg
if (MP_OBJ_IS_DICT_TYPE(args[1])) {
// update from other dictionary (make sure other is not self)
if (args[1] != args[0]) {
mp_uint_t cur = 0;
size_t cur = 0;
mp_map_elem_t *elem = NULL;
while ((elem = dict_iter_next((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[1]), &cur)) != NULL) {
mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value;
@ -375,10 +376,10 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg
}
} else {
// update from a generic iterable of pairs
mp_obj_t iter = mp_getiter(args[1]);
mp_obj_t iter = mp_getiter(args[1], NULL);
mp_obj_t next = MP_OBJ_NULL;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
mp_obj_t inneriter = mp_getiter(next);
mp_obj_t inneriter = mp_getiter(next, NULL);
mp_obj_t key = mp_iternext(inneriter);
mp_obj_t value = mp_iternext(inneriter);
mp_obj_t stop = mp_iternext(inneriter);
@ -394,7 +395,7 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg
}
// update the dict with any keyword args
for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
for (size_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;
}
@ -423,7 +424,7 @@ typedef struct _mp_obj_dict_view_it_t {
mp_obj_base_t base;
mp_dict_view_kind_t kind;
mp_obj_t dict;
mp_uint_t cur;
size_t cur;
} mp_obj_dict_view_it_t;
typedef struct _mp_obj_dict_view_t {
@ -457,14 +458,15 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
STATIC const mp_obj_type_t dict_view_it_type = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = dict_view_it_iternext,
};
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_check_self(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in);
mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t);
mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t*)iter_buf;
o->base.type = &dict_view_it_type;
o->kind = view->kind;
o->dict = view->dict;
@ -479,7 +481,8 @@ STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
bool first = true;
mp_print_str(print, mp_dict_view_names[self->kind]);
mp_print_str(print, "([");
mp_obj_t self_iter = dict_view_getiter(self_in);
mp_obj_iter_buf_t iter_buf;
mp_obj_t self_iter = dict_view_getiter(self_in, &iter_buf);
mp_obj_t next = MP_OBJ_NULL;
while ((next = dict_view_it_iternext(self_iter)) != MP_OBJ_STOP_ITERATION) {
if (!first) {
@ -590,18 +593,18 @@ const mp_obj_type_t mp_type_ordereddict = {
};
#endif
void mp_obj_dict_init(mp_obj_dict_t *dict, mp_uint_t n_args) {
void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args) {
dict->base.type = &mp_type_dict;
mp_map_init(&dict->map, n_args);
}
mp_obj_t mp_obj_new_dict(mp_uint_t n_args) {
mp_obj_t mp_obj_new_dict(size_t n_args) {
mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);
mp_obj_dict_init(o, n_args);
return MP_OBJ_FROM_PTR(o);
}
mp_uint_t mp_obj_dict_len(mp_obj_t self_in) {
size_t mp_obj_dict_len(mp_obj_t self_in) {
mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
return self->map.used;
}

View File

@ -56,13 +56,13 @@ STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, siz
// create enumerate object
mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);
o->base.type = type;
o->iter = mp_getiter(arg_vals.iterable.u_obj);
o->iter = mp_getiter(arg_vals.iterable.u_obj, NULL);
o->cur = arg_vals.start.u_int;
#else
(void)n_kw;
mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);
o->base.type = type;
o->iter = mp_getiter(args[0]);
o->iter = mp_getiter(args[0], NULL);
o->cur = n_args > 1 ? mp_obj_get_int(args[1]) : 0;
#endif
@ -74,7 +74,7 @@ const mp_obj_type_t mp_type_enumerate = {
.name = MP_QSTR_enumerate,
.make_new = enumerate_make_new,
.iternext = enumerate_iternext,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
};
STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) {

View File

@ -312,7 +312,7 @@ mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg)
return mp_obj_new_exception_args(exc_type, 1, &arg);
}
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, mp_uint_t n_args, const mp_obj_t *args) {
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, const mp_obj_t *args) {
assert(exc_type->make_new == mp_obj_exception_make_new);
return exc_type->make_new(exc_type, n_args, 0, args);
}

View File

@ -31,8 +31,8 @@
typedef struct _mp_obj_exception_t {
mp_obj_base_t base;
mp_uint_t traceback_alloc : (BITS_PER_WORD / 2);
mp_uint_t traceback_len : (BITS_PER_WORD / 2);
size_t traceback_alloc : (8 * sizeof(size_t) / 2);
size_t traceback_len : (8 * sizeof(size_t) / 2);
size_t *traceback_data;
mp_obj_tuple_t *args;
} mp_obj_exception_t;

View File

@ -39,7 +39,7 @@ STATIC mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t
mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t);
o->base.type = type;
o->fun = args[0];
o->iter = mp_getiter(args[1]);
o->iter = mp_getiter(args[1], NULL);
return MP_OBJ_FROM_PTR(o);
}
@ -65,7 +65,7 @@ const mp_obj_type_t mp_type_filter = {
{ &mp_type_type },
.name = MP_QSTR_filter,
.make_new = filter_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = filter_iternext,
};

View File

@ -181,9 +181,9 @@ STATIC void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
#endif
#if DEBUG_PRINT
STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) {
STATIC void dump_args(const mp_obj_t *a, size_t sz) {
DEBUG_printf("%p: ", a);
for (mp_uint_t i = 0; i < sz; i++) {
for (size_t i = 0; i < sz; i++) {
DEBUG_printf("%p ", a[i]);
}
DEBUG_printf("\n");
@ -247,15 +247,15 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
const byte *ip = self->bytecode;
// bytecode prelude: state size and exception stack size
mp_uint_t n_state = mp_decode_uint(&ip);
mp_uint_t n_exc_stack = mp_decode_uint(&ip);
size_t n_state = mp_decode_uint(&ip);
size_t n_exc_stack = mp_decode_uint(&ip);
#if VM_DETECT_STACK_OVERFLOW
n_state += 1;
#endif
// allocate state for locals and stack
mp_uint_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
mp_code_state_t *code_state = NULL;
if (state_size > VM_MAX_STATE_ON_STACK) {
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
@ -288,7 +288,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
if (!(vm_return_kind == MP_VM_RETURN_EXCEPTION && self->n_pos_args + self->n_kwonly_args == 0)) {
// Just check to see that we have at least 1 null object left in the state.
bool overflow = true;
for (mp_uint_t i = 0; i < n_state - self->n_pos_args - self->n_kwonly_args; i++) {
for (size_t i = 0; i < n_state - self->n_pos_args - self->n_kwonly_args; i++) {
if (code_state->state[i] == MP_OBJ_NULL) {
overflow = false;
break;
@ -350,8 +350,8 @@ const mp_obj_type_t mp_type_fun_bc = {
};
mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table) {
mp_uint_t n_def_args = 0;
mp_uint_t n_extra_args = 0;
size_t n_def_args = 0;
size_t n_extra_args = 0;
mp_obj_tuple_t *def_args = MP_OBJ_TO_PTR(def_args_in);
if (def_args_in != MP_OBJ_NULL) {
assert(MP_OBJ_IS_TYPE(def_args_in, &mp_type_tuple));
@ -409,7 +409,7 @@ mp_obj_t mp_obj_new_fun_native(mp_obj_t def_args_in, mp_obj_t def_kw_args, const
typedef struct _mp_obj_fun_viper_t {
mp_obj_base_t base;
mp_uint_t n_args;
size_t n_args;
void *fun_data; // GC must be able to trace this pointer
mp_uint_t type_sig;
} mp_obj_fun_viper_t;
@ -457,7 +457,7 @@ STATIC const mp_obj_type_t mp_type_fun_viper = {
.unary_op = mp_generic_unary_op,
};
mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig) {
mp_obj_t mp_obj_new_fun_viper(size_t n_args, void *fun_data, mp_uint_t type_sig) {
mp_obj_fun_viper_t *o = m_new_obj(mp_obj_fun_viper_t);
o->base.type = &mp_type_fun_viper;
o->n_args = n_args;
@ -475,7 +475,7 @@ mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_s
typedef struct _mp_obj_fun_asm_t {
mp_obj_base_t base;
mp_uint_t n_args;
size_t n_args;
void *fun_data; // GC must be able to trace this pointer
mp_uint_t type_sig;
} mp_obj_fun_asm_t;
@ -573,7 +573,7 @@ STATIC const mp_obj_type_t mp_type_fun_asm = {
.unary_op = mp_generic_unary_op,
};
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig) {
mp_obj_t mp_obj_new_fun_asm(size_t n_args, void *fun_data, mp_uint_t type_sig) {
mp_obj_fun_asm_t *o = m_new_obj(mp_obj_fun_asm_t);
o->base.type = &mp_type_fun_asm;
o->n_args = n_args;

View File

@ -236,7 +236,7 @@ const mp_obj_type_t mp_type_gen_instance = {
{ &mp_type_type },
.name = MP_QSTR_generator,
.print = gen_instance_print,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = gen_instance_iternext,
.locals_dict = (mp_obj_dict_t*)&gen_instance_locals_dict,
};

View File

@ -61,13 +61,14 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) {
STATIC const mp_obj_type_t it_type = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = it_iternext,
};
// args are those returned from mp_load_method_maybe (ie either an attribute or a method)
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args) {
mp_obj_getitem_iter_t *o = m_new_obj(mp_obj_getitem_iter_t);
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_getitem_iter_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_getitem_iter_t *o = (mp_obj_getitem_iter_t*)iter_buf;
o->base.type = &it_type;
o->args[0] = args[0];
o->args[1] = args[1];

View File

@ -291,7 +291,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
}
// This is called only with strings whose value doesn't fit in SMALL_INT
mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base) {
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
mp_raise_msg(&mp_type_OverflowError, "long int not supported in this build");
return mp_const_none;
}

View File

@ -273,7 +273,7 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
}
#endif
mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base) {
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
// TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated
// TODO check overflow
mp_obj_int_t *o = m_new_obj(mp_obj_int_t);

View File

@ -407,9 +407,9 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
}
#endif
mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base) {
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
mp_obj_int_t *o = mp_obj_int_new_mpz();
mp_uint_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);
size_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);
*str += n;
return MP_OBJ_FROM_PTR(o);
}

View File

@ -33,8 +33,8 @@
#include "py/runtime.h"
#include "py/stackctrl.h"
STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, mp_uint_t cur);
STATIC mp_obj_list_t *list_new(mp_uint_t n);
STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf);
STATIC mp_obj_list_t *list_new(size_t n);
STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in);
STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args);
@ -50,7 +50,7 @@ STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k
kind = PRINT_REPR;
}
mp_print_str(print, "[");
for (mp_uint_t i = 0; i < o->len; i++) {
for (size_t i = 0; i < o->len; i++) {
if (i > 0) {
mp_print_str(print, ", ");
}
@ -60,7 +60,7 @@ STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k
}
STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) {
mp_obj_t iter = mp_getiter(iterable);
mp_obj_t iter = mp_getiter(iterable, NULL);
mp_obj_t item;
while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
mp_obj_list_append(list, item);
@ -225,8 +225,8 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
}
}
STATIC mp_obj_t list_getiter(mp_obj_t o_in) {
return mp_obj_new_list_iterator(o_in, 0);
STATIC mp_obj_t list_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
return mp_obj_new_list_iterator(o_in, 0, iter_buf);
}
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
@ -374,7 +374,7 @@ STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {
if (index < 0) {
index = 0;
}
if ((mp_uint_t)index > self->len) {
if ((size_t)index > self->len) {
index = self->len;
}
@ -451,7 +451,7 @@ const mp_obj_type_t mp_type_list = {
.locals_dict = (mp_obj_dict_t*)&list_locals_dict,
};
void mp_obj_list_init(mp_obj_list_t *o, mp_uint_t n) {
void mp_obj_list_init(mp_obj_list_t *o, size_t n) {
o->base.type = &mp_type_list;
o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n;
o->len = n;
@ -459,16 +459,16 @@ void mp_obj_list_init(mp_obj_list_t *o, mp_uint_t n) {
mp_seq_clear(o->items, n, o->alloc, sizeof(*o->items));
}
STATIC mp_obj_list_t *list_new(mp_uint_t n) {
STATIC mp_obj_list_t *list_new(size_t n) {
mp_obj_list_t *o = m_new_obj(mp_obj_list_t);
mp_obj_list_init(o, n);
return o;
}
mp_obj_t mp_obj_new_list(mp_uint_t n, mp_obj_t *items) {
mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items) {
mp_obj_list_t *o = list_new(n);
if (items != NULL) {
for (mp_uint_t i = 0; i < n; i++) {
for (size_t i = 0; i < n; i++) {
o->items[i] = items[i];
}
}
@ -481,7 +481,7 @@ void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
*items = self->items;
}
void mp_obj_list_set_len(mp_obj_t self_in, mp_uint_t len) {
void mp_obj_list_set_len(mp_obj_t self_in, size_t len) {
// trust that the caller knows what it's doing
// TODO realloc if len got much smaller than alloc
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
@ -501,7 +501,7 @@ typedef struct _mp_obj_list_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
mp_obj_t list;
mp_uint_t cur;
size_t cur;
} mp_obj_list_it_t;
STATIC mp_obj_t list_it_iternext(mp_obj_t self_in) {
@ -516,8 +516,9 @@ STATIC mp_obj_t list_it_iternext(mp_obj_t self_in) {
}
}
mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, mp_uint_t cur) {
mp_obj_list_it_t *o = m_new_obj(mp_obj_list_it_t);
mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_list_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_list_it_t *o = (mp_obj_list_it_t*)iter_buf;
o->base.type = &mp_type_polymorph_iter;
o->iternext = list_it_iternext;
o->list = list;

View File

@ -30,8 +30,8 @@
typedef struct _mp_obj_list_t {
mp_obj_base_t base;
mp_uint_t alloc;
mp_uint_t len;
size_t alloc;
size_t len;
mp_obj_t *items;
} mp_obj_list_t;

View File

@ -43,7 +43,7 @@ STATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
o->n_iters = n_args - 1;
o->fun = args[0];
for (mp_uint_t i = 0; i < n_args - 1; i++) {
o->iters[i] = mp_getiter(args[i + 1]);
o->iters[i] = mp_getiter(args[i + 1], NULL);
}
return MP_OBJ_FROM_PTR(o);
}
@ -68,6 +68,6 @@ const mp_obj_type_t mp_type_map = {
{ &mp_type_type },
.name = MP_QSTR_map,
.make_new = map_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = map_iternext,
};

View File

@ -49,6 +49,6 @@ STATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) {
const mp_obj_type_t mp_type_polymorph_iter = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = polymorph_it_iternext,
};

View File

@ -55,12 +55,13 @@ STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {
STATIC const mp_obj_type_t range_it_type = {
{ &mp_type_type },
.name = MP_QSTR_iterator,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = range_it_iternext,
};
STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step) {
mp_obj_range_it_t *o = m_new_obj(mp_obj_range_it_t);
STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_range_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_range_it_t *o = (mp_obj_range_it_t*)iter_buf;
o->base.type = &range_it_type;
o->cur = cur;
o->stop = stop;
@ -161,9 +162,9 @@ STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
}
}
STATIC mp_obj_t range_getiter(mp_obj_t o_in) {
STATIC mp_obj_t range_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in);
return mp_obj_new_range_iterator(o->start, o->stop, o->step);
return mp_obj_new_range_iterator(o->start, o->stop, o->step, iter_buf);
}

View File

@ -74,7 +74,7 @@ const mp_obj_type_t mp_type_reversed = {
{ &mp_type_type },
.name = MP_QSTR_reversed,
.make_new = reversed_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = reversed_iternext,
};

View File

@ -44,7 +44,7 @@ typedef struct _mp_obj_set_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
mp_obj_set_t *set;
mp_uint_t cur;
size_t cur;
} mp_obj_set_it_t;
STATIC mp_obj_t set_it_iternext(mp_obj_t self_in);
@ -96,7 +96,7 @@ STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
}
#endif
mp_print_str(print, "{");
for (mp_uint_t i = 0; i < self->set.alloc; i++) {
for (size_t i = 0; i < self->set.alloc; i++) {
if (MP_SET_SLOT_IS_FILLED(&self->set, i)) {
if (!first) {
mp_print_str(print, ", ");
@ -129,7 +129,7 @@ STATIC mp_obj_t set_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
default: { // can only be 0 or 1 arg
// 1 argument, an iterable from which we make a new set
mp_obj_t set = mp_obj_new_set(0, NULL);
mp_obj_t iterable = mp_getiter(args[0]);
mp_obj_t iterable = mp_getiter(args[0], NULL);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
mp_obj_set_store(set, item);
@ -143,10 +143,10 @@ STATIC mp_obj_t set_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
mp_obj_set_it_t *self = MP_OBJ_TO_PTR(self_in);
mp_uint_t max = self->set->set.alloc;
size_t max = self->set->set.alloc;
mp_set_t *set = &self->set->set;
for (mp_uint_t i = self->cur; i < max; i++) {
for (size_t i = self->cur; i < max; i++) {
if (MP_SET_SLOT_IS_FILLED(set, i)) {
self->cur = i + 1;
return set->table[i];
@ -156,8 +156,9 @@ STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
return MP_OBJ_STOP_ITERATION;
}
STATIC mp_obj_t set_getiter(mp_obj_t set_in) {
mp_obj_set_it_t *o = m_new_obj(mp_obj_set_it_t);
STATIC mp_obj_t set_getiter(mp_obj_t set_in, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_set_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_set_it_t *o = (mp_obj_set_it_t*)iter_buf;
o->base.type = &mp_type_polymorph_iter;
o->iternext = set_it_iternext;
o->set = (mp_obj_set_t *)MP_OBJ_TO_PTR(set_in);
@ -228,12 +229,12 @@ STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) {
}
for (mp_uint_t i = 1; i < n_args; i++) {
for (size_t i = 1; i < n_args; i++) {
mp_obj_t other = args[i];
if (self == other) {
set_clear(self);
} else {
mp_obj_t iter = mp_getiter(other);
mp_obj_t iter = mp_getiter(other, NULL);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
set_discard(self, next);
@ -270,7 +271,7 @@ STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update)
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_set_t *out = MP_OBJ_TO_PTR(mp_obj_new_set(0, NULL));
mp_obj_t iter = mp_getiter(other);
mp_obj_t iter = mp_getiter(other, NULL);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
@ -302,7 +303,8 @@ STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) {
check_set_or_frozenset(self_in);
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_t iter = mp_getiter(other);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iter = mp_getiter(other, &iter_buf);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
@ -335,7 +337,8 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
if (proper && self->set.used == other->set.used) {
out = false;
} else {
mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self));
mp_obj_iter_buf_t iter_buf;
mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self), &iter_buf);
mp_obj_t next;
while ((next = set_it_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {
@ -408,7 +411,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove);
STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) {
check_set(self_in);
mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_t iter = mp_getiter(other_in);
mp_obj_t iter = mp_getiter(other_in, NULL);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND_OR_REMOVE_IF_FOUND);
@ -427,7 +430,7 @@ STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference);
STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {
mp_obj_t iter = mp_getiter(other_in);
mp_obj_t iter = mp_getiter(other_in, NULL);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
@ -436,7 +439,7 @@ STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {
STATIC mp_obj_t set_update(size_t n_args, const mp_obj_t *args) {
check_set(args[0]);
for (mp_uint_t i = 1; i < n_args; i++) {
for (size_t i = 1; i < n_args; i++) {
set_update_int(MP_OBJ_TO_PTR(args[0]), args[i]);
}
@ -462,10 +465,10 @@ STATIC mp_obj_t set_unary_op(mp_uint_t op, mp_obj_t self_in) {
if (MP_OBJ_IS_TYPE(self_in, &mp_type_frozenset)) {
// start hash with unique value
mp_int_t hash = (mp_int_t)(uintptr_t)&mp_type_frozenset;
mp_uint_t max = self->set.alloc;
size_t max = self->set.alloc;
mp_set_t *set = &self->set;
for (mp_uint_t i = 0; i < max; i++) {
for (size_t i = 0; i < max; i++) {
if (MP_SET_SLOT_IS_FILLED(set, i)) {
hash += MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, set->table[i]));
}
@ -587,11 +590,11 @@ const mp_obj_type_t mp_type_frozenset = {
};
#endif
mp_obj_t mp_obj_new_set(mp_uint_t n_args, mp_obj_t *items) {
mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items) {
mp_obj_set_t *o = m_new_obj(mp_obj_set_t);
o->base.type = &mp_type_set;
mp_set_init(&o->set, n_args);
for (mp_uint_t i = 0; i < n_args; i++) {
for (size_t i = 0; i < n_args; i++) {
mp_set_lookup(&o->set, items[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}
return MP_OBJ_FROM_PTR(o);

View File

@ -38,13 +38,13 @@
STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict);
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str);
STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);
STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in);
/******************************************************************************/
/* str */
void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, mp_uint_t str_len, bool is_bytes) {
void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t 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;
@ -231,7 +231,8 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
vstr_init(&vstr, len);
}
mp_obj_t iterable = mp_getiter(args[0]);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(args[0], &iter_buf);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
mp_int_t val = mp_obj_get_int(item);
@ -251,9 +252,9 @@ wrong_args:
// like strstr but with specified length and allows \0 bytes
// TODO replace with something more efficient/standard
const byte *find_subbytes(const byte *haystack, mp_uint_t hlen, const byte *needle, mp_uint_t nlen, mp_int_t direction) {
const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction) {
if (hlen >= nlen) {
mp_uint_t str_index, str_index_end;
size_t str_index, str_index_end;
if (direction > 0) {
str_index = 0;
str_index_end = hlen - nlen;
@ -333,7 +334,7 @@ mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// size and execution time so we don't.
const byte *rhs_data;
mp_uint_t rhs_len;
size_t rhs_len;
if (lhs_type == mp_obj_get_type(rhs_in)) {
GET_STR_DATA_LEN(rhs_in, rhs_data_, rhs_len_);
rhs_data = rhs_data_;
@ -441,8 +442,8 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
}
// count required length
mp_uint_t required_len = 0;
for (mp_uint_t i = 0; i < seq_len; i++) {
size_t required_len = 0;
for (size_t i = 0; i < seq_len; i++) {
if (mp_obj_get_type(seq_items[i]) != self_type) {
mp_raise_TypeError(
"join expects a list of str/bytes objects consistent with self object");
@ -458,7 +459,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
vstr_t vstr;
vstr_init_len(&vstr, required_len);
byte *data = (byte*)vstr.buf;
for (mp_uint_t i = 0; i < seq_len; i++) {
for (size_t i = 0; i < seq_len; i++) {
if (i > 0) {
memcpy(data, sep_str, sep_len);
data += sep_len;
@ -644,7 +645,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) {
}
if (idx != 0) {
// We split less parts than split limit, now go cleanup surplus
mp_int_t used = org_splits + 1 - idx;
size_t used = org_splits + 1 - idx;
memmove(res->items, &res->items[idx], used * sizeof(mp_obj_t));
mp_seq_clear(res->items, used, res->alloc, sizeof(*res->items));
res->len = used;
@ -654,7 +655,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) {
return MP_OBJ_FROM_PTR(res);
}
STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, mp_int_t direction, bool is_index) {
STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(args[0]));
@ -762,16 +763,16 @@ STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) {
GET_STR_DATA_LEN(args[0], orig_str, orig_str_len);
mp_uint_t first_good_char_pos = 0;
size_t first_good_char_pos = 0;
bool first_good_char_pos_set = false;
mp_uint_t last_good_char_pos = 0;
mp_uint_t i = 0;
mp_int_t delta = 1;
size_t last_good_char_pos = 0;
size_t i = 0;
int delta = 1;
if (type == RSTRIP) {
i = orig_str_len - 1;
delta = -1;
}
for (mp_uint_t len = orig_str_len; len > 0; len--) {
for (size_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;
@ -801,7 +802,7 @@ STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) {
assert(last_good_char_pos >= first_good_char_pos);
//+1 to accomodate the last character
mp_uint_t stripped_len = last_good_char_pos - first_good_char_pos + 1;
size_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()
@ -1588,11 +1589,11 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) {
// first pass computes the required length of the replaced string
// second pass does the replacements
for (;;) {
mp_uint_t replaced_str_index = 0;
mp_uint_t num_replacements_done = 0;
size_t replaced_str_index = 0;
size_t num_replacements_done = 0;
const byte *old_occurrence;
const byte *offset_ptr = str;
mp_uint_t str_len_remain = str_len;
size_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
@ -1602,7 +1603,7 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) {
replaced_str_index += new_len;
num_replacements_done++;
}
while (num_replacements_done != (mp_uint_t)max_rep && str_len_remain > 0 && (old_occurrence = find_subbytes(offset_ptr, str_len_remain, old, old_len, 1)) != NULL) {
while (num_replacements_done != (size_t)max_rep && str_len_remain > 0 && (old_occurrence = find_subbytes(offset_ptr, str_len_remain, old, old_len, 1)) != NULL) {
if (old_len == 0) {
old_occurrence += 1;
}
@ -1688,7 +1689,7 @@ STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) {
}
#if MICROPY_PY_BUILTINS_STR_PARTITION
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, mp_int_t direction) {
STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) {
mp_check_self(MP_OBJ_IS_STR_OR_BYTES(self_in));
mp_obj_type_t *self_type = mp_obj_get_type(self_in);
if (self_type != mp_obj_get_type(arg)) {
@ -1721,7 +1722,7 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, mp_int_t directi
const byte *position_ptr = find_subbytes(str, str_len, sep, sep_len, direction);
if (position_ptr != NULL) {
mp_uint_t position = position_ptr - str;
size_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);
@ -1745,7 +1746,7 @@ STATIC mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) {
vstr_t vstr;
vstr_init_len(&vstr, self_len);
byte *data = (byte*)vstr.buf;
for (mp_uint_t i = 0; i < self_len; i++) {
for (size_t i = 0; i < self_len; i++) {
*data++ = op(*self_data++);
}
return mp_obj_new_str_from_vstr(mp_obj_get_type(self_in), &vstr);
@ -1767,7 +1768,7 @@ STATIC mp_obj_t str_uni_istype(bool (*f)(unichar), mp_obj_t self_in) {
}
if (f != unichar_isupper && f != unichar_islower) {
for (mp_uint_t i = 0; i < self_len; i++) {
for (size_t i = 0; i < self_len; i++) {
if (!f(*self_data++)) {
return mp_const_false;
}
@ -1775,7 +1776,7 @@ STATIC mp_obj_t str_uni_istype(bool (*f)(unichar), mp_obj_t self_in) {
} else {
bool contains_alpha = false;
for (mp_uint_t i = 0; i < self_len; i++) { // only check alphanumeric characters
for (size_t i = 0; i < self_len; i++) { // only check alphanumeric characters
if (unichar_isalpha(*self_data++)) {
contains_alpha = true;
if (!f(*(self_data - 1))) { // -1 because we already incremented above
@ -1942,7 +1943,7 @@ STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(str8_locals_dict, str8_locals_dict_table);
#if !MICROPY_PY_BUILTINS_STR_UNICODE
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);
const mp_obj_type_t mp_type_str = {
{ &mp_type_type },
@ -2019,7 +2020,7 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) {
return MP_OBJ_FROM_PTR(o);
}
mp_obj_t mp_obj_new_str(const char* data, mp_uint_t len, bool make_qstr_if_not_already) {
mp_obj_t mp_obj_new_str(const char* data, size_t len, bool make_qstr_if_not_already) {
if (make_qstr_if_not_already) {
// use existing, or make a new qstr
return MP_OBJ_NEW_QSTR(qstr_from_strn(data, len));
@ -2040,7 +2041,7 @@ mp_obj_t mp_obj_str_intern(mp_obj_t str) {
return MP_OBJ_NEW_QSTR(qstr_from_strn((const char*)data, len));
}
mp_obj_t mp_obj_new_bytes(const byte* data, mp_uint_t len) {
mp_obj_t mp_obj_new_bytes(const byte* data, size_t len) {
return mp_obj_new_str_of_type(&mp_type_bytes, data, len);
}
@ -2126,7 +2127,7 @@ typedef struct _mp_obj_str8_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
mp_obj_t str;
mp_uint_t cur;
size_t cur;
} mp_obj_str8_it_t;
#if !MICROPY_PY_BUILTINS_STR_UNICODE
@ -2142,8 +2143,9 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
}
}
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
mp_obj_str8_it_t *o = m_new_obj(mp_obj_str8_it_t);
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_str8_it_t *o = (mp_obj_str8_it_t*)iter_buf;
o->base.type = &mp_type_polymorph_iter;
o->iternext = str_it_iternext;
o->str = str;
@ -2164,8 +2166,9 @@ STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) {
}
}
mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str) {
mp_obj_str8_it_t *o = m_new_obj(mp_obj_str8_it_t);
mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_str8_it_t *o = (mp_obj_str8_it_t*)iter_buf;
o->base.type = &mp_type_polymorph_iter;
o->iternext = bytes_it_iternext;
o->str = str;

View File

@ -32,7 +32,7 @@ typedef struct _mp_obj_str_t {
mp_obj_base_t base;
mp_uint_t hash;
// len == number of bytes used in data, alloc = len + 1 because (at the moment) we also append a null byte
mp_uint_t len;
size_t len;
const byte *data;
} mp_obj_str_t;
@ -72,7 +72,7 @@ mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_u
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,
mp_obj_t index, bool is_slice);
const byte *find_subbytes(const byte *haystack, mp_uint_t hlen, const byte *needle, mp_uint_t nlen, mp_int_t direction);
const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj);

View File

@ -215,7 +215,7 @@ const mp_obj_type_t mp_type_stringio = {
.name = MP_QSTR_StringIO,
.print = stringio_print,
.make_new = stringio_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &stringio_stream_p,
.locals_dict = (mp_obj_dict_t*)&stringio_locals_dict,
@ -227,7 +227,7 @@ const mp_obj_type_t mp_type_bytesio = {
.name = MP_QSTR_BytesIO,
.print = stringio_print,
.make_new = stringio_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &bytesio_stream_p,
.locals_dict = (mp_obj_dict_t*)&stringio_locals_dict,

View File

@ -36,7 +36,7 @@
#if MICROPY_PY_BUILTINS_STR_UNICODE
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str);
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf);
/******************************************************************************/
/* str */
@ -284,7 +284,7 @@ typedef struct _mp_obj_str_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
mp_obj_t str;
mp_uint_t cur;
size_t cur;
} mp_obj_str_it_t;
STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
@ -301,8 +301,9 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
}
}
STATIC 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);
STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_str_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_str_it_t *o = (mp_obj_str_it_t*)iter_buf;
o->base.type = &mp_type_polymorph_iter;
o->iternext = str_it_iternext;
o->str = str;

View File

@ -32,8 +32,6 @@
#include "py/runtime0.h"
#include "py/runtime.h"
STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur);
/******************************************************************************/
/* tuple */
@ -45,7 +43,7 @@ void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
mp_print_str(print, "(");
kind = PRINT_REPR;
}
for (mp_uint_t i = 0; i < o->len; i++) {
for (size_t i = 0; i < o->len; i++) {
if (i > 0) {
mp_print_str(print, ", ");
}
@ -80,11 +78,11 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg
// TODO optimise for cases where we know the length of the iterator
mp_uint_t alloc = 4;
mp_uint_t len = 0;
size_t alloc = 4;
size_t len = 0;
mp_obj_t *items = m_new(mp_obj_t, alloc);
mp_obj_t iterable = mp_getiter(args[0]);
mp_obj_t iterable = mp_getiter(args[0], NULL);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (len >= alloc) {
@ -127,7 +125,7 @@ mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) {
case MP_UNARY_OP_HASH: {
// start hash with pointer to empty tuple, to make it fairly unique
mp_int_t hash = (mp_int_t)mp_const_empty_tuple;
for (mp_uint_t i = 0; i < self->len; i++) {
for (size_t i = 0; i < self->len; i++) {
hash += MP_OBJ_SMALL_INT_VALUE(mp_unary_op(MP_UNARY_OP_HASH, self->items[i]));
}
return MP_OBJ_NEW_SMALL_INT(hash);
@ -195,10 +193,6 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
}
}
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in) {
return mp_obj_new_tuple_iterator(MP_OBJ_TO_PTR(o_in), 0);
}
STATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) {
mp_check_self(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
@ -235,7 +229,7 @@ const mp_obj_type_t mp_type_tuple = {
// the zero-length tuple
const mp_obj_tuple_t mp_const_empty_tuple_obj = {{&mp_type_tuple}, 0};
mp_obj_t mp_obj_new_tuple(mp_uint_t n, const mp_obj_t *items) {
mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) {
if (n == 0) {
return mp_const_empty_tuple;
}
@ -243,7 +237,7 @@ mp_obj_t mp_obj_new_tuple(mp_uint_t n, const mp_obj_t *items) {
o->base.type = &mp_type_tuple;
o->len = n;
if (items) {
for (mp_uint_t i = 0; i < n; i++) {
for (size_t i = 0; i < n; i++) {
o->items[i] = items[i];
}
}
@ -270,7 +264,7 @@ typedef struct _mp_obj_tuple_it_t {
mp_obj_base_t base;
mp_fun_1_t iternext;
mp_obj_tuple_t *tuple;
mp_uint_t cur;
size_t cur;
} mp_obj_tuple_it_t;
STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
@ -284,11 +278,12 @@ STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
}
}
STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur) {
mp_obj_tuple_it_t *o = m_new_obj(mp_obj_tuple_it_t);
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
assert(sizeof(mp_obj_tuple_it_t) <= sizeof(mp_obj_iter_buf_t));
mp_obj_tuple_it_t *o = (mp_obj_tuple_it_t*)iter_buf;
o->base.type = &mp_type_polymorph_iter;
o->iternext = tuple_it_iternext;
o->tuple = tuple;
o->cur = cur;
o->tuple = MP_OBJ_TO_PTR(o_in);
o->cur = 0;
return MP_OBJ_FROM_PTR(o);
}

View File

@ -30,13 +30,13 @@
typedef struct _mp_obj_tuple_t {
mp_obj_base_t base;
mp_uint_t len;
size_t len;
mp_obj_t items[];
} mp_obj_tuple_t;
typedef struct _mp_rom_obj_tuple_t {
mp_obj_base_t base;
mp_uint_t len;
size_t len;
mp_rom_obj_t items[];
} mp_rom_obj_tuple_t;
@ -44,7 +44,7 @@ void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in);
mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t mp_obj_tuple_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value);
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in);
mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf);
extern const mp_obj_type_t mp_type_attrtuple;
@ -59,6 +59,6 @@ extern const mp_obj_type_t mp_type_attrtuple;
void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o);
#endif
mp_obj_t mp_obj_new_attrtuple(const qstr *fields, mp_uint_t n, const mp_obj_t *items);
mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items);
#endif // __MICROPY_INCLUDED_PY_OBJTUPLE_H__

View File

@ -284,7 +284,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size
}
// https://docs.python.org/3.4/reference/datamodel.html#object.__new__
// "If __new__() does not return an instance of cls, then the new instances __init__() method will not be invoked."
// "If __new__() does not return an instance of cls, then the new instance's __init__() method will not be invoked."
if (mp_obj_get_type(new_ret) != self) {
return new_ret;
}
@ -533,6 +533,15 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
// try __getattr__
if (attr != MP_QSTR___getattr__) {
#if MICROPY_PY_DELATTR_SETATTR
// If the requested attr is __setattr__/__delattr__ then don't delegate the lookup
// to __getattr__. If we followed CPython's behaviour then __setattr__/__delattr__
// would have already been found in the "object" base class.
if (attr == MP_QSTR___setattr__ || attr == MP_QSTR___delattr__) {
return;
}
#endif
mp_obj_t dest2[3];
mp_load_method_maybe(self_in, MP_QSTR___getattr__, dest2);
if (dest2[0] != MP_OBJ_NULL) {
@ -626,10 +635,35 @@ STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t val
if (value == MP_OBJ_NULL) {
// delete attribute
#if MICROPY_PY_DELATTR_SETATTR
// try __delattr__ first
mp_obj_t attr_delattr_method[3];
mp_load_method_maybe(self_in, MP_QSTR___delattr__, attr_delattr_method);
if (attr_delattr_method[0] != MP_OBJ_NULL) {
// __delattr__ exists, so call it
attr_delattr_method[2] = MP_OBJ_NEW_QSTR(attr);
mp_call_method_n_kw(1, 0, attr_delattr_method);
return true;
}
#endif
mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
return elem != NULL;
} else {
// store attribute
#if MICROPY_PY_DELATTR_SETATTR
// try __setattr__ first
mp_obj_t attr_setattr_method[4];
mp_load_method_maybe(self_in, MP_QSTR___setattr__, attr_setattr_method);
if (attr_setattr_method[0] != MP_OBJ_NULL) {
// __setattr__ exists, so call it
attr_setattr_method[2] = MP_OBJ_NEW_QSTR(attr);
attr_setattr_method[3] = value;
mp_call_method_n_kw(2, 0, attr_setattr_method);
return true;
}
#endif
mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
return true;
}
@ -724,7 +758,7 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons
return mp_call_method_self_n_kw(member[0], member[1], n_args, n_kw, args);
}
STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
STATIC mp_obj_t instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_t member[2] = {MP_OBJ_NULL};
struct class_lookup_data lookup = {
@ -739,7 +773,7 @@ STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
return MP_OBJ_NULL;
} else if (member[0] == MP_OBJ_SENTINEL) {
mp_obj_type_t *type = mp_obj_get_type(self->subobj[0]);
return type->getiter(self->subobj[0]);
return type->getiter(self->subobj[0], iter_buf);
} else {
return mp_call_method_n_kw(0, 0, member);
}

View File

@ -43,7 +43,7 @@ STATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
o->base.type = type;
o->n_iters = n_args;
for (mp_uint_t i = 0; i < n_args; i++) {
o->iters[i] = mp_getiter(args[i]);
o->iters[i] = mp_getiter(args[i], NULL);
}
return MP_OBJ_FROM_PTR(o);
}
@ -71,6 +71,6 @@ const mp_obj_type_t mp_type_zip = {
{ &mp_type_type },
.name = MP_QSTR_zip,
.make_new = zip_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = zip_iternext,
};

View File

@ -69,13 +69,22 @@ typedef struct _rule_t {
} rule_t;
enum {
// define rules with a compile function
#define DEF_RULE(rule, comp, kind, ...) RULE_##rule,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
RULE_maximum_number_of,
#undef DEF_RULE_NC
RULE_string, // special node for non-interned string
RULE_bytes, // special node for non-interned bytes
RULE_const_object, // special node for a constant, generic Python object
// define rules without a compile function
#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) RULE_##rule,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
};
#define or(n) (RULE_ACT_OR | n)
@ -90,8 +99,10 @@ enum {
#define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r)
#ifdef USE_RULE_NAME
#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, #rule, { __VA_ARGS__ } };
#else
#define DEF_RULE(rule, comp, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };
#define DEF_RULE_NC(rule, kind, ...) static const rule_t rule_##rule = { RULE_##rule, kind, { __VA_ARGS__ } };
#endif
#include "py/grammar.h"
#undef or
@ -103,11 +114,25 @@ enum {
#undef opt_rule
#undef one_or_more
#undef DEF_RULE
#undef DEF_RULE_NC
STATIC const rule_t *const rules[] = {
// define rules with a compile function
#define DEF_RULE(rule, comp, kind, ...) &rule_##rule,
#define DEF_RULE_NC(rule, kind, ...)
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
NULL, // RULE_string
NULL, // RULE_bytes
NULL, // RULE_const_object
// define rules without a compile function
#define DEF_RULE(rule, comp, kind, ...)
#define DEF_RULE_NC(rule, kind, ...) &rule_##rule,
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
};
typedef struct _rule_stack_t {
@ -215,7 +240,6 @@ STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, siz
STATIC void push_rule_from_arg(parser_t *parser, size_t arg) {
assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);
size_t rule_id = arg & RULE_ARG_ARG_MASK;
assert(rule_id < RULE_maximum_number_of);
push_rule(parser, parser->lexer->tok_line, rules[rule_id], 0);
}

View File

@ -38,6 +38,9 @@
#include "py/smallint.h"
// The current version of .mpy files
#define MPY_VERSION (1)
// The feature flags byte encodes the compile-time config options that
// affect the generate bytecode.
#define MPY_FEATURE_FLAGS ( \
@ -108,8 +111,8 @@ STATIC void read_bytes(mp_reader_t *reader, byte *buf, size_t len) {
}
}
STATIC mp_uint_t read_uint(mp_reader_t *reader) {
mp_uint_t unum = 0;
STATIC size_t read_uint(mp_reader_t *reader) {
size_t unum = 0;
for (;;) {
byte b = reader->readbyte(reader->data);
unum = (unum << 7) | (b & 0x7f);
@ -121,7 +124,7 @@ STATIC mp_uint_t read_uint(mp_reader_t *reader) {
}
STATIC qstr load_qstr(mp_reader_t *reader) {
mp_uint_t len = read_uint(reader);
size_t len = read_uint(reader);
char *str = m_new(char, len);
read_bytes(reader, (byte*)str, len);
qstr qst = qstr_from_strn(str, len);
@ -164,7 +167,7 @@ STATIC void load_bytecode_qstrs(mp_reader_t *reader, byte *ip, byte *ip_top) {
STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
// load bytecode
mp_uint_t bc_len = read_uint(reader);
size_t bc_len = read_uint(reader);
byte *bytecode = m_new(byte, bc_len);
read_bytes(reader, bytecode, bc_len);
@ -182,17 +185,17 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
load_bytecode_qstrs(reader, (byte*)ip, bytecode + bc_len);
// load constant table
mp_uint_t n_obj = read_uint(reader);
mp_uint_t n_raw_code = read_uint(reader);
size_t n_obj = read_uint(reader);
size_t n_raw_code = read_uint(reader);
mp_uint_t *const_table = m_new(mp_uint_t, prelude.n_pos_args + prelude.n_kwonly_args + n_obj + n_raw_code);
mp_uint_t *ct = const_table;
for (mp_uint_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {
for (size_t i = 0; i < prelude.n_pos_args + prelude.n_kwonly_args; ++i) {
*ct++ = (mp_uint_t)MP_OBJ_NEW_QSTR(load_qstr(reader));
}
for (mp_uint_t i = 0; i < n_obj; ++i) {
for (size_t i = 0; i < n_obj; ++i) {
*ct++ = (mp_uint_t)load_obj(reader);
}
for (mp_uint_t i = 0; i < n_raw_code; ++i) {
for (size_t i = 0; i < n_raw_code; ++i) {
*ct++ = (mp_uint_t)(uintptr_t)load_raw_code(reader);
}
@ -209,10 +212,10 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) {
byte header[4];
read_bytes(reader, header, sizeof(header));
if (strncmp((char*)header, "M\x00", 2) != 0) {
mp_raise_ValueError("invalid .mpy file");
}
if (header[2] != MPY_FEATURE_FLAGS || header[3] > mp_small_int_bits()) {
if (header[0] != 'M'
|| header[1] != MPY_VERSION
|| header[2] != MPY_FEATURE_FLAGS
|| header[3] > mp_small_int_bits()) {
mp_raise_ValueError("incompatible .mpy file");
}
mp_raw_code_t *rc = load_raw_code(reader);
@ -248,7 +251,7 @@ STATIC void mp_print_bytes(mp_print_t *print, const byte *data, size_t len) {
}
#define BYTES_FOR_INT ((BYTES_PER_WORD * 8 + 6) / 7)
STATIC void mp_print_uint(mp_print_t *print, mp_uint_t n) {
STATIC void mp_print_uint(mp_print_t *print, size_t n) {
byte buf[BYTES_FOR_INT];
byte *p = buf + sizeof(buf);
*--p = n & 0x7f;
@ -359,7 +362,7 @@ void mp_raw_code_save(mp_raw_code_t *rc, mp_print_t *print) {
// byte version
// byte feature flags
// byte number of bits in a small int
byte header[4] = {'M', 0, MPY_FEATURE_FLAGS_DYNAMIC,
byte header[4] = {'M', MPY_VERSION, MPY_FEATURE_FLAGS_DYNAMIC,
#if MICROPY_DYNAMIC_COMPILER
mp_dynamic_compiler.small_int_bits,
#else

View File

@ -301,7 +301,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
}
} else if (MP_OBJ_IS_TYPE(rhs, &mp_type_tuple)) {
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(rhs);
for (mp_uint_t i = 0; i < tuple->len; i++) {
for (size_t i = 0; i < tuple->len; i++) {
rhs = tuple->items[i];
if (!mp_obj_is_exception_type(rhs)) {
goto unsupported_op;
@ -520,7 +520,8 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
}
if (type->getiter != NULL) {
/* second attempt, walk the iterator */
mp_obj_t iter = mp_getiter(rhs);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iter = mp_getiter(rhs, &iter_buf);
mp_obj_t next;
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
if (mp_obj_equal(next, lhs)) {
@ -580,7 +581,7 @@ mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {
}
// args contains, eg: arg0 arg1 key0 value0 key1 value1
mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// TODO improve this: fun object can specify its type and we parse here the arguments,
// passing to the function arrays of fixed and keyword arguments
@ -604,7 +605,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args, mp_uint_t n_kw
// args contains: fun self/NULL arg(0) ... arg(n_args-2) arg(n_args-1) kw_key(0) kw_val(0) ... kw_key(n_kw-1) kw_val(n_kw-1)
// if n_args==0 and n_kw==0 then there are only fun and self/NULL
mp_obj_t mp_call_method_n_kw(mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args) {
DEBUG_OP_printf("call method (fun=%p, self=%p, n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", args[0], args[1], n_args, n_kw, args);
int adjust = (args[1] == MP_OBJ_NULL) ? 0 : 1;
return mp_call_function_n_kw(args[0], n_args + adjust, n_kw, args + 2 - adjust);
@ -614,7 +615,7 @@ mp_obj_t mp_call_method_n_kw(mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *a
#if !MICROPY_STACKLESS
STATIC
#endif
void mp_call_prepare_args_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args) {
void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args) {
mp_obj_t fun = *args++;
mp_obj_t self = MP_OBJ_NULL;
if (have_self) {
@ -698,7 +699,8 @@ void mp_call_prepare_args_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const
args2_len += n_args;
// extract the variable position args from the iterator
mp_obj_t iterable = mp_getiter(pos_seq);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(pos_seq, &iter_buf);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
if (args2_len >= args2_alloc) {
@ -724,7 +726,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const
// dictionary
mp_map_t *map = mp_obj_dict_get_map(kw_dict);
assert(args2_len + 2 * map->used <= args2_alloc); // should have enough, since kw_dict_len is in this case hinted correctly above
for (mp_uint_t i = 0; i < map->alloc; i++) {
for (size_t i = 0; i < map->alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
// the key must be a qstr, so intern it if it's a string
mp_obj_t key = map->table[i].key;
@ -743,7 +745,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const
// get the keys iterable
mp_obj_t dest[3];
mp_load_method(kw_dict, MP_QSTR_keys, dest);
mp_obj_t iterable = mp_getiter(mp_call_method_n_kw(0, 0, dest));
mp_obj_t iterable = mp_getiter(mp_call_method_n_kw(0, 0, dest), NULL);
mp_obj_t key;
while ((key = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
@ -780,7 +782,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const
out_args->n_alloc = args2_alloc;
}
mp_obj_t mp_call_method_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const mp_obj_t *args) {
mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args) {
mp_call_args_t out_args;
mp_call_prepare_args_n_kw_var(have_self, n_args_n_kw, args, &out_args);
@ -791,7 +793,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const mp
}
// unpacked items are stored in reverse order into the array pointed to by items
void mp_unpack_sequence(mp_obj_t seq_in, mp_uint_t num, mp_obj_t *items) {
void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
mp_uint_t seq_len;
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
mp_obj_t *seq_items;
@ -805,11 +807,12 @@ void mp_unpack_sequence(mp_obj_t seq_in, mp_uint_t num, mp_obj_t *items) {
} else if (seq_len > num) {
goto too_long;
}
for (mp_uint_t i = 0; i < num; i++) {
for (size_t i = 0; i < num; i++) {
items[i] = seq_items[num - 1 - i];
}
} else {
mp_obj_t iterable = mp_getiter(seq_in);
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(seq_in, &iter_buf);
for (seq_len = 0; seq_len < num; seq_len++) {
mp_obj_t el = mp_iternext(iterable);
@ -841,9 +844,9 @@ too_long:
}
// unpacked items are stored in reverse order into the array pointed to by items
void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) {
mp_uint_t num_left = num_in & 0xff;
mp_uint_t num_right = (num_in >> 8) & 0xff;
void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
size_t num_left = num_in & 0xff;
size_t num_right = (num_in >> 8) & 0xff;
DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right);
mp_uint_t seq_len;
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
@ -861,11 +864,11 @@ void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) {
if (seq_len < num_left + num_right) {
goto too_short;
}
for (mp_uint_t i = 0; i < num_right; i++) {
for (size_t i = 0; i < num_right; i++) {
items[i] = seq_items[seq_len - 1 - i];
}
items[num_right] = mp_obj_new_list(seq_len - num_left - num_right, seq_items + num_left);
for (mp_uint_t i = 0; i < num_left; i++) {
for (size_t i = 0; i < num_left; i++) {
items[num_right + 1 + i] = seq_items[num_left - 1 - i];
}
} else {
@ -873,7 +876,7 @@ void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) {
// items destination array, then the rest to a dynamically created list. Once the
// iterable is exhausted, we take from this list for the right part of the items.
// TODO Improve to waste less memory in the dynamically created list.
mp_obj_t iterable = mp_getiter(seq_in);
mp_obj_t iterable = mp_getiter(seq_in, NULL);
mp_obj_t item;
for (seq_len = 0; seq_len < num_left; seq_len++) {
item = mp_iternext(iterable);
@ -890,7 +893,7 @@ void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) {
goto too_short;
}
items[num_right] = MP_OBJ_FROM_PTR(rest);
for (mp_uint_t i = 0; i < num_right; i++) {
for (size_t i = 0; i < num_right; i++) {
items[num_right - 1 - i] = rest->items[rest->len - num_right + i];
}
mp_obj_list_set_len(MP_OBJ_FROM_PTR(rest), rest->len - num_right);
@ -1096,13 +1099,24 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
}
}
mp_obj_t mp_getiter(mp_obj_t o_in) {
mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
assert(o_in);
mp_obj_type_t *type = mp_obj_get_type(o_in);
// Check for native getiter which is the identity. We handle this case explicitly
// so we don't unnecessarily allocate any RAM for the iter_buf, which won't be used.
if (type->getiter == mp_identity_getiter) {
return o_in;
}
// if caller did not provide a buffer then allocate one on the heap
if (iter_buf == NULL) {
iter_buf = m_new_obj(mp_obj_iter_buf_t);
}
// check for native getiter (corresponds to __iter__)
mp_obj_type_t *type = mp_obj_get_type(o_in);
if (type->getiter != NULL) {
mp_obj_t iter = type->getiter(o_in);
mp_obj_t iter = type->getiter(o_in, iter_buf);
if (iter != MP_OBJ_NULL) {
return iter;
}
@ -1113,7 +1127,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in) {
mp_load_method_maybe(o_in, MP_QSTR___getitem__, dest);
if (dest[0] != MP_OBJ_NULL) {
// __getitem__ exists, create and return an iterator
return mp_obj_new_getitem_iter(dest);
return mp_obj_new_getitem_iter(dest, iter_buf);
}
// object not iterable
@ -1350,7 +1364,7 @@ void mp_import_all(mp_obj_t module) {
// TODO: Support __all__
mp_map_t *map = mp_obj_dict_get_map(MP_OBJ_FROM_PTR(mp_obj_module_get_globals(module)));
for (mp_uint_t i = 0; i < map->alloc; i++) {
for (size_t i = 0; i < map->alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
qstr name = MP_OBJ_QSTR_VALUE(map->table[i].key);
if (*qstr_str(name) != '_') {

View File

@ -92,9 +92,9 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs);
mp_obj_t mp_call_function_0(mp_obj_t fun);
mp_obj_t mp_call_function_1(mp_obj_t fun, mp_obj_t arg);
mp_obj_t mp_call_function_2(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
mp_obj_t mp_call_function_n_kw(mp_obj_t fun, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_n_kw(mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const mp_obj_t *args);
mp_obj_t mp_call_function_n_kw(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_self_n_kw(mp_obj_t meth, mp_obj_t self, size_t n_args, size_t n_kw, const mp_obj_t *args);
// Call function and catch/dump exception - for Python callbacks from C code
void mp_call_function_1_protected(mp_obj_t fun, mp_obj_t arg);
@ -102,7 +102,7 @@ void mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2);
typedef struct _mp_call_args_t {
mp_obj_t fun;
mp_uint_t n_args, n_kw, n_alloc;
size_t n_args, n_kw, n_alloc;
mp_obj_t *args;
} mp_call_args_t;
@ -111,11 +111,11 @@ typedef struct _mp_call_args_t {
// prepares argument array suitable for passing to ->call() method of a
// function object (and mp_call_function_n_kw()).
// (Only needed in stackless mode.)
void mp_call_prepare_args_n_kw_var(bool have_self, mp_uint_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args);
void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args);
#endif
void mp_unpack_sequence(mp_obj_t seq, mp_uint_t num, mp_obj_t *items);
void mp_unpack_ex(mp_obj_t seq, mp_uint_t num, mp_obj_t *items);
void mp_unpack_sequence(mp_obj_t seq, size_t num, mp_obj_t *items);
void mp_unpack_ex(mp_obj_t seq, size_t num, mp_obj_t *items);
mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
void mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest);
@ -123,7 +123,7 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
mp_obj_t mp_getiter(mp_obj_t o);
mp_obj_t mp_getiter(mp_obj_t o, mp_obj_iter_buf_t *iter_buf);
mp_obj_t mp_iternext_allow_raise(mp_obj_t o); // may return MP_OBJ_STOP_ITERATION instead of raising StopIteration()
mp_obj_t mp_iternext(mp_obj_t o); // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration(...)
mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val);
@ -155,7 +155,7 @@ NORETURN void mp_exc_recursion_depth(void);
// helper functions for native/viper code
mp_uint_t mp_convert_obj_to_native(mp_obj_t obj, mp_uint_t type);
mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type);
mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, const mp_obj_t *args);
mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args);
void mp_native_raise(mp_obj_t o);
#define mp_sys_path (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_path_obj)))

View File

@ -127,8 +127,8 @@ typedef enum {
MP_F_NATIVE_CALL_FUNCTION_N_KW,
MP_F_CALL_METHOD_N_KW,
MP_F_CALL_METHOD_N_KW_VAR,
MP_F_GETITER,
MP_F_ITERNEXT,
MP_F_NATIVE_GETITER,
MP_F_NATIVE_ITERNEXT,
MP_F_NLR_PUSH,
MP_F_NLR_POP,
MP_F_NATIVE_RAISE,

View File

@ -387,6 +387,10 @@ const byte *mp_bytecode_print_str(const byte *ip) {
printf("GET_ITER");
break;
case MP_BC_GET_ITER_STACK:
printf("GET_ITER_STACK");
break;
case MP_BC_FOR_ITER:
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
printf("FOR_ITER " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));

70
py/vm.c
View File

@ -63,8 +63,8 @@ typedef enum {
do { \
unum = (unum << 7) + (*ip & 0x7f); \
} while ((*ip++ & 0x80) != 0)
#define DECODE_ULABEL mp_uint_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
#define DECODE_SLABEL mp_uint_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
#define DECODE_ULABEL size_t ulab = (ip[0] | (ip[1] << 8)); ip += 2
#define DECODE_SLABEL size_t slab = (ip[0] | (ip[1] << 8)) - 0x8000; ip += 2
#if MICROPY_PERSISTENT_CODE
@ -169,6 +169,12 @@ run_code_state: ;
volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
mp_exc_stack_t *volatile exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
#if MICROPY_PY_THREAD_GIL && MICROPY_PY_THREAD_GIL_VM_DIVISOR
// This needs to be volatile and outside the VM loop so it persists across handling
// of any exceptions. Otherwise it's possible that the VM never gives up the GIL.
volatile int gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
#endif
// outer exception handling loop
for (;;) {
nlr_buf_t nlr;
@ -675,7 +681,9 @@ unwind_jump:;
}
ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump
if (unum != 0) {
// pop iter and iter_buf
sp--;
sp -= sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t);
}
DISPATCH_WITH_PEND_EXC_CHECK();
}
@ -717,17 +725,39 @@ unwind_jump:;
ENTRY(MP_BC_GET_ITER):
MARK_EXC_IP_SELECTIVE();
SET_TOP(mp_getiter(TOP()));
SET_TOP(mp_getiter(TOP(), NULL));
DISPATCH();
// An iterator for a for-loop takes 4 slots on the stack. They are either
// used to store the iterator object itself, or the first slot is NULL and
// the second slot holds a reference to the iterator object.
ENTRY(MP_BC_GET_ITER_STACK): {
MARK_EXC_IP_SELECTIVE();
mp_obj_t obj = TOP();
mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
sp += sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1;
obj = mp_getiter(obj, iter_buf);
if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
// Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
sp[-3] = MP_OBJ_NULL;
sp[-2] = obj;
}
DISPATCH();
}
ENTRY(MP_BC_FOR_ITER): {
MARK_EXC_IP_SELECTIVE();
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
code_state->sp = sp;
assert(TOP());
mp_obj_t value = mp_iternext_allow_raise(TOP());
mp_obj_t obj;
if (sp[-3] == MP_OBJ_NULL) {
obj = sp[-2];
} else {
obj = MP_OBJ_FROM_PTR(&sp[-3]);
}
mp_obj_t value = mp_iternext_allow_raise(obj);
if (value == MP_OBJ_STOP_ITERATION) {
--sp; // pop the exhausted iterator
sp -= 4; // pop the exhausted iterator
ip += ulab; // jump to after for-block
} else {
PUSH(value); // push the next iteration value
@ -857,7 +887,7 @@ unwind_jump:;
ENTRY(MP_BC_MAKE_CLOSURE): {
DECODE_PTR;
mp_uint_t n_closed_over = *ip++;
size_t n_closed_over = *ip++;
// Stack layout: closed_overs <- TOS
sp -= n_closed_over - 1;
SET_TOP(mp_make_closure_from_raw_code(ptr, n_closed_over, sp));
@ -866,7 +896,7 @@ unwind_jump:;
ENTRY(MP_BC_MAKE_CLOSURE_DEFARGS): {
DECODE_PTR;
mp_uint_t n_closed_over = *ip++;
size_t n_closed_over = *ip++;
// Stack layout: def_tuple def_dict closed_overs <- TOS
sp -= 2 + n_closed_over - 1;
SET_TOP(mp_make_closure_from_raw_code(ptr, 0x100 | n_closed_over, sp));
@ -952,8 +982,8 @@ unwind_jump:;
code_state->sp = sp;
code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
mp_uint_t n_args = unum & 0xff;
mp_uint_t n_kw = (unum >> 8) & 0xff;
size_t n_args = unum & 0xff;
size_t n_kw = (unum >> 8) & 0xff;
int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
@ -1243,9 +1273,17 @@ pending_exception_check:
RAISE(obj);
}
// TODO make GIL release more efficient
MP_THREAD_GIL_EXIT();
MP_THREAD_GIL_ENTER();
#if MICROPY_PY_THREAD_GIL
#if MICROPY_PY_THREAD_GIL_VM_DIVISOR
if (--gil_divisor == 0) {
gil_divisor = MICROPY_PY_THREAD_GIL_VM_DIVISOR;
#else
{
#endif
MP_THREAD_GIL_EXIT();
MP_THREAD_GIL_ENTER();
}
#endif
} // for loop
@ -1269,7 +1307,7 @@ exception_handler:
const byte *ip = code_state->ip + 1;
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
code_state->ip = ip + ulab; // jump to after for-block
code_state->sp -= 1; // pop the exhausted iterator
code_state->sp -= 4; // pop the exhausted iterator
goto outer_dispatch_loop; // continue with dispatch loop
} else if (*code_state->ip == MP_BC_YIELD_FROM) {
// StopIteration inside yield from call means return a value of
@ -1290,7 +1328,7 @@ unwind_loop:
// TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
const byte *ip = code_state->code_info;
mp_uint_t code_info_size = mp_decode_uint(&ip);
size_t code_info_size = mp_decode_uint(&ip);
#if MICROPY_PERSISTENT_CODE
qstr block_name = ip[0] | (ip[1] << 8);
qstr source_file = ip[2] | (ip[3] << 8);
@ -1303,7 +1341,7 @@ unwind_loop:
size_t source_line = 1;
size_t c;
while ((c = *ip)) {
mp_uint_t b, l;
size_t b, l;
if ((c & 0x80) == 0) {
// 0b0LLBBBBB encoding
b = c & 0x1f;

View File

@ -73,6 +73,7 @@ static const void *const entry_table[256] = {
[MP_BC_SETUP_FINALLY] = &&entry_MP_BC_SETUP_FINALLY,
[MP_BC_END_FINALLY] = &&entry_MP_BC_END_FINALLY,
[MP_BC_GET_ITER] = &&entry_MP_BC_GET_ITER,
[MP_BC_GET_ITER_STACK] = &&entry_MP_BC_GET_ITER_STACK,
[MP_BC_FOR_ITER] = &&entry_MP_BC_FOR_ITER,
[MP_BC_POP_BLOCK] = &&entry_MP_BC_POP_BLOCK,
[MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT,

View File

@ -51,7 +51,7 @@ INC += -I../lib/mp-readline
INC += -I../lib/netutils
INC += -I../lib/timeutils
CFLAGS_CORTEX_M = -mthumb -mabi=aapcs-linux -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
CFLAGS_CORTEX_M = -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
CFLAGS_MCU_f4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -DMCU_SERIES_F4
CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 -DMCU_SERIES_F7
CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -DMCU_SERIES_L4
@ -64,7 +64,7 @@ CFLAGS += -Iboards/$(BOARD)
CFLAGS += -DSTM32_HAL_H='<stm32$(MCU_SERIES)xx_hal.h>'
LDFLAGS = -nostdlib -L $(LD_DIR) -T $(LD_FILE) -Map=$(@:.elf=.map) --cref
LIBS =
LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
# Remove uncalled code from the final image.
CFLAGS += -fdata-sections -ffunction-sections
@ -78,9 +78,6 @@ else
COPT += -Os -DNDEBUG
endif
# uncomment this if you want libgcc
#LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
SRC_LIB = $(addprefix lib/,\
libc/string0.c \
libm/math.c \
@ -115,6 +112,7 @@ SRC_LIB = $(addprefix lib/,\
netutils/netutils.c \
timeutils/timeutils.c \
utils/pyexec.c \
utils/interrupt_char.c \
)
DRIVERS_SRC_C = $(addprefix drivers/,\

View File

@ -35,7 +35,7 @@
// I2C busses
#define MICROPY_HW_I2C1_SCL (pin_B6)
#define MICROPY_HW_I2C1_SDA (pin_B7)
#define MICROPY_HW_I2C1_SDA (pin_B9)
//#define MICROPY_HW_I2C2_SCL (pin_B10)
//#define MICROPY_HW_I2C2_SDA (pin_B11)
#define MICROPY_HW_I2C3_SCL (pin_A8)

View File

@ -27,15 +27,10 @@
#include <stdio.h>
#include <string.h>
#include "py/nlr.h"
#include "py/lexer.h"
#include "py/parse.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
#include "py/gc.h"
#include "py/mphal.h"
#include "lib/utils/pyexec.h"
#include "lib/oofatfs/ff.h"
#include "extmod/vfs.h"
@ -695,6 +690,10 @@ soft_reset_exit:
can_deinit();
#endif
#if MICROPY_PY_THREAD
pyb_thread_deinit();
#endif
first_soft_reset = false;
goto soft_reset;
}

View File

@ -41,6 +41,7 @@
#include "extmod/vfs_fat.h"
#include "gccollect.h"
#include "irq.h"
#include "pybthread.h"
#include "rng.h"
#include "storage.h"
#include "pin.h"
@ -159,6 +160,10 @@ STATIC mp_obj_t machine_info(mp_uint_t n_args, const mp_obj_t *args) {
}
}
#if MICROPY_PY_THREAD
pyb_thread_dump();
#endif
if (n_args == 1) {
// arg given means dump gc allocation table
gc_dump_alloc_table();

View File

@ -299,7 +299,21 @@ static inline mp_uint_t disable_irq(void) {
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
#if MICROPY_PY_THREAD
#define MICROPY_EVENT_POLL_HOOK \
do { \
if (pyb_thread_enabled) { \
MP_THREAD_GIL_EXIT(); \
pyb_thread_yield(); \
MP_THREAD_GIL_ENTER(); \
} else { \
__WFI(); \
} \
} while (0);
#else
#define MICROPY_EVENT_POLL_HOOK __WFI();
#endif
// There is no classical C heap in bare-metal ports, only Python
// garbage-collected heap. For completeness, emulate C heap via

View File

@ -21,10 +21,6 @@ NORETURN void mp_hal_raise(HAL_StatusTypeDef status) {
mp_raise_OSError(mp_hal_status_to_errno_table[status]);
}
void mp_hal_set_interrupt_char(int c) {
usb_vcp_set_interrupt_char(c);
}
int mp_hal_stdin_rx_chr(void) {
for (;;) {
#if 0

View File

@ -44,15 +44,13 @@ void mp_thread_init(void) {
void mp_thread_gc_others(void) {
mp_thread_mutex_lock(&thread_mutex, 1);
gc_collect_root((void**)&pyb_thread_cur, 1);
for (pyb_thread_t *th = pyb_thread_cur;; th = th->next) {
for (pyb_thread_t *th = pyb_thread_all; th != NULL; th = th->all_next) {
gc_collect_root((void**)&th, 1);
gc_collect_root(&th->arg, 1);
gc_collect_root(&th->stack, 1);
if (th != pyb_thread_cur) {
gc_collect_root(th->stack, th->stack_len);
}
if (th->next == pyb_thread_cur) {
break;
}
}
mp_thread_mutex_unlock(&thread_mutex);
}
@ -93,31 +91,4 @@ void mp_thread_start(void) {
void mp_thread_finish(void) {
}
void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
*mutex = 0;
}
int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) {
uint32_t irq_state = disable_irq();
if (*mutex) {
// mutex is locked
if (!wait) {
enable_irq(irq_state);
return 0; // failed to lock mutex
}
while (*mutex) {
enable_irq(irq_state);
pyb_thread_yield();
irq_state = disable_irq();
}
}
*mutex = 1;
enable_irq(irq_state);
return 1; // have mutex
}
void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
*mutex = 0;
}
#endif // MICROPY_PY_THREAD

View File

@ -29,7 +29,7 @@
#include "py/mpthread.h"
#include "pybthread.h"
typedef uint32_t mp_thread_mutex_t;
typedef pyb_mutex_t mp_thread_mutex_t;
void mp_thread_init(void);
void mp_thread_gc_others(void);
@ -42,4 +42,16 @@ static inline struct _mp_state_thread_t *mp_thread_get_state(void) {
return pyb_thread_get_local();
}
static inline void mp_thread_mutex_init(mp_thread_mutex_t *m) {
pyb_mutex_init(m);
}
static inline int mp_thread_mutex_lock(mp_thread_mutex_t *m, int wait) {
return pyb_mutex_lock(m, wait);
}
static inline void mp_thread_mutex_unlock(mp_thread_mutex_t *m) {
pyb_mutex_unlock(m);
}
#endif // __MICROPY_INCLUDED_STMHAL_MPTHREADPORT_H__

View File

@ -29,6 +29,7 @@
#include "py/mpstate.h"
#include "py/runtime.h"
#include "lib/utils/interrupt_char.h"
#include "pendsv.h"
#include "irq.h"
@ -52,12 +53,12 @@ void pendsv_init(void) {
// PENDSV feature. This will wait until all interrupts are finished then raise
// the given exception object using nlr_jump in the context of the top-level
// thread.
void pendsv_nlr_jump(void *o) {
void pendsv_kbd_intr(void) {
if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_NULL) {
MP_STATE_VM(mp_pending_exception) = o;
mp_keyboard_interrupt();
} else {
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
pendsv_object = o;
pendsv_object = &MP_STATE_VM(mp_kbd_exception);
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
}
}

View File

@ -25,7 +25,7 @@
*/
void pendsv_init(void);
void pendsv_nlr_jump(void *val);
void pendsv_kbd_intr(void);
// since we play tricks with the stack, the compiler must not generate a
// prelude for this function

View File

@ -120,7 +120,7 @@ STATIC const mp_obj_type_t stdio_obj_type = {
.name = MP_QSTR_FileIO,
// TODO .make_new?
.print = stdio_obj_print,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &stdio_obj_stream_p,
.locals_dict = (mp_obj_t)&stdio_locals_dict,
@ -153,7 +153,7 @@ STATIC const mp_obj_type_t stdio_buffer_obj_type = {
{ &mp_type_type },
.name = MP_QSTR_FileIO,
.print = stdio_obj_print,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &stdio_buffer_obj_stream_p,
.locals_dict = (mp_obj_t)&stdio_locals_dict,

View File

@ -34,29 +34,80 @@
#if MICROPY_PY_THREAD
int pyb_thread_enabled;
pyb_thread_t *pyb_thread_cur;
#define PYB_MUTEX_UNLOCKED ((void*)0)
#define PYB_MUTEX_LOCKED ((void*)1)
extern void __fatal_error(const char*);
volatile int pyb_thread_enabled;
pyb_thread_t *volatile pyb_thread_all;
pyb_thread_t *volatile pyb_thread_cur;
static inline void pyb_thread_add_to_runable(pyb_thread_t *thread) {
thread->run_prev = pyb_thread_cur->run_prev;
thread->run_next = pyb_thread_cur;
pyb_thread_cur->run_prev->run_next = thread;
pyb_thread_cur->run_prev = thread;
}
static inline void pyb_thread_remove_from_runable(pyb_thread_t *thread) {
if (thread->run_next == thread) {
__fatal_error("deadlock");
}
thread->run_prev->run_next = thread->run_next;
thread->run_next->run_prev = thread->run_prev;
}
void pyb_thread_init(pyb_thread_t *thread) {
pyb_thread_enabled = 0;
pyb_thread_all = thread;
pyb_thread_cur = thread;
pyb_thread_cur->sp = NULL; // will be set when this thread switches out
pyb_thread_cur->local_state = 0; // will be set by mp_thread_init
pyb_thread_cur->arg = NULL;
pyb_thread_cur->stack = &_heap_end;
pyb_thread_cur->stack_len = ((uint32_t)&_estack - (uint32_t)&_heap_end) / sizeof(uint32_t);
pyb_thread_cur->prev = thread;
pyb_thread_cur->next = thread;
thread->sp = NULL; // will be set when this thread switches out
thread->local_state = 0; // will be set by mp_thread_init
thread->arg = NULL;
thread->stack = &_heap_end;
thread->stack_len = ((uint32_t)&_estack - (uint32_t)&_heap_end) / sizeof(uint32_t);
thread->all_next = NULL;
thread->run_prev = thread;
thread->run_next = thread;
thread->queue_next = NULL;
}
void pyb_thread_deinit() {
uint32_t irq_state = disable_irq();
pyb_thread_enabled = 0;
pyb_thread_all = pyb_thread_cur;
pyb_thread_cur->all_next = NULL;
pyb_thread_cur->run_prev = pyb_thread_cur;
pyb_thread_cur->run_next = pyb_thread_cur;
enable_irq(irq_state);
}
STATIC void pyb_thread_terminate(void) {
uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV);
pyb_thread_cur->prev->next = pyb_thread_cur->next;
pyb_thread_cur->next->prev = pyb_thread_cur->prev;
if (pyb_thread_cur->next == pyb_thread_cur->prev) {
uint32_t irq_state = disable_irq();
pyb_thread_t *thread = pyb_thread_cur;
// take current thread off the run list
pyb_thread_remove_from_runable(thread);
// take current thread off the list of all threads
for (pyb_thread_t **n = (pyb_thread_t**)&pyb_thread_all;; n = &(*n)->all_next) {
if (*n == thread) {
*n = thread->all_next;
break;
}
}
// clean pointers as much as possible to help GC
thread->all_next = NULL;
thread->queue_next = NULL;
thread->stack = NULL;
if (pyb_thread_all->all_next == NULL) {
// only 1 thread left
pyb_thread_enabled = 0;
}
restore_irq_pri(irq_state);
pyb_thread_yield(); // should not return
// thread switch will occur after we enable irqs
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
enable_irq(irq_state);
// should not return
__fatal_error("could not terminate");
}
uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, void *entry, void *arg) {
@ -77,21 +128,105 @@ uint32_t pyb_thread_new(pyb_thread_t *thread, void *stack, size_t stack_len, voi
thread->arg = arg;
thread->stack = stack;
thread->stack_len = stack_len;
uint32_t irq_state = raise_irq_pri(IRQ_PRI_PENDSV);
thread->queue_next = NULL;
uint32_t irq_state = disable_irq();
pyb_thread_enabled = 1;
thread->next = pyb_thread_cur->next;
thread->prev = pyb_thread_cur;
pyb_thread_cur->next->prev = thread;
pyb_thread_cur->next = thread;
restore_irq_pri(irq_state);
thread->all_next = pyb_thread_all;
pyb_thread_all = thread;
pyb_thread_add_to_runable(thread);
enable_irq(irq_state);
return (uint32_t)thread; // success
}
void pyb_thread_dump(void) {
if (!pyb_thread_enabled) {
printf("THREAD: only main thread\n");
} else {
printf("THREAD:\n");
for (pyb_thread_t *th = pyb_thread_all; th != NULL; th = th->all_next) {
bool runable = false;
for (pyb_thread_t *th2 = pyb_thread_cur;; th2 = th2->run_next) {
if (th == th2) {
runable = true;
break;
}
if (th2->run_next == pyb_thread_cur) {
break;
}
}
printf(" id=%p sp=%p sz=%u", th, th->stack, th->stack_len);
if (runable) {
printf(" (runable)");
}
printf("\n");
}
}
}
// should only be called from pendsv_isr_handler
void *pyb_thread_next(void *sp) {
pyb_thread_cur->sp = sp;
pyb_thread_cur = pyb_thread_cur->next;
pyb_thread_cur = pyb_thread_cur->run_next;
pyb_thread_cur->timeslice = 4; // in milliseconds
return pyb_thread_cur->sp;
}
void pyb_mutex_init(pyb_mutex_t *m) {
*m = PYB_MUTEX_UNLOCKED;
}
int pyb_mutex_lock(pyb_mutex_t *m, int wait) {
uint32_t irq_state = disable_irq();
if (*m == PYB_MUTEX_UNLOCKED) {
// mutex is available
*m = PYB_MUTEX_LOCKED;
enable_irq(irq_state);
} else {
// mutex is locked
if (!wait) {
enable_irq(irq_state);
return 0; // failed to lock mutex
}
if (*m == PYB_MUTEX_LOCKED) {
*m = pyb_thread_cur;
} else {
for (pyb_thread_t *n = *m;; n = n->queue_next) {
if (n->queue_next == NULL) {
n->queue_next = pyb_thread_cur;
break;
}
}
}
pyb_thread_cur->queue_next = NULL;
// take current thread off the run list
pyb_thread_remove_from_runable(pyb_thread_cur);
// thread switch will occur after we enable irqs
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
enable_irq(irq_state);
// when we come back we have the mutex
}
return 1; // have mutex
}
void pyb_mutex_unlock(pyb_mutex_t *m) {
uint32_t irq_state = disable_irq();
if (*m == PYB_MUTEX_LOCKED) {
// no threads are blocked on the mutex
*m = PYB_MUTEX_UNLOCKED;
} else {
// at least one thread is blocked on this mutex
pyb_thread_t *th = *m;
if (th->queue_next == NULL) {
// no other threads are blocked
*m = PYB_MUTEX_LOCKED;
} else {
// at least one other thread is still blocked
*m = th->queue_next;
}
// put unblocked thread on runable list
pyb_thread_add_to_runable(th);
}
enable_irq(irq_state);
}
#endif // MICROPY_PY_THREAD

View File

@ -33,15 +33,23 @@ typedef struct _pyb_thread_t {
void *arg; // thread Python args, a GC root pointer
void *stack; // pointer to the stack
size_t stack_len; // number of words in the stack
struct _pyb_thread_t *prev;
struct _pyb_thread_t *next;
uint32_t timeslice;
struct _pyb_thread_t *all_next;
struct _pyb_thread_t *run_prev;
struct _pyb_thread_t *run_next;
struct _pyb_thread_t *queue_next;
} pyb_thread_t;
extern int pyb_thread_enabled;
extern pyb_thread_t *pyb_thread_cur;
typedef pyb_thread_t *pyb_mutex_t;
extern volatile int pyb_thread_enabled;
extern pyb_thread_t *volatile pyb_thread_all;
extern pyb_thread_t *volatile pyb_thread_cur;
void pyb_thread_init(pyb_thread_t *th);
void pyb_thread_deinit();
uint32_t pyb_thread_new(pyb_thread_t *th, void *stack, size_t stack_len, void *entry, void *arg);
void pyb_thread_dump(void);
static inline uint32_t pyb_thread_get_id(void) {
return (uint32_t)pyb_thread_cur;
@ -56,7 +64,15 @@ static inline void *pyb_thread_get_local(void) {
}
static inline void pyb_thread_yield(void) {
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
if (pyb_thread_cur->run_next == pyb_thread_cur) {
__WFI();
} else {
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
}
}
void pyb_mutex_init(pyb_mutex_t *m);
int pyb_mutex_lock(pyb_mutex_t *m, int wait);
void pyb_mutex_unlock(pyb_mutex_t *m);
#endif // MICROPY_INCLUDED_STMHAL_PYBTHREAD_H

View File

@ -70,6 +70,7 @@
#include "stm32_it.h"
#include STM32_HAL_H
#include "py/mpstate.h"
#include "py/obj.h"
#include "py/mphal.h"
#include "pendsv.h"
@ -315,9 +316,14 @@ void SysTick_Handler(void) {
}
#if MICROPY_PY_THREAD
// signal a thread switch at 4ms=250Hz
if (pyb_thread_enabled && (uwTick & 0x03) == 0x03) {
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
if (pyb_thread_enabled) {
if (pyb_thread_cur->timeslice == 0) {
if (pyb_thread_cur->run_next != pyb_thread_cur) {
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
}
} else {
--pyb_thread_cur->timeslice;
}
}
#endif
}

View File

@ -29,9 +29,11 @@
#include "py/obj.h"
#include "irq.h"
#include "systick.h"
#include "pybthread.h"
// We provide our own version of HAL_Delay that calls __WFI while waiting, in
// order to reduce power consumption.
// Note: Upon entering this function we may or may not have the GIL.
void HAL_Delay(uint32_t Delay) {
if (query_irq() == IRQ_STATE_ENABLED) {
// IRQs enabled, so can use systick counter to do the delay
@ -40,7 +42,15 @@ void HAL_Delay(uint32_t Delay) {
// Wraparound of tick is taken care of by 2's complement arithmetic.
while (uwTick - start < Delay) {
// Enter sleep mode, waiting for (at least) the SysTick interrupt.
#if MICROPY_PY_THREAD
if (pyb_thread_enabled) {
pyb_thread_yield();
} else {
__WFI();
}
#else
__WFI();
#endif
}
} else {
// IRQs disabled, so need to use a busy loop for the delay.

View File

@ -1037,7 +1037,7 @@ const mp_obj_type_t pyb_uart_type = {
.name = MP_QSTR_UART,
.print = pyb_uart_print,
.make_new = pyb_uart_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &uart_stream_p,
.locals_dict = (mp_obj_t)&pyb_uart_locals_dict,

View File

@ -38,6 +38,7 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "bufhelper.h"
#include "usb.h"
@ -96,7 +97,7 @@ const mp_obj_tuple_t pyb_usb_hid_keyboard_obj = {
};
void pyb_usb_init0(void) {
USBD_CDC_SetInterrupt(-1);
mp_hal_set_interrupt_char(-1);
MP_STATE_PORT(pyb_hid_report_desc) = MP_OBJ_NULL;
}
@ -141,15 +142,6 @@ bool usb_vcp_is_enabled(void) {
return (pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED) != 0;
}
void usb_vcp_set_interrupt_char(int c) {
if (pyb_usb_flags & PYB_USB_FLAG_DEV_ENABLED) {
if (c != -1) {
mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
}
USBD_CDC_SetInterrupt(c);
}
}
int usb_vcp_recv_byte(uint8_t *c) {
return USBD_CDC_Rx(c, 1, 0);
}
@ -364,7 +356,7 @@ STATIC mp_obj_t pyb_usb_vcp_make_new(const mp_obj_type_t *type, size_t n_args, s
}
STATIC mp_obj_t pyb_usb_vcp_setinterrupt(mp_obj_t self_in, mp_obj_t int_chr_in) {
usb_vcp_set_interrupt_char(mp_obj_get_int(int_chr_in));
mp_hal_set_interrupt_char(mp_obj_get_int(int_chr_in));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_usb_vcp_setinterrupt_obj, pyb_usb_vcp_setinterrupt);
@ -526,7 +518,7 @@ const mp_obj_type_t pyb_usb_vcp_type = {
.name = MP_QSTR_USB_VCP,
.print = pyb_usb_vcp_print,
.make_new = pyb_usb_vcp_make_new,
.getiter = mp_identity,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &pyb_usb_vcp_stream_p,
.locals_dict = (mp_obj_t)&pyb_usb_vcp_locals_dict,

View File

@ -61,7 +61,6 @@ void pyb_usb_init0(void);
bool pyb_usb_dev_init(uint16_t vid, uint16_t pid, usb_device_mode_t mode, USBD_HID_ModeInfoTypeDef *hid_info);
void pyb_usb_dev_deinit(void);
bool usb_vcp_is_enabled(void);
void usb_vcp_set_interrupt_char(int c);
int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0
void usb_vcp_send_strn(const char* str, int len);
void usb_vcp_send_strn_cooked(const char *str, int len);

View File

@ -43,6 +43,7 @@
#include "py/mpstate.h"
#include "py/obj.h"
#include "lib/utils/interrupt_char.h"
#include "irq.h"
#include "timer.h"
#include "usb.h"
@ -79,8 +80,6 @@ static uint16_t UserTxBufPtrOutShadow = 0; // shadow of above
static uint8_t UserTxBufPtrWaitCount = 0; // used to implement a timeout waiting for low-level USB driver
static uint8_t UserTxNeedEmptyPacket = 0; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
static int user_interrupt_char = -1;
/* Private function prototypes -----------------------------------------------*/
static int8_t CDC_Itf_Init (void);
static int8_t CDC_Itf_DeInit (void);
@ -147,13 +146,6 @@ static int8_t CDC_Itf_Init(void)
UserRxBufCur = 0;
UserRxBufLen = 0;
/* NOTE: we cannot reset these here, because USBD_CDC_SetInterrupt
* may be called before this init function to set these values.
* This can happen if the USB enumeration occurs after the call to
* USBD_CDC_SetInterrupt.
user_interrupt_char = -1;
*/
return (USBD_OK);
}
@ -339,7 +331,7 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
uint32_t delta_len;
if (user_interrupt_char == -1) {
if (mp_interrupt_char == -1) {
// no special interrupt character
delta_len = *Len;
@ -350,10 +342,10 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
uint8_t *src = Buf;
uint8_t *buf_top = Buf + *Len;
for (; src < buf_top; src++) {
if (*src == user_interrupt_char) {
if (*src == mp_interrupt_char) {
char_found = true;
// raise exception when interrupts are finished
pendsv_nlr_jump(&MP_STATE_VM(mp_kbd_exception));
// raise KeyboardInterrupt when interrupts are finished
pendsv_kbd_intr();
} else {
if (char_found) {
*dest = *src;
@ -385,10 +377,6 @@ int USBD_CDC_IsConnected(void) {
return dev_is_connected;
}
void USBD_CDC_SetInterrupt(int chr) {
user_interrupt_char = chr;
}
int USBD_CDC_TxHalfEmpty(void) {
int32_t tx_waiting = (int32_t)UserTxBufPtrIn - (int32_t)UserTxBufPtrOut;
if (tx_waiting < 0) {

View File

@ -32,7 +32,6 @@
extern const USBD_CDC_ItfTypeDef USBD_CDC_fops;
int USBD_CDC_IsConnected(void);
void USBD_CDC_SetInterrupt(int chr);
int USBD_CDC_TxHalfEmpty(void);
int USBD_CDC_Tx(const uint8_t *buf, uint32_t len, uint32_t timeout);

Some files were not shown because too many files have changed in this diff Show More