Merge branch 'master' into nrf52
This commit is contained in:
commit
05ec4f64e2
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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::
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -1,4 +1,4 @@
|
|||
from machine import Pin
|
||||
from machine import Pin, Signal
|
||||
|
||||
# 96Boards/Qualcomm DragonBoard 410c
|
||||
#
|
||||
|
|
|
@ -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))
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
26
extmod/vfs.c
26
extmod/vfs.c
|
@ -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);
|
||||
|
|
|
@ -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.
|
@ -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) \
|
||||
|
|
1
py/bc0.h
1
py/bc0.h
|
@ -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
|
||||
|
|
102
py/compile.c
102
py/compile.c
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
21
py/emitbc.c
21
py/emitbc.c
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
240
py/grammar.h
240
py/grammar.h
|
@ -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))
|
||||
|
|
473
py/lexer.c
473
py/lexer.c
|
@ -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.
|
||||
|
|
44
py/lexer.h
44
py/lexer.h
|
@ -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);
|
||||
|
|
32
py/map.c
32
py/map.c
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
64
py/mpz.c
64
py/mpz.c
|
@ -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) {
|
||||
|
|
19
py/mpz.h
19
py/mpz.h
|
@ -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__
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -115,5 +115,5 @@ nlr_jump:
|
|||
|
||||
#endif // defined(__xtensa__)
|
||||
#if defined(linux)
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
|
5
py/obj.c
5
py/obj.c
|
@ -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) {
|
||||
|
|
79
py/obj.h
79
py/obj.h
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
49
py/objdict.c
49
py/objdict.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
24
py/objfun.c
24
py/objfun.c
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
31
py/objlist.c
31
py/objlist.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
41
py/objset.c
41
py/objset.c
|
@ -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);
|
||||
|
|
71
py/objstr.c
71
py/objstr.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
40
py/objtype.c
40
py/objtype.c
|
@ -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 instance’s __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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
28
py/parse.c
28
py/parse.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
62
py/runtime.c
62
py/runtime.c
|
@ -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) != '_') {
|
||||
|
|
18
py/runtime.h
18
py/runtime.h
|
@ -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)))
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
70
py/vm.c
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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/,\
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
16
stmhal/usb.c
16
stmhal/usb.c
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue