diff options
author | Damien George <damien@micropython.org> | 2020-06-16 21:42:44 +1000 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2020-06-16 22:02:24 +1000 |
commit | 178395031157f61af5426add2de1d76d91440b21 (patch) | |
tree | 4f4898ff7f2e707e5b5e4a7245422b07689fb338 /py/compile.c | |
parent | 0fd91e39b1711772c88cfe4e0aaf817fe3387ba6 (diff) |
py/compile: Implement PEP 572, assignment expressions with := operator.
The syntax matches CPython and the semantics are equivalent except that,
unlike CPython, MicroPython allows using := to assign to comprehension
iteration variables, because disallowing this would take a lot of code to
check for it.
The new compile-time option MICROPY_PY_ASSIGN_EXPR selects this feature and
is enabled by default, following MICROPY_PY_ASYNC_AWAIT.
Diffstat (limited to 'py/compile.c')
-rw-r--r-- | py/compile.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/py/compile.c b/py/compile.c index 8835ec2f8..da5c9190a 100644 --- a/py/compile.c +++ b/py/compile.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013-2015 Damien P. George + * Copyright (c) 2013-2020 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -2108,6 +2108,27 @@ STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_funcdef_lambdef(comp, this_scope, pns->nodes[0], PN_varargslist); } +#if MICROPY_PY_ASSIGN_EXPR +STATIC void compile_namedexpr_helper(compiler_t *comp, mp_parse_node_t pn_name, mp_parse_node_t pn_expr) { + if (!MP_PARSE_NODE_IS_ID(pn_name)) { + compile_syntax_error(comp, (mp_parse_node_t)pn_name, MP_ERROR_TEXT("can't assign to expression")); + } + compile_node(comp, pn_expr); + EMIT(dup_top); + scope_t *old_scope = comp->scope_cur; + if (SCOPE_IS_COMP_LIKE(comp->scope_cur->kind)) { + // Use parent's scope for assigned value so it can "escape" + comp->scope_cur = comp->scope_cur->parent; + } + compile_store_id(comp, MP_PARSE_NODE_LEAF_ARG(pn_name)); + comp->scope_cur = old_scope; +} + +STATIC void compile_namedexpr(compiler_t *comp, mp_parse_node_struct_t *pns) { + compile_namedexpr_helper(comp, pns->nodes[0], pns->nodes[1]); +} +#endif + STATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) { bool cond = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test; uint l_end = comp_next_label(comp); @@ -2353,6 +2374,12 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar star_flags |= MP_EMIT_STAR_FLAG_DOUBLE; dblstar_args_node = pns_arg; } else if (MP_PARSE_NODE_STRUCT_KIND(pns_arg) == PN_argument) { + #if MICROPY_PY_ASSIGN_EXPR + if (MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_argument_4)) { + compile_namedexpr_helper(comp, pns_arg->nodes[0], ((mp_parse_node_struct_t *)pns_arg->nodes[1])->nodes[0]); + n_positional++; + } else + #endif if (!MP_PARSE_NODE_IS_STRUCT_KIND(pns_arg->nodes[1], PN_comp_for)) { if (!MP_PARSE_NODE_IS_ID(pns_arg->nodes[0])) { compile_syntax_error(comp, (mp_parse_node_t)pns_arg, MP_ERROR_TEXT("LHS of keyword arg must be an id")); |