diff options
| author | Mark <56205165+gamblor21@users.noreply.github.com> | 2020-10-16 15:52:45 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-16 15:52:45 -0500 |
| commit | 8e6d3e5b91f4c7cdb0dc4743a9a9937708daa624 (patch) | |
| tree | 6d541d14808bd8456b17303fb654a73300f1adc5 /py | |
| parent | 645382d51d37a40312118eebc11da75639913fce (diff) | |
| parent | f0b37313c5adf2ad940d7279aa49620d36d7292d (diff) | |
Merge branch 'main' into recv_into_size_check6.1.0-alpha.0
Diffstat (limited to 'py')
| -rw-r--r-- | py/circuitpy_defns.mk | 7 | ||||
| -rw-r--r-- | py/circuitpy_mpconfig.h | 1 | ||||
| -rw-r--r-- | py/circuitpy_mpconfig.mk | 13 | ||||
| -rw-r--r-- | py/compile.c | 17 | ||||
| -rw-r--r-- | py/genlast.py | 71 | ||||
| -rw-r--r-- | py/mkrules.mk | 10 | ||||
| -rw-r--r-- | py/objgenerator.c | 18 |
7 files changed, 117 insertions, 20 deletions
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 76c0a4db6..ccdf973e9 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -45,7 +45,6 @@ BASE_CFLAGS = \ -Wnested-externs \ -Wunreachable-code \ -Wcast-align \ - -Wno-error=lto-type-mismatch \ -D__$(CHIP_VARIANT)__ \ -ffunction-sections \ -fdata-sections \ @@ -66,7 +65,6 @@ ifneq ($(FROZEN_DIR),) # To use frozen source modules, put your .py files in a subdirectory (eg scripts/) # and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch). CFLAGS += -DMICROPY_MODULE_FROZEN_STR -CFLAGS += -Wno-error=lto-type-mismatch endif # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and @@ -76,7 +74,6 @@ endif ifneq ($(FROZEN_MPY_DIRS),) CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY -CFLAGS += -Wno-error=lto-type-mismatch endif @@ -528,10 +525,10 @@ SRC_MOD += $(addprefix lib/mp3/src/, \ $(BUILD)/lib/mp3/src/buffers.o: CFLAGS += -include "py/misc.h" -D'MPDEC_ALLOCATOR(x)=m_malloc(x,0)' -D'MPDEC_FREE(x)=m_free(x)' endif ifeq ($(CIRCUITPY_RGBMATRIX),1) -SRC_MOD += $(addprefix lib/protomatter/, \ +SRC_MOD += $(addprefix lib/protomatter/src/, \ core.c \ ) -$(BUILD)/lib/protomatter/core.o: CFLAGS += -include "shared-module/rgbmatrix/allocator.h" -DCIRCUITPY -Wno-missing-braces +$(BUILD)/lib/protomatter/src/core.o: CFLAGS += -include "shared-module/rgbmatrix/allocator.h" -DCIRCUITPY -Wno-missing-braces endif # All possible sources are listed here, and are filtered by SRC_PATTERNS. diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index a0eb4fc07..1e01bd9c5 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -79,7 +79,6 @@ #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) -#define MICROPY_PY_ASYNC_AWAIT (0) #define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_BUILTINS_BYTEARRAY (1) diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 9b9bd83b4..a6aabec33 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -32,6 +32,9 @@ CIRCUITPY_FULL_BUILD ?= 1 CFLAGS += -DCIRCUITPY_FULL_BUILD=$(CIRCUITPY_FULL_BUILD) +# async/await language keyword support +MICROPY_PY_ASYNC_AWAIT ?= $(CIRCUITPY_FULL_BUILD) +CFLAGS += -DMICROPY_PY_ASYNC_AWAIT=$(MICROPY_PY_ASYNC_AWAIT) CIRCUITPY_AESIO ?= 0 CFLAGS += -DCIRCUITPY_AESIO=$(CIRCUITPY_AESIO) @@ -76,14 +79,14 @@ CFLAGS += -DCIRCUITPY_AUDIOMP3=$(CIRCUITPY_AUDIOMP3) CIRCUITPY_BITBANGIO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_BITBANGIO=$(CIRCUITPY_BITBANGIO) -# Explicitly enabled for boards that support _bleio. -CIRCUITPY_BLEIO ?= 0 -CFLAGS += -DCIRCUITPY_BLEIO=$(CIRCUITPY_BLEIO) - # _bleio can be supported on most any board via HCI -CIRCUITPY_BLEIO_HCI ?= 0 +CIRCUITPY_BLEIO_HCI ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_BLEIO_HCI=$(CIRCUITPY_BLEIO_HCI) +# Explicitly enabled for boards that support _bleio. +CIRCUITPY_BLEIO ?= $(CIRCUITPY_BLEIO_HCI) +CFLAGS += -DCIRCUITPY_BLEIO=$(CIRCUITPY_BLEIO) + CIRCUITPY_BOARD ?= 1 CFLAGS += -DCIRCUITPY_BOARD=$(CIRCUITPY_BOARD) diff --git a/py/compile.c b/py/compile.c index 653aae004..04bcf5bc1 100644 --- a/py/compile.c +++ b/py/compile.c @@ -853,7 +853,7 @@ STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) { mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t*)pns_body->nodes[0]; body_name = compile_funcdef_helper(comp, pns0, emit_options); scope_t *fscope = (scope_t*)pns0->nodes[4]; - fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR; + fscope->scope_flags |= MP_SCOPE_FLAG_GENERATOR | MP_SCOPE_FLAG_ASYNC; #endif } else { assert(MP_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef); // should be @@ -2632,6 +2632,12 @@ STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(yield, MP_EMIT_YIELD_VALUE); } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) { pns = (mp_parse_node_struct_t*)pns->nodes[0]; +#if MICROPY_PY_ASYNC_AWAIT + if(comp->scope_cur->scope_flags & MP_SCOPE_FLAG_ASYNC) { + compile_syntax_error(comp, (mp_parse_node_t)pns, translate("'yield from' inside async function")); + return; + } +#endif compile_node(comp, pns->nodes[0]); compile_yield_from(comp); } else { @@ -2648,7 +2654,14 @@ STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pn } compile_require_async_context(comp, pns); compile_atom_expr_normal(comp, pns); - compile_yield_from(comp); + + // If it's an awaitable thing, need to reach for the __await__ method for the coroutine. + // async def functions' __await__ return themselves, which are able to receive a send(), + // while other types with custom __await__ implementations return async generators. + EMIT_ARG(load_method, MP_QSTR___await__, false); + EMIT_ARG(call_method, 0, 0, 0); + EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); + EMIT_ARG(yield, MP_EMIT_YIELD_FROM); } #endif diff --git a/py/genlast.py b/py/genlast.py new file mode 100644 index 000000000..1df2a2482 --- /dev/null +++ b/py/genlast.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +import sys +import re +import os +import itertools +from concurrent.futures import ProcessPoolExecutor +import multiprocessing +import threading +import subprocess + +from makeqstrdefs import qstr_unescape, QSTRING_BLACK_LIST + +re_line = re.compile(r"#[line]*\s(\d+)\s\"([^\"]+)\"", re.DOTALL) +re_qstr = re.compile(r'MP_QSTR_[_a-zA-Z0-9]+', re.DOTALL) +re_translate = re.compile(r'translate\(\"((?:(?=(\\?))\2.)*?)\"\)', re.DOTALL) + +def write_out(fname, output_dir, output): + if output: + for m, r in [("/", "__"), ("\\", "__"), (":", "@"), ("..", "@@")]: + fname = fname.replace(m, r) + with open(output_dir + "/" + fname + ".qstr", "w") as f: + f.write("\n".join(output) + "\n") + +def process_file(fname, output_dir, content): + content = content.decode('utf-8', errors='ignore') + output = [] + for match in re_qstr.findall(content): + name = match.replace('MP_QSTR_', '') + if name not in QSTRING_BLACK_LIST: + output.append('Q(' + qstr_unescape(name) + ')') + for match in re_translate.findall(content): + output.append('TRANSLATE("' + match[0] + '")') + + write_out(fname, output_dir, output) + + +def checkoutput1(args): + info = subprocess.run(args, check=True, stdout=subprocess.PIPE, input='') + return info.stdout + +def preprocess(command, output_dir, fn): + try: + output = checkoutput1(command + [fn]) + process_file(fn, output_dir, output) + except Exception as e: + print(e, file=sys.stderr) + +def maybe_preprocess(command, output_dir, fn): + if subprocess.call(["grep", "-lqE", "(MP_QSTR|translate)", fn]) == 0: + preprocess(command, output_dir, fn) + +if __name__ == '__main__': + + + idx1 = sys.argv.index('--') + idx2 = sys.argv.index('--', idx1+1) + output_dir = sys.argv[1] + check = sys.argv[2:idx1] + always = sys.argv[idx1+1:idx2] + command = sys.argv[idx2+1:] + + if not os.path.isdir(output_dir): + os.makedirs(output_dir) + + # Mac and Windows use 'spawn'. Uncomment this during testing to catch spawn-specific problems on Linux. + #multiprocessing.set_start_method("spawn") + executor = ProcessPoolExecutor(max_workers=multiprocessing.cpu_count() + 1) + executor.map(maybe_preprocess, itertools.repeat(command), itertools.repeat(output_dir), check) + executor.map(preprocess, itertools.repeat(command), itertools.repeat(output_dir), always) + executor.shutdown() diff --git a/py/mkrules.mk b/py/mkrules.mk index 0b3ecc0e1..549b0e5e4 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -76,18 +76,14 @@ $(OBJ): | $(HEADER_BUILD)/qstrdefs.enum.h $(HEADER_BUILD)/mpversion.h # - if anything in QSTR_GLOBAL_DEPENDENCIES is newer, then process all source files ($^) # - else, if list of newer prerequisites ($?) is not empty, then process just these ($?) # - else, process all source files ($^) [this covers "make -B" which can set $? to empty] -$(HEADER_BUILD)/qstr.i.last: $(SRC_QSTR) $(SRC_QSTR_PREPROCESSOR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)/mpversion.h +$(HEADER_BUILD)/qstr.split: $(SRC_QSTR) $(SRC_QSTR_PREPROCESSOR) $(QSTR_GLOBAL_DEPENDENCIES) | $(HEADER_BUILD)/mpversion.h $(PY_SRC)/genlast.py $(STEPECHO) "GEN $@" - $(Q)grep -lE "(MP_QSTR|translate)" $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) | xargs $(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(SRC_QSTR_PREPROCESSOR) >$(HEADER_BUILD)/qstr.i.last; - -$(HEADER_BUILD)/qstr.split: $(HEADER_BUILD)/qstr.i.last $(PY_SRC)/makeqstrdefs.py - $(STEPECHO) "GEN $@" - $(Q)$(PYTHON3) $(PY_SRC)/makeqstrdefs.py split $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED) + $(Q)$(PYTHON3) $(PY_SRC)/genlast.py $(HEADER_BUILD)/qstr $(if $(filter $?,$(QSTR_GLOBAL_DEPENDENCIES)),$^,$(if $?,$?,$^)) -- $(SRC_QSTR_PREPROCESSOR) -- $(CPP) $(QSTR_GEN_EXTRA_CFLAGS) $(CFLAGS) $(Q)touch $@ $(QSTR_DEFS_COLLECTED): $(HEADER_BUILD)/qstr.split $(PY_SRC)/makeqstrdefs.py $(STEPECHO) "GEN $@" - $(Q)$(PYTHON3) $(PY_SRC)/makeqstrdefs.py cat $(HEADER_BUILD)/qstr.i.last $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED) + $(Q)$(PYTHON3) $(PY_SRC)/makeqstrdefs.py cat - $(HEADER_BUILD)/qstr $(QSTR_DEFS_COLLECTED) # $(sort $(var)) removes duplicates # diff --git a/py/objgenerator.c b/py/objgenerator.c index df421b60c..5e651ac26 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -225,6 +225,21 @@ STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send); +#if MICROPY_PY_ASYNC_AWAIT +STATIC mp_obj_t gen_instance_await(mp_obj_t self_in) { + mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); + if ( !self->coroutine_generator ) { + // Pretend like a generator does not have this coroutine behavior. + // Pay no attention to the dir() behind the curtain + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, + translate("type object 'generator' has no attribute '__await__'"))); + } + // You can directly call send on a coroutine generator or you can __await__ then send on the return of that. + return self; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_await_obj, gen_instance_await); +#endif + STATIC mp_obj_t gen_instance_close(mp_obj_t self_in); STATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) { mp_obj_t exc = (n_args == 2) ? args[1] : args[2]; @@ -280,6 +295,9 @@ STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { #if MICROPY_PY_GENERATOR_PEND_THROW { MP_ROM_QSTR(MP_QSTR_pend_throw), MP_ROM_PTR(&gen_instance_pend_throw_obj) }, #endif + #if MICROPY_PY_ASYNC_AWAIT + { MP_ROM_QSTR(MP_QSTR___await__), MP_ROM_PTR(&gen_instance_await_obj) }, + #endif }; STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table); |
