summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
authorMark <56205165+gamblor21@users.noreply.github.com>2020-10-16 15:52:45 -0500
committerGitHub <noreply@github.com>2020-10-16 15:52:45 -0500
commit8e6d3e5b91f4c7cdb0dc4743a9a9937708daa624 (patch)
tree6d541d14808bd8456b17303fb654a73300f1adc5 /py
parent645382d51d37a40312118eebc11da75639913fce (diff)
parentf0b37313c5adf2ad940d7279aa49620d36d7292d (diff)
Merge branch 'main' into recv_into_size_check6.1.0-alpha.0
Diffstat (limited to 'py')
-rw-r--r--py/circuitpy_defns.mk7
-rw-r--r--py/circuitpy_mpconfig.h1
-rw-r--r--py/circuitpy_mpconfig.mk13
-rw-r--r--py/compile.c17
-rw-r--r--py/genlast.py71
-rw-r--r--py/mkrules.mk10
-rw-r--r--py/objgenerator.c18
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);