diff options
author | Brandt Bucher <brandtbucher@gmail.com> | 2021-02-26 22:51:55 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-26 22:51:55 (GMT) |
commit | 145bf269df3530176f6ebeab1324890ef7070bf8 (patch) | |
tree | 4c4928d6250785372171a52be0b7269aa444511b /Python | |
parent | cc02b4f2e810ab524d845daa18bc94df5b092dd8 (diff) | |
download | cpython-145bf269df3530176f6ebeab1324890ef7070bf8.zip cpython-145bf269df3530176f6ebeab1324890ef7070bf8.tar.gz cpython-145bf269df3530176f6ebeab1324890ef7070bf8.tar.bz2 |
bpo-42128: Structural Pattern Matching (PEP 634) (GH-22917)
Co-authored-by: Guido van Rossum <guido@python.org>
Co-authored-by: Talin <viridia@gmail.com>
Co-authored-by: Pablo Galindo <pablogsal@gmail.com>
Diffstat (limited to 'Python')
-rw-r--r-- | Python/Python-ast.c | 469 | ||||
-rw-r--r-- | Python/ast.c | 29 | ||||
-rw-r--r-- | Python/ast_opt.c | 130 | ||||
-rw-r--r-- | Python/ceval.c | 382 | ||||
-rw-r--r-- | Python/compile.c | 739 | ||||
-rw-r--r-- | Python/importlib_external.h | 218 | ||||
-rw-r--r-- | Python/opcode_targets.h | 12 | ||||
-rw-r--r-- | Python/pystate.c | 2 | ||||
-rw-r--r-- | Python/symtable.c | 34 |
9 files changed, 1872 insertions, 143 deletions
diff --git a/Python/Python-ast.c b/Python/Python-ast.c index debd3e3..439da8f 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -91,6 +91,9 @@ struct ast_state { PyObject *Lt_type; PyObject *MatMult_singleton; PyObject *MatMult_type; + PyObject *MatchAs_type; + PyObject *MatchOr_type; + PyObject *Match_type; PyObject *Mod_singleton; PyObject *Mod_type; PyObject *Module_type; @@ -137,6 +140,7 @@ struct ast_state { PyObject *Yield_type; PyObject *__dict__; PyObject *__doc__; + PyObject *__match_args__; PyObject *__module__; PyObject *_attributes; PyObject *_fields; @@ -153,6 +157,7 @@ struct ast_state { PyObject *bases; PyObject *body; PyObject *boolop_type; + PyObject *cases; PyObject *cause; PyObject *cmpop_type; PyObject *col_offset; @@ -175,6 +180,7 @@ struct ast_state { PyObject *format_spec; PyObject *func; PyObject *generators; + PyObject *guard; PyObject *handlers; PyObject *id; PyObject *ifs; @@ -193,6 +199,7 @@ struct ast_state { PyObject *level; PyObject *lineno; PyObject *lower; + PyObject *match_case_type; PyObject *mod_type; PyObject *module; PyObject *msg; @@ -204,6 +211,8 @@ struct ast_state { PyObject *ops; PyObject *optional_vars; PyObject *orelse; + PyObject *pattern; + PyObject *patterns; PyObject *posonlyargs; PyObject *returns; PyObject *right; @@ -211,6 +220,7 @@ struct ast_state { PyObject *slice; PyObject *step; PyObject *stmt_type; + PyObject *subject; PyObject *tag; PyObject *target; PyObject *targets; @@ -348,6 +358,9 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->Lt_type); Py_CLEAR(state->MatMult_singleton); Py_CLEAR(state->MatMult_type); + Py_CLEAR(state->MatchAs_type); + Py_CLEAR(state->MatchOr_type); + Py_CLEAR(state->Match_type); Py_CLEAR(state->Mod_singleton); Py_CLEAR(state->Mod_type); Py_CLEAR(state->Module_type); @@ -394,6 +407,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->Yield_type); Py_CLEAR(state->__dict__); Py_CLEAR(state->__doc__); + Py_CLEAR(state->__match_args__); Py_CLEAR(state->__module__); Py_CLEAR(state->_attributes); Py_CLEAR(state->_fields); @@ -410,6 +424,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->bases); Py_CLEAR(state->body); Py_CLEAR(state->boolop_type); + Py_CLEAR(state->cases); Py_CLEAR(state->cause); Py_CLEAR(state->cmpop_type); Py_CLEAR(state->col_offset); @@ -432,6 +447,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->format_spec); Py_CLEAR(state->func); Py_CLEAR(state->generators); + Py_CLEAR(state->guard); Py_CLEAR(state->handlers); Py_CLEAR(state->id); Py_CLEAR(state->ifs); @@ -450,6 +466,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->level); Py_CLEAR(state->lineno); Py_CLEAR(state->lower); + Py_CLEAR(state->match_case_type); Py_CLEAR(state->mod_type); Py_CLEAR(state->module); Py_CLEAR(state->msg); @@ -461,6 +478,8 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->ops); Py_CLEAR(state->optional_vars); Py_CLEAR(state->orelse); + Py_CLEAR(state->pattern); + Py_CLEAR(state->patterns); Py_CLEAR(state->posonlyargs); Py_CLEAR(state->returns); Py_CLEAR(state->right); @@ -468,6 +487,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->slice); Py_CLEAR(state->step); Py_CLEAR(state->stmt_type); + Py_CLEAR(state->subject); Py_CLEAR(state->tag); Py_CLEAR(state->target); Py_CLEAR(state->targets); @@ -494,6 +514,7 @@ static int init_identifiers(struct ast_state *state) { if ((state->__dict__ = PyUnicode_InternFromString("__dict__")) == NULL) return 0; if ((state->__doc__ = PyUnicode_InternFromString("__doc__")) == NULL) return 0; + if ((state->__match_args__ = PyUnicode_InternFromString("__match_args__")) == NULL) return 0; if ((state->__module__ = PyUnicode_InternFromString("__module__")) == NULL) return 0; if ((state->_attributes = PyUnicode_InternFromString("_attributes")) == NULL) return 0; if ((state->_fields = PyUnicode_InternFromString("_fields")) == NULL) return 0; @@ -506,6 +527,7 @@ static int init_identifiers(struct ast_state *state) if ((state->attr = PyUnicode_InternFromString("attr")) == NULL) return 0; if ((state->bases = PyUnicode_InternFromString("bases")) == NULL) return 0; if ((state->body = PyUnicode_InternFromString("body")) == NULL) return 0; + if ((state->cases = PyUnicode_InternFromString("cases")) == NULL) return 0; if ((state->cause = PyUnicode_InternFromString("cause")) == NULL) return 0; if ((state->col_offset = PyUnicode_InternFromString("col_offset")) == NULL) return 0; if ((state->comparators = PyUnicode_InternFromString("comparators")) == NULL) return 0; @@ -523,6 +545,7 @@ static int init_identifiers(struct ast_state *state) if ((state->format_spec = PyUnicode_InternFromString("format_spec")) == NULL) return 0; if ((state->func = PyUnicode_InternFromString("func")) == NULL) return 0; if ((state->generators = PyUnicode_InternFromString("generators")) == NULL) return 0; + if ((state->guard = PyUnicode_InternFromString("guard")) == NULL) return 0; if ((state->handlers = PyUnicode_InternFromString("handlers")) == NULL) return 0; if ((state->id = PyUnicode_InternFromString("id")) == NULL) return 0; if ((state->ifs = PyUnicode_InternFromString("ifs")) == NULL) return 0; @@ -549,12 +572,15 @@ static int init_identifiers(struct ast_state *state) if ((state->ops = PyUnicode_InternFromString("ops")) == NULL) return 0; if ((state->optional_vars = PyUnicode_InternFromString("optional_vars")) == NULL) return 0; if ((state->orelse = PyUnicode_InternFromString("orelse")) == NULL) return 0; + if ((state->pattern = PyUnicode_InternFromString("pattern")) == NULL) return 0; + if ((state->patterns = PyUnicode_InternFromString("patterns")) == NULL) return 0; if ((state->posonlyargs = PyUnicode_InternFromString("posonlyargs")) == NULL) return 0; if ((state->returns = PyUnicode_InternFromString("returns")) == NULL) return 0; if ((state->right = PyUnicode_InternFromString("right")) == NULL) return 0; if ((state->simple = PyUnicode_InternFromString("simple")) == NULL) return 0; if ((state->slice = PyUnicode_InternFromString("slice")) == NULL) return 0; if ((state->step = PyUnicode_InternFromString("step")) == NULL) return 0; + if ((state->subject = PyUnicode_InternFromString("subject")) == NULL) return 0; if ((state->tag = PyUnicode_InternFromString("tag")) == NULL) return 0; if ((state->target = PyUnicode_InternFromString("target")) == NULL) return 0; if ((state->targets = PyUnicode_InternFromString("targets")) == NULL) return 0; @@ -579,6 +605,7 @@ GENERATE_ASDL_SEQ_CONSTRUCTOR(arg, arg_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(keyword, keyword_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(alias, alias_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(withitem, withitem_ty) +GENERATE_ASDL_SEQ_CONSTRUCTOR(match_case, match_case_ty) GENERATE_ASDL_SEQ_CONSTRUCTOR(type_ignore, type_ignore_ty) static PyObject* ast2obj_mod(struct ast_state *state, void*); @@ -682,6 +709,10 @@ static const char * const AsyncWith_fields[]={ "body", "type_comment", }; +static const char * const Match_fields[]={ + "subject", + "cases", +}; static const char * const Raise_fields[]={ "exc", "cause", @@ -832,6 +863,13 @@ static const char * const Slice_fields[]={ "upper", "step", }; +static const char * const MatchAs_fields[]={ + "pattern", + "name", +}; +static const char * const MatchOr_fields[]={ + "patterns", +}; static PyObject* ast2obj_expr_context(struct ast_state *state, expr_context_ty); static PyObject* ast2obj_boolop(struct ast_state *state, boolop_ty); static PyObject* ast2obj_operator(struct ast_state *state, operator_ty); @@ -899,6 +937,12 @@ static const char * const withitem_fields[]={ "context_expr", "optional_vars", }; +static PyObject* ast2obj_match_case(struct ast_state *state, void*); +static const char * const match_case_fields[]={ + "pattern", + "guard", + "body", +}; static PyObject* ast2obj_type_ignore(struct ast_state *state, void*); static const char * const TypeIgnore_fields[]={ "lineno", @@ -1089,9 +1133,10 @@ make_type(struct ast_state *state, const char *type, PyObject* base, } PyTuple_SET_ITEM(fnames, i, field); } - result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){OOOOOs}", + result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){OOOOOOOs}", type, base, state->_fields, fnames, + state->__match_args__, fnames, state->__module__, state->ast, state->__doc__, doc); @@ -1222,6 +1267,7 @@ static int add_ast_fields(struct ast_state *state) empty_tuple = PyTuple_New(0); if (!empty_tuple || PyObject_SetAttrString(state->AST_type, "_fields", empty_tuple) < 0 || + PyObject_SetAttrString(state->AST_type, "__match_args__", empty_tuple) < 0 || PyObject_SetAttrString(state->AST_type, "_attributes", empty_tuple) < 0) { Py_XDECREF(empty_tuple); return -1; @@ -1291,6 +1337,7 @@ init_types(struct ast_state *state) " | If(expr test, stmt* body, stmt* orelse)\n" " | With(withitem* items, stmt* body, string? type_comment)\n" " | AsyncWith(withitem* items, stmt* body, string? type_comment)\n" + " | Match(expr subject, match_case* cases)\n" " | Raise(expr? exc, expr? cause)\n" " | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)\n" " | Assert(expr test, expr? msg)\n" @@ -1393,6 +1440,10 @@ init_types(struct ast_state *state) if (PyObject_SetAttr(state->AsyncWith_type, state->type_comment, Py_None) == -1) return 0; + state->Match_type = make_type(state, "Match", state->stmt_type, + Match_fields, 2, + "Match(expr subject, match_case* cases)"); + if (!state->Match_type) return 0; state->Raise_type = make_type(state, "Raise", state->stmt_type, Raise_fields, 2, "Raise(expr? exc, expr? cause)"); @@ -1471,7 +1522,9 @@ init_types(struct ast_state *state) " | Name(identifier id, expr_context ctx)\n" " | List(expr* elts, expr_context ctx)\n" " | Tuple(expr* elts, expr_context ctx)\n" - " | Slice(expr? lower, expr? upper, expr? step)"); + " | Slice(expr? lower, expr? upper, expr? step)\n" + " | MatchAs(expr pattern, identifier name)\n" + " | MatchOr(expr* patterns)"); if (!state->expr_type) return 0; if (!add_attributes(state, state->expr_type, expr_attributes, 4)) return 0; if (PyObject_SetAttr(state->expr_type, state->end_lineno, Py_None) == -1) @@ -1604,6 +1657,14 @@ init_types(struct ast_state *state) return 0; if (PyObject_SetAttr(state->Slice_type, state->step, Py_None) == -1) return 0; + state->MatchAs_type = make_type(state, "MatchAs", state->expr_type, + MatchAs_fields, 2, + "MatchAs(expr pattern, identifier name)"); + if (!state->MatchAs_type) return 0; + state->MatchOr_type = make_type(state, "MatchOr", state->expr_type, + MatchOr_fields, 1, + "MatchOr(expr* patterns)"); + if (!state->MatchOr_type) return 0; state->expr_context_type = make_type(state, "expr_context", state->AST_type, NULL, 0, "expr_context = Load | Store | Del"); @@ -1910,6 +1971,13 @@ init_types(struct ast_state *state) if (PyObject_SetAttr(state->withitem_type, state->optional_vars, Py_None) == -1) return 0; + state->match_case_type = make_type(state, "match_case", state->AST_type, + match_case_fields, 3, + "match_case(expr pattern, expr? guard, stmt* body)"); + if (!state->match_case_type) return 0; + if (!add_attributes(state, state->match_case_type, NULL, 0)) return 0; + if (PyObject_SetAttr(state->match_case_type, state->guard, Py_None) == -1) + return 0; state->type_ignore_type = make_type(state, "type_ignore", state->AST_type, NULL, 0, "type_ignore = TypeIgnore(int lineno, string tag)"); @@ -1955,6 +2023,8 @@ static int obj2ast_alias(struct ast_state *state, PyObject* obj, alias_ty* out, PyArena* arena); static int obj2ast_withitem(struct ast_state *state, PyObject* obj, withitem_ty* out, PyArena* arena); +static int obj2ast_match_case(struct ast_state *state, PyObject* obj, + match_case_ty* out, PyArena* arena); static int obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* out, PyArena* arena); @@ -2389,6 +2459,29 @@ AsyncWith(asdl_withitem_seq * items, asdl_stmt_seq * body, string type_comment, } stmt_ty +Match(expr_ty subject, asdl_match_case_seq * cases, int lineno, int col_offset, + int end_lineno, int end_col_offset, PyArena *arena) +{ + stmt_ty p; + if (!subject) { + PyErr_SetString(PyExc_ValueError, + "field 'subject' is required for Match"); + return NULL; + } + p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = Match_kind; + p->v.Match.subject = subject; + p->v.Match.cases = cases; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + +stmt_ty Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena) { @@ -3263,6 +3356,51 @@ Slice(expr_ty lower, expr_ty upper, expr_ty step, int lineno, int col_offset, return p; } +expr_ty +MatchAs(expr_ty pattern, identifier name, int lineno, int col_offset, int + end_lineno, int end_col_offset, PyArena *arena) +{ + expr_ty p; + if (!pattern) { + PyErr_SetString(PyExc_ValueError, + "field 'pattern' is required for MatchAs"); + return NULL; + } + if (!name) { + PyErr_SetString(PyExc_ValueError, + "field 'name' is required for MatchAs"); + return NULL; + } + p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = MatchAs_kind; + p->v.MatchAs.pattern = pattern; + p->v.MatchAs.name = name; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + +expr_ty +MatchOr(asdl_expr_seq * patterns, int lineno, int col_offset, int end_lineno, + int end_col_offset, PyArena *arena) +{ + expr_ty p; + p = (expr_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = MatchOr_kind; + p->v.MatchOr.patterns = patterns; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + comprehension_ty comprehension(expr_ty target, expr_ty iter, asdl_expr_seq * ifs, int is_async, PyArena *arena) @@ -3406,6 +3544,24 @@ withitem(expr_ty context_expr, expr_ty optional_vars, PyArena *arena) return p; } +match_case_ty +match_case(expr_ty pattern, expr_ty guard, asdl_stmt_seq * body, PyArena *arena) +{ + match_case_ty p; + if (!pattern) { + PyErr_SetString(PyExc_ValueError, + "field 'pattern' is required for match_case"); + return NULL; + } + p = (match_case_ty)PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->pattern = pattern; + p->guard = guard; + p->body = body; + return p; +} + type_ignore_ty TypeIgnore(int lineno, string tag, PyArena *arena) { @@ -3847,6 +4003,22 @@ ast2obj_stmt(struct ast_state *state, void* _o) goto failed; Py_DECREF(value); break; + case Match_kind: + tp = (PyTypeObject *)state->Match_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(state, o->v.Match.subject); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->subject, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(state, (asdl_seq*)o->v.Match.cases, + ast2obj_match_case); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->cases, value) == -1) + goto failed; + Py_DECREF(value); + break; case Raise_kind: tp = (PyTypeObject *)state->Raise_type; result = PyType_GenericNew(tp, NULL, NULL); @@ -4460,6 +4632,32 @@ ast2obj_expr(struct ast_state *state, void* _o) goto failed; Py_DECREF(value); break; + case MatchAs_kind: + tp = (PyTypeObject *)state->MatchAs_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(state, o->v.MatchAs.pattern); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->pattern, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_identifier(state, o->v.MatchAs.name); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->name, value) == -1) + goto failed; + Py_DECREF(value); + break; + case MatchOr_kind: + tp = (PyTypeObject *)state->MatchOr_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_list(state, (asdl_seq*)o->v.MatchOr.patterns, + ast2obj_expr); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->patterns, value) == -1) + goto failed; + Py_DECREF(value); + break; } value = ast2obj_int(state, o->lineno); if (!value) goto failed; @@ -4928,6 +5126,40 @@ failed: } PyObject* +ast2obj_match_case(struct ast_state *state, void* _o) +{ + match_case_ty o = (match_case_ty)_o; + PyObject *result = NULL, *value = NULL; + PyTypeObject *tp; + if (!o) { + Py_RETURN_NONE; + } + tp = (PyTypeObject *)state->match_case_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) return NULL; + value = ast2obj_expr(state, o->pattern); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->pattern, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(state, o->guard); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->guard, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_list(state, (asdl_seq*)o->body, ast2obj_stmt); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->body, value) == -1) + goto failed; + Py_DECREF(value); + return result; +failed: + Py_XDECREF(value); + Py_XDECREF(result); + return NULL; +} + +PyObject* ast2obj_type_ignore(struct ast_state *state, void* _o) { type_ignore_ty o = (type_ignore_ty)_o; @@ -6581,6 +6813,66 @@ obj2ast_stmt(struct ast_state *state, PyObject* obj, stmt_ty* out, PyArena* if (*out == NULL) goto failed; return 0; } + tp = state->Match_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + expr_ty subject; + asdl_match_case_seq* cases; + + if (_PyObject_LookupAttr(obj, state->subject, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"subject\" missing from Match"); + return 1; + } + else { + int res; + res = obj2ast_expr(state, tmp, &subject, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->cases, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"cases\" missing from Match"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "Match field \"cases\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + cases = _Py_asdl_match_case_seq_new(len, arena); + if (cases == NULL) goto failed; + for (i = 0; i < len; i++) { + match_case_ty val; + PyObject *tmp2 = PyList_GET_ITEM(tmp, i); + Py_INCREF(tmp2); + res = obj2ast_match_case(state, tmp2, &val, arena); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "Match field \"cases\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(cases, i, val); + } + Py_CLEAR(tmp); + } + *out = Match(subject, cases, lineno, col_offset, end_lineno, + end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } tp = state->Raise_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -8591,6 +8883,92 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (*out == NULL) goto failed; return 0; } + tp = state->MatchAs_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + expr_ty pattern; + identifier name; + + if (_PyObject_LookupAttr(obj, state->pattern, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"pattern\" missing from MatchAs"); + return 1; + } + else { + int res; + res = obj2ast_expr(state, tmp, &pattern, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->name, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from MatchAs"); + return 1; + } + else { + int res; + res = obj2ast_identifier(state, tmp, &name, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + *out = MatchAs(pattern, name, lineno, col_offset, end_lineno, + end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } + tp = state->MatchOr_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return 1; + } + if (isinstance) { + asdl_expr_seq* patterns; + + if (_PyObject_LookupAttr(obj, state->patterns, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"patterns\" missing from MatchOr"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "MatchOr field \"patterns\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + patterns = _Py_asdl_expr_seq_new(len, arena); + if (patterns == NULL) goto failed; + for (i = 0; i < len; i++) { + expr_ty val; + PyObject *tmp2 = PyList_GET_ITEM(tmp, i); + Py_INCREF(tmp2); + res = obj2ast_expr(state, tmp2, &val, arena); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "MatchOr field \"patterns\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(patterns, i, val); + } + Py_CLEAR(tmp); + } + *out = MatchOr(patterns, lineno, col_offset, end_lineno, + end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } PyErr_Format(PyExc_TypeError, "expected some sort of expr, but got %R", obj); failed: @@ -9652,6 +10030,81 @@ failed: } int +obj2ast_match_case(struct ast_state *state, PyObject* obj, match_case_ty* out, + PyArena* arena) +{ + PyObject* tmp = NULL; + expr_ty pattern; + expr_ty guard; + asdl_stmt_seq* body; + + if (_PyObject_LookupAttr(obj, state->pattern, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"pattern\" missing from match_case"); + return 1; + } + else { + int res; + res = obj2ast_expr(state, tmp, &pattern, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->guard, &tmp) < 0) { + return 1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + guard = NULL; + } + else { + int res; + res = obj2ast_expr(state, tmp, &guard, arena); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (_PyObject_LookupAttr(obj, state->body, &tmp) < 0) { + return 1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from match_case"); + return 1; + } + else { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "match_case field \"body\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + body = _Py_asdl_stmt_seq_new(len, arena); + if (body == NULL) goto failed; + for (i = 0; i < len; i++) { + stmt_ty val; + PyObject *tmp2 = PyList_GET_ITEM(tmp, i); + Py_INCREF(tmp2); + res = obj2ast_stmt(state, tmp2, &val, arena); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "match_case field \"body\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(body, i, val); + } + Py_CLEAR(tmp); + } + *out = match_case(pattern, guard, body, arena); + return 0; +failed: + Py_XDECREF(tmp); + return 1; +} + +int obj2ast_type_ignore(struct ast_state *state, PyObject* obj, type_ignore_ty* out, PyArena* arena) { @@ -9792,6 +10245,9 @@ astmodule_exec(PyObject *m) if (PyModule_AddObjectRef(m, "AsyncWith", state->AsyncWith_type) < 0) { return -1; } + if (PyModule_AddObjectRef(m, "Match", state->Match_type) < 0) { + return -1; + } if (PyModule_AddObjectRef(m, "Raise", state->Raise_type) < 0) { return -1; } @@ -9911,6 +10367,12 @@ astmodule_exec(PyObject *m) if (PyModule_AddObjectRef(m, "Slice", state->Slice_type) < 0) { return -1; } + if (PyModule_AddObjectRef(m, "MatchAs", state->MatchAs_type) < 0) { + return -1; + } + if (PyModule_AddObjectRef(m, "MatchOr", state->MatchOr_type) < 0) { + return -1; + } if (PyModule_AddObjectRef(m, "expr_context", state->expr_context_type) < 0) { return -1; @@ -10050,6 +10512,9 @@ astmodule_exec(PyObject *m) if (PyModule_AddObjectRef(m, "withitem", state->withitem_type) < 0) { return -1; } + if (PyModule_AddObjectRef(m, "match_case", state->match_case_type) < 0) { + return -1; + } if (PyModule_AddObjectRef(m, "type_ignore", state->type_ignore_type) < 0) { return -1; } diff --git a/Python/ast.c b/Python/ast.c index 5e74f65..c58b4a6 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -309,6 +309,14 @@ validate_expr(expr_ty exp, expr_context_ty ctx) return validate_exprs(exp->v.Tuple.elts, ctx, 0); case NamedExpr_kind: return validate_expr(exp->v.NamedExpr.value, Load); + case MatchAs_kind: + PyErr_SetString(PyExc_ValueError, + "MatchAs is only valid in match_case patterns"); + return 0; + case MatchOr_kind: + PyErr_SetString(PyExc_ValueError, + "MatchOr is only valid in match_case patterns"); + return 0; /* This last case doesn't have any checking. */ case Name_kind: return 1; @@ -318,6 +326,13 @@ validate_expr(expr_ty exp, expr_context_ty ctx) } static int +validate_pattern(expr_ty p) +{ + // Coming soon (thanks Batuhan)! + return 1; +} + +static int _validate_nonempty_seq(asdl_seq *seq, const char *what, const char *owner) { if (asdl_seq_LEN(seq)) @@ -415,6 +430,20 @@ validate_stmt(stmt_ty stmt) return 0; } return validate_body(stmt->v.AsyncWith.body, "AsyncWith"); + case Match_kind: + if (!validate_expr(stmt->v.Match.subject, Load) + || !validate_nonempty_seq(stmt->v.Match.cases, "cases", "Match")) { + return 0; + } + for (i = 0; i < asdl_seq_LEN(stmt->v.Match.cases); i++) { + match_case_ty m = asdl_seq_GET(stmt->v.Match.cases, i); + if (!validate_pattern(m->pattern) + || (m->guard && !validate_expr(m->guard, Load)) + || !validate_body(m->body, "match_case")) { + return 0; + } + } + return 1; case Raise_kind: if (stmt->v.Raise.exc) { return validate_expr(stmt->v.Raise.exc, Load) && diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 8c958ca..6ad00dc 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -408,6 +408,9 @@ static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOp static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); +static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); +static int astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state); + #define CALL(FUNC, TYPE, ARG) \ if (!FUNC((ARG), ctx_, state)) \ return 0; @@ -590,6 +593,10 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) case Constant_kind: // Already a constant, nothing further to do break; + case MatchAs_kind: + case MatchOr_kind: + // These can't occur outside of patterns. + Py_UNREACHABLE(); // No default case, so the compiler will emit a warning if new expression // kinds are added without being handled here } @@ -709,6 +716,10 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) case Expr_kind: CALL(astfold_expr, expr_ty, node_->v.Expr.value); break; + case Match_kind: + CALL(astfold_expr, expr_ty, node_->v.Match.subject); + CALL_SEQ(astfold_match_case, match_case, node_->v.Match.cases); + break; // The following statements don't contain any subexpressions to be folded case Import_kind: case ImportFrom_kind: @@ -746,6 +757,125 @@ astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) return 1; } +static int +astfold_pattern_negative(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) +{ + assert(node_->kind == UnaryOp_kind); + assert(node_->v.UnaryOp.op == USub); + assert(node_->v.UnaryOp.operand->kind == Constant_kind); + PyObject *value = node_->v.UnaryOp.operand->v.Constant.value; + assert(PyComplex_CheckExact(value) || + PyFloat_CheckExact(value) || + PyLong_CheckExact(value)); + PyObject *negated = PyNumber_Negative(value); + if (negated == NULL) { + return 0; + } + assert(PyComplex_CheckExact(negated) || + PyFloat_CheckExact(negated) || + PyLong_CheckExact(negated)); + return make_const(node_, negated, ctx_); +} + +static int +astfold_pattern_complex(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) +{ + expr_ty left = node_->v.BinOp.left; + expr_ty right = node_->v.BinOp.right; + if (left->kind == UnaryOp_kind) { + CALL(astfold_pattern_negative, expr_ty, left); + } + assert(left->kind = Constant_kind); + assert(right->kind = Constant_kind); + // LHS must be real, RHS must be imaginary: + if (!(PyFloat_CheckExact(left->v.Constant.value) || + PyLong_CheckExact(left->v.Constant.value)) || + !PyComplex_CheckExact(right->v.Constant.value)) + { + // Not actually valid, but it's the compiler's job to complain: + return 1; + } + PyObject *new; + if (node_->v.BinOp.op == Add) { + new = PyNumber_Add(left->v.Constant.value, right->v.Constant.value); + } + else { + assert(node_->v.BinOp.op == Sub); + new = PyNumber_Subtract(left->v.Constant.value, right->v.Constant.value); + } + if (new == NULL) { + return 0; + } + assert(PyComplex_CheckExact(new)); + return make_const(node_, new, ctx_); +} + +static int +astfold_pattern_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) +{ + CALL(astfold_pattern, expr_ty, node_->value); + return 1; +} + +static int +astfold_pattern(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) +{ + // Don't blindly optimize the pattern as an expr; it plays by its own rules! + // Currently, this is only used to form complex/negative numeric constants. + switch (node_->kind) { + case Attribute_kind: + break; + case BinOp_kind: + CALL(astfold_pattern_complex, expr_ty, node_); + break; + case Call_kind: + CALL_SEQ(astfold_pattern, expr, node_->v.Call.args); + CALL_SEQ(astfold_pattern_keyword, keyword, node_->v.Call.keywords); + break; + case Constant_kind: + break; + case Dict_kind: + CALL_SEQ(astfold_pattern, expr, node_->v.Dict.keys); + CALL_SEQ(astfold_pattern, expr, node_->v.Dict.values); + break; + // Not actually valid, but it's the compiler's job to complain: + case JoinedStr_kind: + break; + case List_kind: + CALL_SEQ(astfold_pattern, expr, node_->v.List.elts); + break; + case MatchAs_kind: + CALL(astfold_pattern, expr_ty, node_->v.MatchAs.pattern); + break; + case MatchOr_kind: + CALL_SEQ(astfold_pattern, expr, node_->v.MatchOr.patterns); + break; + case Name_kind: + break; + case Starred_kind: + CALL(astfold_pattern, expr_ty, node_->v.Starred.value); + break; + case Tuple_kind: + CALL_SEQ(astfold_pattern, expr, node_->v.Tuple.elts); + break; + case UnaryOp_kind: + CALL(astfold_pattern_negative, expr_ty, node_); + break; + default: + Py_UNREACHABLE(); + } + return 1; +} + +static int +astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) +{ + CALL(astfold_pattern, expr_ty, node_->pattern); + CALL_OPT(astfold_expr, expr_ty, node_->guard); + CALL_SEQ(astfold_stmt, stmt, node_->body); + return 1; +} + #undef CALL #undef CALL_OPT #undef CALL_SEQ diff --git a/Python/ceval.c b/Python/ceval.c index e1a8f15..7862643 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -880,6 +880,230 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) return 0; } + +// PEP 634: Structural Pattern Matching + + +// Return a tuple of values corresponding to keys, with error checks for +// duplicate/missing keys. +static PyObject* +match_keys(PyThreadState *tstate, PyObject *map, PyObject *keys) +{ + assert(PyTuple_CheckExact(keys)); + Py_ssize_t nkeys = PyTuple_GET_SIZE(keys); + if (!nkeys) { + // No keys means no items. + return PyTuple_New(0); + } + PyObject *seen = NULL; + PyObject *dummy = NULL; + PyObject *values = NULL; + // We use the two argument form of map.get(key, default) for two reasons: + // - Atomically check for a key and get its value without error handling. + // - Don't cause key creation or resizing in dict subclasses like + // collections.defaultdict that define __missing__ (or similar). + _Py_IDENTIFIER(get); + PyObject *get = _PyObject_GetAttrId(map, &PyId_get); + if (get == NULL) { + goto fail; + } + seen = PySet_New(NULL); + if (seen == NULL) { + goto fail; + } + // dummy = object() + dummy = _PyObject_CallNoArg((PyObject *)&PyBaseObject_Type); + if (dummy == NULL) { + goto fail; + } + values = PyList_New(0); + if (values == NULL) { + goto fail; + } + for (Py_ssize_t i = 0; i < nkeys; i++) { + PyObject *key = PyTuple_GET_ITEM(keys, i); + if (PySet_Contains(seen, key) || PySet_Add(seen, key)) { + if (!_PyErr_Occurred(tstate)) { + // Seen it before! + _PyErr_Format(tstate, PyExc_ValueError, + "mapping pattern checks duplicate key (%R)", key); + } + goto fail; + } + PyObject *value = PyObject_CallFunctionObjArgs(get, key, dummy, NULL); + if (value == NULL) { + goto fail; + } + if (value == dummy) { + // key not in map! + Py_DECREF(value); + Py_DECREF(values); + // Return None: + Py_INCREF(Py_None); + values = Py_None; + goto done; + } + PyList_Append(values, value); + Py_DECREF(value); + } + Py_SETREF(values, PyList_AsTuple(values)); + // Success: +done: + Py_DECREF(get); + Py_DECREF(seen); + Py_DECREF(dummy); + return values; +fail: + Py_XDECREF(get); + Py_XDECREF(seen); + Py_XDECREF(dummy); + Py_XDECREF(values); + return NULL; +} + +// Extract a named attribute from the subject, with additional bookkeeping to +// raise TypeErrors for repeated lookups. On failure, return NULL (with no +// error set). Use _PyErr_Occurred(tstate) to disambiguate. +static PyObject* +match_class_attr(PyThreadState *tstate, PyObject *subject, PyObject *type, + PyObject *name, PyObject *seen) +{ + assert(PyUnicode_CheckExact(name)); + assert(PySet_CheckExact(seen)); + if (PySet_Contains(seen, name) || PySet_Add(seen, name)) { + if (!_PyErr_Occurred(tstate)) { + // Seen it before! + _PyErr_Format(tstate, PyExc_TypeError, + "%s() got multiple sub-patterns for attribute %R", + ((PyTypeObject*)type)->tp_name, name); + } + return NULL; + } + PyObject *attr = PyObject_GetAttr(subject, name); + if (attr == NULL && _PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { + _PyErr_Clear(tstate); + } + return attr; +} + +// On success (match), return a tuple of extracted attributes. On failure (no +// match), return NULL. Use _PyErr_Occurred(tstate) to disambiguate. +static PyObject* +match_class(PyThreadState *tstate, PyObject *subject, PyObject *type, + Py_ssize_t nargs, PyObject *kwargs) +{ + if (!PyType_Check(type)) { + const char *e = "called match pattern must be a type"; + _PyErr_Format(tstate, PyExc_TypeError, e); + return NULL; + } + assert(PyTuple_CheckExact(kwargs)); + // First, an isinstance check: + if (PyObject_IsInstance(subject, type) <= 0) { + return NULL; + } + // So far so good: + PyObject *seen = PySet_New(NULL); + if (seen == NULL) { + return NULL; + } + PyObject *attrs = PyList_New(0); + if (attrs == NULL) { + Py_DECREF(seen); + return NULL; + } + // NOTE: From this point on, goto fail on failure: + PyObject *match_args = NULL; + // First, the positional subpatterns: + if (nargs) { + int match_self = 0; + match_args = PyObject_GetAttrString(type, "__match_args__"); + if (match_args) { + if (PyList_CheckExact(match_args)) { + Py_SETREF(match_args, PyList_AsTuple(match_args)); + } + if (match_args == NULL) { + goto fail; + } + if (!PyTuple_CheckExact(match_args)) { + const char *e = "%s.__match_args__ must be a list or tuple " + "(got %s)"; + _PyErr_Format(tstate, PyExc_TypeError, e, + ((PyTypeObject *)type)->tp_name, + Py_TYPE(match_args)->tp_name); + goto fail; + } + } + else if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) { + _PyErr_Clear(tstate); + // _Py_TPFLAGS_MATCH_SELF is only acknowledged if the type does not + // define __match_args__. This is natural behavior for subclasses: + // it's as if __match_args__ is some "magic" value that is lost as + // soon as they redefine it. + match_args = PyTuple_New(0); + match_self = PyType_HasFeature((PyTypeObject*)type, + _Py_TPFLAGS_MATCH_SELF); + } + else { + goto fail; + } + assert(PyTuple_CheckExact(match_args)); + Py_ssize_t allowed = match_self ? 1 : PyTuple_GET_SIZE(match_args); + if (allowed < nargs) { + const char *plural = (allowed == 1) ? "" : "s"; + _PyErr_Format(tstate, PyExc_TypeError, + "%s() accepts %d positional sub-pattern%s (%d given)", + ((PyTypeObject*)type)->tp_name, + allowed, plural, nargs); + goto fail; + } + if (match_self) { + // Easy. Copy the subject itself, and move on to kwargs. + PyList_Append(attrs, subject); + } + else { + for (Py_ssize_t i = 0; i < nargs; i++) { + PyObject *name = PyTuple_GET_ITEM(match_args, i); + if (!PyUnicode_CheckExact(name)) { + _PyErr_Format(tstate, PyExc_TypeError, + "__match_args__ elements must be strings " + "(got %s)", Py_TYPE(name)->tp_name); + goto fail; + } + PyObject *attr = match_class_attr(tstate, subject, type, name, + seen); + if (attr == NULL) { + goto fail; + } + PyList_Append(attrs, attr); + Py_DECREF(attr); + } + } + Py_CLEAR(match_args); + } + // Finally, the keyword subpatterns: + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(kwargs); i++) { + PyObject *name = PyTuple_GET_ITEM(kwargs, i); + PyObject *attr = match_class_attr(tstate, subject, type, name, seen); + if (attr == NULL) { + goto fail; + } + PyList_Append(attrs, attr); + Py_DECREF(attr); + } + Py_SETREF(attrs, PyList_AsTuple(attrs)); + Py_DECREF(seen); + return attrs; +fail: + // We really don't care whether an error was raised or not... that's our + // caller's problem. All we know is that the match failed. + Py_XDECREF(match_args); + Py_DECREF(seen); + Py_DECREF(attrs); + return NULL; +} + + static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause); static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **); @@ -3618,6 +3842,164 @@ main_loop: #endif } + case TARGET(GET_LEN): { + // PUSH(len(TOS)) + Py_ssize_t len_i = PyObject_Length(TOP()); + if (len_i < 0) { + goto error; + } + PyObject *len_o = PyLong_FromSsize_t(len_i); + if (len_o == NULL) { + goto error; + } + PUSH(len_o); + DISPATCH(); + } + + case TARGET(MATCH_CLASS): { + // Pop TOS. On success, set TOS to True and TOS1 to a tuple of + // attributes. On failure, set TOS to False. + PyObject *names = POP(); + PyObject *type = TOP(); + PyObject *subject = SECOND(); + assert(PyTuple_CheckExact(names)); + PyObject *attrs = match_class(tstate, subject, type, oparg, names); + Py_DECREF(names); + if (attrs) { + // Success! + assert(PyTuple_CheckExact(attrs)); + Py_DECREF(subject); + SET_SECOND(attrs); + } + else if (_PyErr_Occurred(tstate)) { + goto error; + } + Py_DECREF(type); + SET_TOP(PyBool_FromLong(!!attrs)); + DISPATCH(); + } + + case TARGET(MATCH_MAPPING): { + // PUSH(isinstance(TOS, _collections_abc.Mapping)) + PyObject *subject = TOP(); + // Fast path for dicts: + if (PyDict_Check(subject)) { + Py_INCREF(Py_True); + PUSH(Py_True); + DISPATCH(); + } + // Lazily import _collections_abc.Mapping, and keep it handy on the + // PyInterpreterState struct (it gets cleaned up at exit): + PyInterpreterState *interp = PyInterpreterState_Get(); + if (interp->map_abc == NULL) { + PyObject *abc = PyImport_ImportModule("_collections_abc"); + if (abc == NULL) { + goto error; + } + interp->map_abc = PyObject_GetAttrString(abc, "Mapping"); + if (interp->map_abc == NULL) { + goto error; + } + } + int match = PyObject_IsInstance(subject, interp->map_abc); + if (match < 0) { + goto error; + } + PUSH(PyBool_FromLong(match)); + DISPATCH(); + } + + case TARGET(MATCH_SEQUENCE): { + // PUSH(not isinstance(TOS, (bytearray, bytes, str)) + // and isinstance(TOS, _collections_abc.Sequence)) + PyObject *subject = TOP(); + // Fast path for lists and tuples: + if (PyType_FastSubclass(Py_TYPE(subject), + Py_TPFLAGS_LIST_SUBCLASS | + Py_TPFLAGS_TUPLE_SUBCLASS)) + { + Py_INCREF(Py_True); + PUSH(Py_True); + DISPATCH(); + } + // Bail on some possible Sequences that we intentionally exclude: + if (PyType_FastSubclass(Py_TYPE(subject), + Py_TPFLAGS_BYTES_SUBCLASS | + Py_TPFLAGS_UNICODE_SUBCLASS) || + PyByteArray_Check(subject)) + { + Py_INCREF(Py_False); + PUSH(Py_False); + DISPATCH(); + } + // Lazily import _collections_abc.Sequence, and keep it handy on the + // PyInterpreterState struct (it gets cleaned up at exit): + PyInterpreterState *interp = PyInterpreterState_Get(); + if (interp->seq_abc == NULL) { + PyObject *abc = PyImport_ImportModule("_collections_abc"); + if (abc == NULL) { + goto error; + } + interp->seq_abc = PyObject_GetAttrString(abc, "Sequence"); + if (interp->seq_abc == NULL) { + goto error; + } + } + int match = PyObject_IsInstance(subject, interp->seq_abc); + if (match < 0) { + goto error; + } + PUSH(PyBool_FromLong(match)); + DISPATCH(); + } + + case TARGET(MATCH_KEYS): { + // On successful match for all keys, PUSH(values) and PUSH(True). + // Otherwise, PUSH(None) and PUSH(False). + PyObject *keys = TOP(); + PyObject *subject = SECOND(); + PyObject *values_or_none = match_keys(tstate, subject, keys); + if (values_or_none == NULL) { + goto error; + } + PUSH(values_or_none); + if (values_or_none == Py_None) { + Py_INCREF(Py_False); + PUSH(Py_False); + DISPATCH(); + } + assert(PyTuple_CheckExact(values_or_none)); + Py_INCREF(Py_True); + PUSH(Py_True); + DISPATCH(); + } + + case TARGET(COPY_DICT_WITHOUT_KEYS): { + // rest = dict(TOS1) + // for key in TOS: + // del rest[key] + // SET_TOP(rest) + PyObject *keys = TOP(); + PyObject *subject = SECOND(); + PyObject *rest = PyDict_New(); + if (rest == NULL || PyDict_Update(rest, subject)) { + Py_XDECREF(rest); + goto error; + } + // This may seem a bit inefficient, but keys is rarely big enough to + // actually impact runtime. + assert(PyTuple_CheckExact(keys)); + for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(keys); i++) { + if (PyDict_DelItem(rest, PyTuple_GET_ITEM(keys, i))) { + Py_DECREF(rest); + goto error; + } + } + Py_DECREF(keys); + SET_TOP(rest); + DISPATCH(); + } + case TARGET(GET_ITER): { /* before: [obj]; after [getiter(obj)] */ PyObject *iterable = TOP(); diff --git a/Python/compile.c b/Python/compile.c index 386c552..454005e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -202,6 +202,11 @@ struct compiler { PyArena *c_arena; /* pointer to memory allocation arena */ }; +typedef struct { + PyObject *stores; + int allow_irrefutable; +} pattern_context; + static int compiler_enter_scope(struct compiler *, identifier, int, void *, int); static void compiler_free(struct compiler *); static basicblock *compiler_new_block(struct compiler *); @@ -210,7 +215,7 @@ static int compiler_addop(struct compiler *, int); static int compiler_addop_i(struct compiler *, int, Py_ssize_t); static int compiler_addop_j(struct compiler *, int, basicblock *); static int compiler_addop_j_noline(struct compiler *, int, basicblock *); -static int compiler_error(struct compiler *, const char *); +static int compiler_error(struct compiler *, const char *, ...); static int compiler_warn(struct compiler *, const char *, ...); static int compiler_nameop(struct compiler *, identifier, expr_context_ty); @@ -248,6 +253,11 @@ static int compiler_async_comprehension_generator( int depth, expr_ty elt, expr_ty val, int type); +static int compiler_pattern(struct compiler *, expr_ty, pattern_context *); +static int compiler_match(struct compiler *, stmt_ty); +static int compiler_pattern_subpattern(struct compiler *, expr_ty, + pattern_context *); + static PyCodeObject *assemble(struct compiler *, int addNone); static PyObject *__doc__, *__annotations__; @@ -1150,6 +1160,16 @@ stack_effect(int opcode, int oparg, int jump) case DICT_MERGE: case DICT_UPDATE: return -1; + case COPY_DICT_WITHOUT_KEYS: + return 0; + case MATCH_CLASS: + return -1; + case GET_LEN: + case MATCH_MAPPING: + case MATCH_SEQUENCE: + return 1; + case MATCH_KEYS: + return 2; default: return PY_INVALID_STACK_EFFECT; } @@ -1580,6 +1600,11 @@ compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b) } \ } +#define RETURN_IF_FALSE(X) \ + if (!(X)) { \ + return 0; \ + } + /* Search if variable annotations are present statically in a block. */ static int @@ -3414,6 +3439,8 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) return compiler_while(c, s); case If_kind: return compiler_if(c, s); + case Match_kind: + return compiler_match(c, s); case Raise_kind: n = 0; if (s->v.Raise.exc) { @@ -3758,12 +3785,11 @@ starunpack_helper(struct compiler *c, asdl_expr_seq *elts, int pushed, } static int -assignment_helper(struct compiler *c, asdl_expr_seq *elts) +unpack_helper(struct compiler *c, asdl_expr_seq *elts) { Py_ssize_t n = asdl_seq_LEN(elts); - Py_ssize_t i; int seen_star = 0; - for (i = 0; i < n; i++) { + for (Py_ssize_t i = 0; i < n; i++) { expr_ty elt = asdl_seq_GET(elts, i); if (elt->kind == Starred_kind && !seen_star) { if ((i >= (1 << 8)) || @@ -3782,7 +3808,15 @@ assignment_helper(struct compiler *c, asdl_expr_seq *elts) if (!seen_star) { ADDOP_I(c, UNPACK_SEQUENCE, n); } - for (i = 0; i < n; i++) { + return 1; +} + +static int +assignment_helper(struct compiler *c, asdl_expr_seq *elts) +{ + Py_ssize_t n = asdl_seq_LEN(elts); + RETURN_IF_FALSE(unpack_helper(c, elts)); + for (Py_ssize_t i = 0; i < n; i++) { expr_ty elt = asdl_seq_GET(elts, i); VISIT(c, expr, elt->kind != Starred_kind ? elt : elt->v.Starred.value); } @@ -4132,13 +4166,8 @@ validate_keywords(struct compiler *c, asdl_keyword_seq *keywords) for (Py_ssize_t j = i + 1; j < nkeywords; j++) { keyword_ty other = ((keyword_ty)asdl_seq_GET(keywords, j)); if (other->arg && !PyUnicode_Compare(key->arg, other->arg)) { - PyObject *msg = PyUnicode_FromFormat("keyword argument repeated: %U", key->arg); - if (msg == NULL) { - return -1; - } c->u->u_col_offset = other->col_offset; - compiler_error(c, PyUnicode_AsUTF8(msg)); - Py_DECREF(msg); + compiler_error(c, "keyword argument repeated: %U", key->arg); return -1; } } @@ -5119,6 +5148,10 @@ compiler_visit_expr1(struct compiler *c, expr_ty e) return compiler_list(c, e); case Tuple_kind: return compiler_tuple(c, e); + case MatchAs_kind: + case MatchOr_kind: + // Can only occur in patterns, which are handled elsewhere. + Py_UNREACHABLE(); } return 1; } @@ -5305,28 +5338,34 @@ compiler_annassign(struct compiler *c, stmt_ty s) */ static int -compiler_error(struct compiler *c, const char *errstr) +compiler_error(struct compiler *c, const char *format, ...) { - PyObject *loc; - PyObject *u = NULL, *v = NULL; - - loc = PyErr_ProgramTextObject(c->c_filename, c->u->u_lineno); - if (!loc) { + va_list vargs; +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + PyObject *msg = PyUnicode_FromFormatV(format, vargs); + va_end(vargs); + if (msg == NULL) { + return 0; + } + PyObject *loc = PyErr_ProgramTextObject(c->c_filename, c->u->u_lineno); + if (loc == NULL) { Py_INCREF(Py_None); loc = Py_None; } - u = Py_BuildValue("(OiiO)", c->c_filename, c->u->u_lineno, - c->u->u_col_offset + 1, loc); - if (!u) - goto exit; - v = Py_BuildValue("(zO)", errstr, u); - if (!v) + PyObject *args = Py_BuildValue("O(OiiO)", msg, c->c_filename, + c->u->u_lineno, c->u->u_col_offset + 1, loc); + Py_DECREF(msg); + if (args == NULL) { goto exit; - PyErr_SetObject(PyExc_SyntaxError, v); + } + PyErr_SetObject(PyExc_SyntaxError, args); exit: Py_DECREF(loc); - Py_XDECREF(u); - Py_XDECREF(v); + Py_XDECREF(args); return 0; } @@ -5421,6 +5460,654 @@ compiler_slice(struct compiler *c, expr_ty s) return 1; } + +// PEP 634: Structural Pattern Matching + +// To keep things simple, all compiler_pattern_* routines follow the convention +// of replacing TOS (the subject for the given pattern) with either True (match) +// or False (no match). We do this even for irrefutable patterns; the idea is +// that it's much easier to smooth out any redundant pushing, popping, and +// jumping in the peephole optimizer than to detect or predict it here. + + +#define WILDCARD_CHECK(N) \ + ((N)->kind == Name_kind && \ + _PyUnicode_EqualToASCIIString((N)->v.Name.id, "_")) + + +static int +pattern_helper_store_name(struct compiler *c, identifier n, pattern_context *pc) +{ + assert(!_PyUnicode_EqualToASCIIString(n, "_")); + // Can't assign to the same name twice: + if (pc->stores == NULL) { + RETURN_IF_FALSE(pc->stores = PySet_New(NULL)); + } + else { + int duplicate = PySet_Contains(pc->stores, n); + if (duplicate < 0) { + return 0; + } + if (duplicate) { + const char *e = "multiple assignments to name %R in pattern"; + return compiler_error(c, e, n); + } + } + RETURN_IF_FALSE(!PySet_Add(pc->stores, n)); + RETURN_IF_FALSE(compiler_nameop(c, n, Store)); + return 1; +} + + +static int +pattern_helper_sequence_unpack(struct compiler *c, asdl_expr_seq *values, + Py_ssize_t star, pattern_context *pc) +{ + RETURN_IF_FALSE(unpack_helper(c, values)); + // We've now got a bunch of new subjects on the stack. If any of them fail + // to match, we need to pop everything else off, then finally push False. + // fails is an array of blocks that correspond to the necessary amount of + // popping for each element: + basicblock **fails; + Py_ssize_t size = asdl_seq_LEN(values); + fails = (basicblock **)PyObject_Malloc(sizeof(basicblock*) * size); + if (fails == NULL) { + PyErr_NoMemory(); + return 0; + } + // NOTE: Can't use our nice returning macros anymore: they'll leak memory! + // goto error on error. + for (Py_ssize_t i = 0; i < size; i++) { + fails[i] = compiler_new_block(c); + if (fails[i] == NULL) { + goto error; + } + } + for (Py_ssize_t i = 0; i < size; i++) { + expr_ty value = asdl_seq_GET(values, i); + if (i == star) { + assert(value->kind == Starred_kind); + value = value->v.Starred.value; + } + if (!compiler_pattern_subpattern(c, value, pc) || + !compiler_addop_j(c, POP_JUMP_IF_FALSE, fails[i]) || + compiler_next_block(c) == NULL) + { + goto error; + } + } + // Success! + basicblock *end = compiler_new_block(c); + if (end == NULL || + !compiler_addop_load_const(c, Py_True) || + !compiler_addop_j(c, JUMP_FORWARD, end)) + { + goto error; + } + // This is where we handle failed sub-patterns. For a sequence pattern like + // [a, b, c, d], this will look like: + // fails[0]: POP_TOP + // fails[1]: POP_TOP + // fails[2]: POP_TOP + // fails[3]: LOAD_CONST False + for (Py_ssize_t i = 0; i < size - 1; i++) { + compiler_use_next_block(c, fails[i]); + if (!compiler_addop(c, POP_TOP)) { + goto error; + } + } + compiler_use_next_block(c, fails[size - 1]); + if (!compiler_addop_load_const(c, Py_False)) { + goto error; + } + compiler_use_next_block(c, end); + PyObject_Free(fails); + return 1; +error: + PyObject_Free(fails); + return 0; +} + +// Like pattern_helper_sequence_unpack, but uses BINARY_SUBSCR instead of +// UNPACK_SEQUENCE / UNPACK_EX. This is more efficient for patterns with a +// starred wildcard like [first, *_] / [first, *_, last] / [*_, last] / etc. +static int +pattern_helper_sequence_subscr(struct compiler *c, asdl_expr_seq *values, + Py_ssize_t star, pattern_context *pc) +{ + basicblock *end, *fail_pop_1; + RETURN_IF_FALSE(end = compiler_new_block(c)); + RETURN_IF_FALSE(fail_pop_1 = compiler_new_block(c)); + Py_ssize_t size = asdl_seq_LEN(values); + for (Py_ssize_t i = 0; i < size; i++) { + expr_ty value = asdl_seq_GET(values, i); + if (WILDCARD_CHECK(value)) { + continue; + } + if (i == star) { + assert(value->kind == Starred_kind); + assert(WILDCARD_CHECK(value->v.Starred.value)); + continue; + } + ADDOP(c, DUP_TOP); + if (i < star) { + ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(i)); + } + else { + // The subject may not support negative indexing! Compute a + // nonnegative index: + ADDOP(c, GET_LEN); + ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(size - i)); + ADDOP(c, BINARY_SUBTRACT); + } + ADDOP(c, BINARY_SUBSCR); + RETURN_IF_FALSE(compiler_pattern_subpattern(c, value, pc)); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + } + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_True); + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, fail_pop_1); + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_False); + compiler_use_next_block(c, end); + return 1; +} + + +// Like compiler_pattern, but turn off checks for irrefutability. +static int +compiler_pattern_subpattern(struct compiler *c, expr_ty p, pattern_context *pc) +{ + int allow_irrefutable = pc->allow_irrefutable; + pc->allow_irrefutable = 1; + RETURN_IF_FALSE(compiler_pattern(c, p, pc)); + pc->allow_irrefutable = allow_irrefutable; + return 1; +} + + +static int +compiler_pattern_as(struct compiler *c, expr_ty p, pattern_context *pc) +{ + assert(p->kind == MatchAs_kind); + basicblock *end, *fail_pop_1; + RETURN_IF_FALSE(end = compiler_new_block(c)); + RETURN_IF_FALSE(fail_pop_1 = compiler_new_block(c)); + // Need to make a copy for (possibly) storing later: + ADDOP(c, DUP_TOP); + RETURN_IF_FALSE(compiler_pattern(c, p->v.MatchAs.pattern, pc)); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + RETURN_IF_FALSE(pattern_helper_store_name(c, p->v.MatchAs.name, pc)); + ADDOP_LOAD_CONST(c, Py_True); + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, fail_pop_1); + // Need to pop that unused copy from before: + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_False); + compiler_use_next_block(c, end); + return 1; +} + + +static int +compiler_pattern_capture(struct compiler *c, expr_ty p, pattern_context *pc) +{ + assert(p->kind == Name_kind); + assert(p->v.Name.ctx == Store); + assert(!WILDCARD_CHECK(p)); + if (!pc->allow_irrefutable) { + // Whoops, can't have a name capture here! + const char *e = "name capture %R makes remaining patterns unreachable"; + return compiler_error(c, e, p->v.Name.id); + } + RETURN_IF_FALSE(pattern_helper_store_name(c, p->v.Name.id, pc)); + ADDOP_LOAD_CONST(c, Py_True); + return 1; +} + + +static int +compiler_pattern_class(struct compiler *c, expr_ty p, pattern_context *pc) +{ + asdl_expr_seq *args = p->v.Call.args; + asdl_keyword_seq *kwargs = p->v.Call.keywords; + Py_ssize_t nargs = asdl_seq_LEN(args); + Py_ssize_t nkwargs = asdl_seq_LEN(kwargs); + if (INT_MAX < nargs || INT_MAX < nargs + nkwargs - 1) { + const char *e = "too many sub-patterns in class pattern %R"; + return compiler_error(c, e, p->v.Call.func); + } + RETURN_IF_FALSE(!validate_keywords(c, kwargs)); + basicblock *end, *fail_pop_1; + RETURN_IF_FALSE(end = compiler_new_block(c)); + RETURN_IF_FALSE(fail_pop_1 = compiler_new_block(c)); + VISIT(c, expr, p->v.Call.func); + PyObject *kwnames; + RETURN_IF_FALSE(kwnames = PyTuple_New(nkwargs)); + Py_ssize_t i; + for (i = 0; i < nkwargs; i++) { + PyObject *name = ((keyword_ty) asdl_seq_GET(kwargs, i))->arg; + Py_INCREF(name); + PyTuple_SET_ITEM(kwnames, i, name); + } + ADDOP_LOAD_CONST_NEW(c, kwnames); + ADDOP_I(c, MATCH_CLASS, nargs); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + // TOS is now a tuple of (nargs + nkwargs) attributes. + for (i = 0; i < nargs + nkwargs; i++) { + expr_ty arg; + if (i < nargs) { + // Positional: + arg = asdl_seq_GET(args, i); + } + else { + // Keyword: + arg = ((keyword_ty) asdl_seq_GET(kwargs, i - nargs))->value; + } + if (WILDCARD_CHECK(arg)) { + continue; + } + // Get the i-th attribute, and match it against the i-th pattern: + ADDOP(c, DUP_TOP); + ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(i)); + ADDOP(c, BINARY_SUBSCR); + RETURN_IF_FALSE(compiler_pattern_subpattern(c, arg, pc)); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + } + // Success! Pop the tuple of attributes: + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_True); + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, fail_pop_1); + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_False); + compiler_use_next_block(c, end); + return 1; +} + + +static int +compiler_pattern_literal(struct compiler *c, expr_ty p, pattern_context *pc) +{ + assert(p->kind == Constant_kind); + PyObject *v = p->v.Constant.value; + ADDOP_LOAD_CONST(c, v); + // Literal True, False, and None are compared by identity. All others use + // equality: + ADDOP_COMPARE(c, (v == Py_None || PyBool_Check(v)) ? Is : Eq); + return 1; +} + + +static int +compiler_pattern_mapping(struct compiler *c, expr_ty p, pattern_context *pc) +{ + basicblock *end, *fail_pop_1, *fail_pop_3; + RETURN_IF_FALSE(end = compiler_new_block(c)); + RETURN_IF_FALSE(fail_pop_1 = compiler_new_block(c)); + RETURN_IF_FALSE(fail_pop_3 = compiler_new_block(c)); + asdl_expr_seq *keys = p->v.Dict.keys; + asdl_expr_seq *values = p->v.Dict.values; + Py_ssize_t size = asdl_seq_LEN(values); + // A starred pattern will be a keyless value. It is guranteed to be last: + int star = size ? !asdl_seq_GET(keys, size - 1) : 0; + ADDOP(c, MATCH_MAPPING); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + if (!size) { + // If the pattern is just "{}", we're done! + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_True); + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, fail_pop_1); + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_False); + compiler_use_next_block(c, end); + return 1; + } + if (size - star) { + // If the pattern has any keys in it, perform a length check: + ADDOP(c, GET_LEN); + ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(size - star)); + ADDOP_COMPARE(c, GtE); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + } + if (INT_MAX < size - star - 1) { + return compiler_error(c, "too many sub-patterns in mapping pattern"); + } + // Collect all of the keys into a tuple for MATCH_KEYS and + // COPY_DICT_WITHOUT_KEYS. They can either be dotted names or literals: + for (Py_ssize_t i = 0; i < size - star; i++) { + expr_ty key = asdl_seq_GET(keys, i); + if (key == NULL) { + const char *e = "can't use starred name here " + "(consider moving to end)"; + return compiler_error(c, e); + } + VISIT(c, expr, key); + } + ADDOP_I(c, BUILD_TUPLE, size - star); + ADDOP(c, MATCH_KEYS); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_3); + NEXT_BLOCK(c); + // So far so good. There's now a tuple of values on the stack to match + // sub-patterns against: + for (Py_ssize_t i = 0; i < size - star; i++) { + expr_ty value = asdl_seq_GET(values, i); + if (WILDCARD_CHECK(value)) { + continue; + } + ADDOP(c, DUP_TOP); + ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(i)); + ADDOP(c, BINARY_SUBSCR); + RETURN_IF_FALSE(compiler_pattern_subpattern(c, value, pc)); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_3); + NEXT_BLOCK(c); + } + // If we get this far, it's a match! We're done with that tuple of values. + ADDOP(c, POP_TOP); + if (star) { + // If we had a starred name, bind a dict of remaining items to it: + ADDOP(c, COPY_DICT_WITHOUT_KEYS); + PyObject *id = asdl_seq_GET(values, size - 1)->v.Name.id; + RETURN_IF_FALSE(pattern_helper_store_name(c, id, pc)); + } + else { + // Otherwise, we don't care about this tuple of keys anymore: + ADDOP(c, POP_TOP); + } + // Pop the subject: + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_True); + ADDOP_JUMP(c, JUMP_FORWARD, end); + // The top two items are a tuple of values or None, followed by a tuple of + // keys. Pop them both: + compiler_use_next_block(c, fail_pop_3); + ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); + compiler_use_next_block(c, fail_pop_1); + // Pop the subject: + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_False); + compiler_use_next_block(c, end); + return 1; +} + + +static int +compiler_pattern_or(struct compiler *c, expr_ty p, pattern_context *pc) +{ + assert(p->kind == MatchOr_kind); + // control is the set of names bound by the first alternative. If all of the + // others bind the same names (they should), then this becomes pc->stores. + PyObject *control = NULL; + basicblock *end, *pass_pop_1; + RETURN_IF_FALSE(end = compiler_new_block(c)); + RETURN_IF_FALSE(pass_pop_1 = compiler_new_block(c)); + Py_ssize_t size = asdl_seq_LEN(p->v.MatchOr.patterns); + assert(size > 1); + // We're going to be messing with pc. Keep the original info handy: + PyObject *stores_init = pc->stores; + int allow_irrefutable = pc->allow_irrefutable; + for (Py_ssize_t i = 0; i < size; i++) { + // NOTE: Can't use our nice returning macros in here: they'll leak sets! + expr_ty alt = asdl_seq_GET(p->v.MatchOr.patterns, i); + pc->stores = PySet_New(stores_init); + // An irrefutable sub-pattern must be last, if it is allowed at all: + int is_last = i == size - 1; + pc->allow_irrefutable = allow_irrefutable && is_last; + SET_LOC(c, alt); + if (pc->stores == NULL || + // Only copy the subject if we're *not* on the last alternative: + (!is_last && !compiler_addop(c, DUP_TOP)) || + !compiler_pattern(c, alt, pc) || + // Only jump if we're *not* on the last alternative: + (!is_last && !compiler_addop_j(c, POP_JUMP_IF_TRUE, pass_pop_1)) || + !compiler_next_block(c)) + { + goto fail; + } + if (!i) { + // If this is the first alternative, save its stores as a "control" + // for the others (they can't bind a different set of names): + control = pc->stores; + continue; + } + if (PySet_GET_SIZE(pc->stores) || PySet_GET_SIZE(control)) { + // Otherwise, check to see if we differ from the control set: + PyObject *diff = PyNumber_InPlaceXor(pc->stores, control); + if (diff == NULL) { + goto fail; + } + if (PySet_GET_SIZE(diff)) { + // The names differ! Raise. + Py_DECREF(diff); + compiler_error(c, "alternative patterns bind different names"); + goto fail; + } + Py_DECREF(diff); + } + Py_DECREF(pc->stores); + } + Py_XDECREF(stores_init); + // Update pc->stores and restore pc->allow_irrefutable: + pc->stores = control; + pc->allow_irrefutable = allow_irrefutable; + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, pass_pop_1); + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_True); + compiler_use_next_block(c, end); + return 1; +fail: + Py_XDECREF(stores_init); + Py_XDECREF(control); + return 0; +} + + +static int +compiler_pattern_sequence(struct compiler *c, expr_ty p, pattern_context *pc) +{ + assert(p->kind == List_kind || p->kind == Tuple_kind); + asdl_expr_seq *values = (p->kind == Tuple_kind) ? p->v.Tuple.elts + : p->v.List.elts; + Py_ssize_t size = asdl_seq_LEN(values); + Py_ssize_t star = -1; + int only_wildcard = 1; + int star_wildcard = 0; + // Find a starred name, if it exists. There may be at most one: + for (Py_ssize_t i = 0; i < size; i++) { + expr_ty value = asdl_seq_GET(values, i); + if (value->kind == Starred_kind) { + value = value->v.Starred.value; + if (star >= 0) { + const char *e = "multiple starred names in sequence pattern"; + return compiler_error(c, e); + } + star_wildcard = WILDCARD_CHECK(value); + star = i; + } + only_wildcard &= WILDCARD_CHECK(value); + } + basicblock *end, *fail_pop_1; + RETURN_IF_FALSE(end = compiler_new_block(c)); + RETURN_IF_FALSE(fail_pop_1 = compiler_new_block(c)); + ADDOP(c, MATCH_SEQUENCE); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + if (star < 0) { + // No star: len(subject) == size + ADDOP(c, GET_LEN); + ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(size)); + ADDOP_COMPARE(c, Eq); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + } + else if (size > 1) { + // Star: len(subject) >= size - 1 + ADDOP(c, GET_LEN); + ADDOP_LOAD_CONST_NEW(c, PyLong_FromSsize_t(size - 1)); + ADDOP_COMPARE(c, GtE); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, fail_pop_1); + NEXT_BLOCK(c); + } + if (only_wildcard) { + // Patterns like: [] / [_] / [_, _] / [*_] / [_, *_] / [_, _, *_] / etc. + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_True); + } + else if (star_wildcard) { + RETURN_IF_FALSE(pattern_helper_sequence_subscr(c, values, star, pc)); + } + else { + RETURN_IF_FALSE(pattern_helper_sequence_unpack(c, values, star, pc)); + } + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, fail_pop_1); + ADDOP(c, POP_TOP) + ADDOP_LOAD_CONST(c, Py_False); + compiler_use_next_block(c, end); + return 1; +} + + +static int +compiler_pattern_value(struct compiler *c, expr_ty p, pattern_context *pc) +{ + assert(p->kind == Attribute_kind); + assert(p->v.Attribute.ctx == Load); + VISIT(c, expr, p); + ADDOP_COMPARE(c, Eq); + return 1; +} + + +static int +compiler_pattern_wildcard(struct compiler *c, expr_ty p, pattern_context *pc) +{ + assert(p->kind == Name_kind); + assert(p->v.Name.ctx == Store); + assert(WILDCARD_CHECK(p)); + if (!pc->allow_irrefutable) { + // Whoops, can't have a wildcard here! + const char *e = "wildcard makes remaining patterns unreachable"; + return compiler_error(c, e); + } + ADDOP(c, POP_TOP); + ADDOP_LOAD_CONST(c, Py_True); + return 1; +} + + +static int +compiler_pattern(struct compiler *c, expr_ty p, pattern_context *pc) +{ + SET_LOC(c, p); + switch (p->kind) { + case Attribute_kind: + return compiler_pattern_value(c, p, pc); + case BinOp_kind: + // Because we allow "2+2j", things like "2+2" make it this far: + return compiler_error(c, "patterns cannot include operators"); + case Call_kind: + return compiler_pattern_class(c, p, pc); + case Constant_kind: + return compiler_pattern_literal(c, p, pc); + case Dict_kind: + return compiler_pattern_mapping(c, p, pc); + case JoinedStr_kind: + // Because we allow strings, f-strings make it this far: + return compiler_error(c, "patterns cannot include f-strings"); + case List_kind: + case Tuple_kind: + return compiler_pattern_sequence(c, p, pc); + case MatchAs_kind: + return compiler_pattern_as(c, p, pc); + case MatchOr_kind: + return compiler_pattern_or(c, p, pc); + case Name_kind: + if (WILDCARD_CHECK(p)) { + return compiler_pattern_wildcard(c, p, pc); + } + return compiler_pattern_capture(c, p, pc); + default: + Py_UNREACHABLE(); + } +} + + +static int +compiler_match(struct compiler *c, stmt_ty s) +{ + VISIT(c, expr, s->v.Match.subject); + basicblock *next, *end; + RETURN_IF_FALSE(end = compiler_new_block(c)); + Py_ssize_t cases = asdl_seq_LEN(s->v.Match.cases); + assert(cases); + pattern_context pc; + // We use pc.stores to track: + // - Repeated name assignments in the same pattern. + // - Different name assignments in alternatives. + // It's a set of names, but we don't create it until it's needed: + pc.stores = NULL; + match_case_ty m = asdl_seq_GET(s->v.Match.cases, cases - 1); + int has_default = WILDCARD_CHECK(m->pattern) && 1 < cases; + for (Py_ssize_t i = 0; i < cases - has_default; i++) { + m = asdl_seq_GET(s->v.Match.cases, i); + SET_LOC(c, m->pattern); + RETURN_IF_FALSE(next = compiler_new_block(c)); + // If pc.allow_irrefutable is 0, any name captures against our subject + // will raise. Irrefutable cases must be either guarded, last, or both: + pc.allow_irrefutable = m->guard != NULL || i == cases - 1; + // Only copy the subject if we're *not* on the last case: + if (i != cases - has_default - 1) { + ADDOP(c, DUP_TOP); + } + int result = compiler_pattern(c, m->pattern, &pc); + Py_CLEAR(pc.stores); + RETURN_IF_FALSE(result); + ADDOP_JUMP(c, POP_JUMP_IF_FALSE, next); + NEXT_BLOCK(c); + if (m->guard) { + RETURN_IF_FALSE(compiler_jump_if(c, m->guard, next, 0)); + } + // Success! Pop the subject off, we're done with it: + if (i != cases - has_default - 1) { + ADDOP(c, POP_TOP); + } + VISIT_SEQ(c, stmt, m->body); + ADDOP_JUMP(c, JUMP_FORWARD, end); + compiler_use_next_block(c, next); + } + if (has_default) { + if (cases == 1) { + // No matches. Done with the subject: + ADDOP(c, POP_TOP); + } + // A trailing "case _" is common, and lets us save a bit of redundant + // pushing and popping in the loop above: + m = asdl_seq_GET(s->v.Match.cases, cases - 1); + SET_LOC(c, m->pattern); + if (m->guard) { + RETURN_IF_FALSE(compiler_jump_if(c, m->guard, end, 0)); + } + VISIT_SEQ(c, stmt, m->body); + } + compiler_use_next_block(c, end); + return 1; +} + + +#undef WILDCARD_CHECK + + /* End of the compiler section, beginning of the assembler section */ /* do depth-first search of basic block graph, starting with block. diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 32ed87d..6b4cd39 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -315,7 +315,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,115,38,0,0,0,16,5,6,1,22,1,4,255, 2,2,14,3,24,1,16,128,18,1,12,1,2,1,12,1, 2,3,12,254,2,1,2,1,2,254,2,253,255,128,114,84, - 0,0,0,105,105,13,0,0,114,45,0,0,0,114,33,0, + 0,0,0,105,106,13,0,0,114,45,0,0,0,114,33,0, 0,0,115,2,0,0,0,13,10,90,11,95,95,112,121,99, 97,99,104,101,95,95,122,4,111,112,116,45,122,3,46,112, 121,122,4,46,112,121,119,122,4,46,112,121,99,41,1,218, @@ -429,7 +429,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 90,15,97,108,109,111,115,116,95,102,105,108,101,110,97,109, 101,218,8,102,105,108,101,110,97,109,101,114,7,0,0,0, 114,7,0,0,0,114,8,0,0,0,218,17,99,97,99,104, - 101,95,102,114,111,109,95,115,111,117,114,99,101,85,1,0, + 101,95,102,114,111,109,95,115,111,117,114,99,101,86,1,0, 0,115,74,0,0,0,8,18,6,1,2,1,4,255,8,2, 4,1,8,1,12,1,10,1,12,1,16,1,8,1,8,1, 8,1,24,1,8,1,12,1,6,1,8,2,8,1,8,1, @@ -510,7 +510,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,90,9,111,112,116,95,108,101,118,101,108,90,13,98, 97,115,101,95,102,105,108,101,110,97,109,101,114,7,0,0, 0,114,7,0,0,0,114,8,0,0,0,218,17,115,111,117, - 114,99,101,95,102,114,111,109,95,99,97,99,104,101,156,1, + 114,99,101,95,102,114,111,109,95,99,97,99,104,101,157,1, 0,0,115,62,0,0,0,12,9,8,1,10,1,12,1,4, 1,10,1,12,1,14,1,16,1,4,1,4,1,12,1,8, 1,8,1,2,1,8,255,10,2,8,1,14,1,10,1,16, @@ -546,7 +546,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 120,116,101,110,115,105,111,110,218,11,115,111,117,114,99,101, 95,112,97,116,104,114,7,0,0,0,114,7,0,0,0,114, 8,0,0,0,218,15,95,103,101,116,95,115,111,117,114,99, - 101,102,105,108,101,196,1,0,0,115,24,0,0,0,12,7, + 101,102,105,108,101,197,1,0,0,115,24,0,0,0,12,7, 4,1,16,1,24,1,4,1,2,1,12,1,16,1,14,1, 16,1,2,254,255,128,114,120,0,0,0,99,1,0,0,0, 0,0,0,0,0,0,0,0,1,0,0,0,8,0,0,0, @@ -559,7 +559,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 112,108,101,114,113,0,0,0,114,109,0,0,0,114,95,0, 0,0,114,101,0,0,0,41,1,114,108,0,0,0,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,218,11,95, - 103,101,116,95,99,97,99,104,101,100,215,1,0,0,115,20, + 103,101,116,95,99,97,99,104,101,100,216,1,0,0,115,20, 0,0,0,14,1,2,1,10,1,12,1,6,1,14,1,4, 1,4,2,2,251,255,128,114,124,0,0,0,99,1,0,0, 0,0,0,0,0,0,0,0,0,2,0,0,0,8,0,0, @@ -574,7 +574,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,114,65,0,0,0,114,64,0,0,0,41,2,114, 58,0,0,0,114,66,0,0,0,114,7,0,0,0,114,7, 0,0,0,114,8,0,0,0,218,10,95,99,97,108,99,95, - 109,111,100,101,227,1,0,0,115,16,0,0,0,2,2,14, + 109,111,100,101,228,1,0,0,115,16,0,0,0,2,2,14, 1,12,1,6,1,8,3,4,1,2,251,255,128,114,126,0, 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,3, 0,0,0,4,0,0,0,3,0,0,0,115,52,0,0,0, @@ -611,7 +611,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 108,102,114,128,0,0,0,218,4,97,114,103,115,218,6,107, 119,97,114,103,115,169,1,218,6,109,101,116,104,111,100,114, 7,0,0,0,114,8,0,0,0,218,19,95,99,104,101,99, - 107,95,110,97,109,101,95,119,114,97,112,112,101,114,247,1, + 107,95,110,97,109,101,95,119,114,97,112,112,101,114,248,1, 0,0,115,20,0,0,0,8,1,8,1,10,1,4,1,8, 1,2,255,2,1,6,255,24,2,255,128,122,40,95,99,104, 101,99,107,95,110,97,109,101,46,60,108,111,99,97,108,115, @@ -630,14 +630,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 99,116,95,95,218,6,117,112,100,97,116,101,41,3,90,3, 110,101,119,90,3,111,108,100,114,82,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,218,5,95,119, - 114,97,112,4,2,0,0,115,12,0,0,0,8,1,10,1, + 114,97,112,5,2,0,0,115,12,0,0,0,8,1,10,1, 18,1,2,128,18,1,255,128,122,26,95,99,104,101,99,107, 95,110,97,109,101,46,60,108,111,99,97,108,115,62,46,95, 119,114,97,112,41,1,78,41,2,218,10,95,98,111,111,116, 115,116,114,97,112,114,145,0,0,0,41,3,114,134,0,0, 0,114,135,0,0,0,114,145,0,0,0,114,7,0,0,0, 114,133,0,0,0,114,8,0,0,0,218,11,95,99,104,101, - 99,107,95,110,97,109,101,239,1,0,0,115,14,0,0,0, + 99,107,95,110,97,109,101,240,1,0,0,115,14,0,0,0, 14,8,8,10,8,1,8,2,10,6,4,1,255,128,114,147, 0,0,0,99,2,0,0,0,0,0,0,0,0,0,0,0, 5,0,0,0,6,0,0,0,67,0,0,0,115,60,0,0, @@ -665,7 +665,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 97,109,101,218,6,108,111,97,100,101,114,218,8,112,111,114, 116,105,111,110,115,218,3,109,115,103,114,7,0,0,0,114, 7,0,0,0,114,8,0,0,0,218,17,95,102,105,110,100, - 95,109,111,100,117,108,101,95,115,104,105,109,14,2,0,0, + 95,109,111,100,117,108,101,95,115,104,105,109,15,2,0,0, 115,12,0,0,0,14,10,16,1,4,1,22,1,4,1,255, 128,114,154,0,0,0,99,3,0,0,0,0,0,0,0,0, 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, @@ -733,7 +733,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 115,90,5,109,97,103,105,99,114,105,0,0,0,114,17,0, 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, 0,218,13,95,99,108,97,115,115,105,102,121,95,112,121,99, - 31,2,0,0,115,30,0,0,0,12,16,8,1,16,1,12, + 32,2,0,0,115,30,0,0,0,12,16,8,1,16,1,12, 1,16,1,12,1,10,1,12,1,8,1,16,1,8,2,16, 1,16,1,4,1,255,128,114,163,0,0,0,99,5,0,0, 0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0, @@ -788,7 +788,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,114,162,0,0,0,114,105,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,218,23,95,118, 97,108,105,100,97,116,101,95,116,105,109,101,115,116,97,109, - 112,95,112,121,99,64,2,0,0,115,20,0,0,0,24,19, + 112,95,112,121,99,65,2,0,0,115,20,0,0,0,24,19, 10,1,12,1,16,1,8,1,22,1,2,255,22,2,8,254, 255,128,114,167,0,0,0,99,4,0,0,0,0,0,0,0, 0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,0, @@ -834,7 +834,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,218,11,115,111,117,114,99,101,95,104,97,115,104,114, 128,0,0,0,114,162,0,0,0,114,7,0,0,0,114,7, 0,0,0,114,8,0,0,0,218,18,95,118,97,108,105,100, - 97,116,101,95,104,97,115,104,95,112,121,99,92,2,0,0, + 97,116,101,95,104,97,115,104,95,112,121,99,93,2,0,0, 115,16,0,0,0,16,17,2,1,8,1,4,255,2,2,6, 254,4,255,255,128,114,169,0,0,0,99,4,0,0,0,0, 0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,67, @@ -858,7 +858,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,42,0,0,0,114,128,0,0,0,114,118,0,0,0,114, 119,0,0,0,218,4,99,111,100,101,114,7,0,0,0,114, 7,0,0,0,114,8,0,0,0,218,17,95,99,111,109,112, - 105,108,101,95,98,121,116,101,99,111,100,101,116,2,0,0, + 105,108,101,95,98,121,116,101,99,111,100,101,117,2,0,0, 115,20,0,0,0,10,2,10,1,12,1,8,1,12,1,4, 1,10,2,4,1,6,255,255,128,114,176,0,0,0,99,3, 0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5, @@ -877,7 +877,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,166,0,0,0,114,42,0,0,0,114,7,0,0,0,114, 7,0,0,0,114,8,0,0,0,218,22,95,99,111,100,101, 95,116,111,95,116,105,109,101,115,116,97,109,112,95,112,121, - 99,129,2,0,0,115,14,0,0,0,8,2,14,1,14,1, + 99,130,2,0,0,115,14,0,0,0,8,2,14,1,14,1, 14,1,16,1,4,1,255,128,114,181,0,0,0,84,99,3, 0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5, 0,0,0,67,0,0,0,115,80,0,0,0,116,0,116,1, @@ -895,7 +895,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,90,7,99,104,101,99,107,101,100,114,42,0,0,0, 114,17,0,0,0,114,7,0,0,0,114,7,0,0,0,114, 8,0,0,0,218,17,95,99,111,100,101,95,116,111,95,104, - 97,115,104,95,112,121,99,139,2,0,0,115,16,0,0,0, + 97,115,104,95,112,121,99,140,2,0,0,115,16,0,0,0, 8,2,12,1,14,1,16,1,10,1,16,1,4,1,255,128, 114,182,0,0,0,99,1,0,0,0,0,0,0,0,0,0, 0,0,5,0,0,0,6,0,0,0,67,0,0,0,115,62, @@ -923,7 +923,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 105,110,103,90,15,110,101,119,108,105,110,101,95,100,101,99, 111,100,101,114,114,7,0,0,0,114,7,0,0,0,114,8, 0,0,0,218,13,100,101,99,111,100,101,95,115,111,117,114, - 99,101,150,2,0,0,115,12,0,0,0,8,5,12,1,10, + 99,101,151,2,0,0,115,12,0,0,0,8,5,12,1,10, 1,12,1,20,1,255,128,114,187,0,0,0,169,2,114,151, 0,0,0,218,26,115,117,98,109,111,100,117,108,101,95,115, 101,97,114,99,104,95,108,111,99,97,116,105,111,110,115,99, @@ -984,7 +984,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 8,115,117,102,102,105,120,101,115,114,193,0,0,0,90,7, 100,105,114,110,97,109,101,114,7,0,0,0,114,7,0,0, 0,114,8,0,0,0,218,23,115,112,101,99,95,102,114,111, - 109,95,102,105,108,101,95,108,111,99,97,116,105,111,110,167, + 109,95,102,105,108,101,95,108,111,99,97,116,105,111,110,168, 2,0,0,115,74,0,0,0,8,12,4,4,10,1,2,2, 14,1,14,1,4,1,2,251,10,7,16,8,6,1,8,3, 14,1,14,1,10,1,6,1,4,1,2,253,4,5,8,3, @@ -1023,7 +1023,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 72,75,69,89,95,76,79,67,65,76,95,77,65,67,72,73, 78,69,114,20,0,0,0,114,7,0,0,0,114,7,0,0, 0,114,8,0,0,0,218,14,95,111,112,101,110,95,114,101, - 103,105,115,116,114,121,247,2,0,0,115,12,0,0,0,2, + 103,105,115,116,114,121,248,2,0,0,115,12,0,0,0,2, 2,16,1,12,1,18,1,2,255,255,128,122,36,87,105,110, 100,111,119,115,82,101,103,105,115,116,114,121,70,105,110,100, 101,114,46,95,111,112,101,110,95,114,101,103,105,115,116,114, @@ -1050,7 +1050,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 116,114,121,95,107,101,121,114,21,0,0,0,90,4,104,107, 101,121,218,8,102,105,108,101,112,97,116,104,114,7,0,0, 0,114,7,0,0,0,114,8,0,0,0,218,16,95,115,101, - 97,114,99,104,95,114,101,103,105,115,116,114,121,254,2,0, + 97,114,99,104,95,114,101,103,105,115,116,114,121,255,2,0, 0,115,30,0,0,0,6,2,8,1,6,2,6,1,16,1, 6,255,2,2,12,1,26,1,18,128,4,3,12,254,6,1, 2,255,255,128,122,38,87,105,110,100,111,119,115,82,101,103, @@ -1073,7 +1073,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,218,6,116,97,114,103,101,116,114,210,0,0,0, 114,151,0,0,0,114,200,0,0,0,114,198,0,0,0,114, 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,9, - 102,105,110,100,95,115,112,101,99,13,3,0,0,115,36,0, + 102,105,110,100,95,115,112,101,99,14,3,0,0,115,36,0, 0,0,10,2,8,1,4,1,2,1,12,1,12,1,6,1, 14,1,14,1,6,1,8,1,2,1,6,254,8,3,2,252, 4,255,2,254,255,128,122,31,87,105,110,100,111,119,115,82, @@ -1093,7 +1093,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 169,4,114,209,0,0,0,114,150,0,0,0,114,58,0,0, 0,114,198,0,0,0,114,7,0,0,0,114,7,0,0,0, 114,8,0,0,0,218,11,102,105,110,100,95,109,111,100,117, - 108,101,29,3,0,0,115,10,0,0,0,12,7,8,1,6, + 108,101,30,3,0,0,115,10,0,0,0,12,7,8,1,6, 1,4,2,255,128,122,33,87,105,110,100,111,119,115,82,101, 103,105,115,116,114,121,70,105,110,100,101,114,46,102,105,110, 100,95,109,111,100,117,108,101,41,2,78,78,41,1,78,41, @@ -1105,7 +1105,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 104,111,100,114,204,0,0,0,218,11,99,108,97,115,115,109, 101,116,104,111,100,114,211,0,0,0,114,214,0,0,0,114, 217,0,0,0,114,7,0,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,114,202,0,0,0,235,2,0, + 0,0,0,114,8,0,0,0,114,202,0,0,0,236,2,0, 0,115,32,0,0,0,8,0,4,2,2,3,2,255,2,4, 2,255,12,3,2,2,10,1,2,6,10,1,2,14,12,1, 2,15,16,1,255,128,114,202,0,0,0,99,0,0,0,0, @@ -1142,7 +1142,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 108,0,0,0,90,13,102,105,108,101,110,97,109,101,95,98, 97,115,101,90,9,116,97,105,108,95,110,97,109,101,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,114,193,0, - 0,0,48,3,0,0,115,10,0,0,0,18,3,16,1,14, + 0,0,49,3,0,0,115,10,0,0,0,18,3,16,1,14, 1,16,1,255,128,122,24,95,76,111,97,100,101,114,66,97, 115,105,99,115,46,105,115,95,112,97,99,107,97,103,101,99, 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, @@ -1152,7 +1152,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,32,99,114,101,97,116,105,111,110,46,78,114,7,0,0, 0,169,2,114,130,0,0,0,114,198,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,218,13,99,114, - 101,97,116,101,95,109,111,100,117,108,101,56,3,0,0,243, + 101,97,116,101,95,109,111,100,117,108,101,57,3,0,0,243, 4,0,0,0,4,0,255,128,122,27,95,76,111,97,100,101, 114,66,97,115,105,99,115,46,99,114,101,97,116,101,95,109, 111,100,117,108,101,99,2,0,0,0,0,0,0,0,0,0, @@ -1172,7 +1172,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 111,118,101,100,218,4,101,120,101,99,114,143,0,0,0,41, 3,114,130,0,0,0,218,6,109,111,100,117,108,101,114,175, 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,218,11,101,120,101,99,95,109,111,100,117,108,101,59, + 0,0,218,11,101,120,101,99,95,109,111,100,117,108,101,60, 3,0,0,115,14,0,0,0,12,2,8,1,6,1,4,1, 6,255,20,2,255,128,122,25,95,76,111,97,100,101,114,66, 97,115,105,99,115,46,101,120,101,99,95,109,111,100,117,108, @@ -1184,14 +1184,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,218,17,95,108,111,97,100,95,109,111,100,117,108,101,95, 115,104,105,109,169,2,114,130,0,0,0,114,150,0,0,0, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, - 11,108,111,97,100,95,109,111,100,117,108,101,67,3,0,0, + 11,108,111,97,100,95,109,111,100,117,108,101,68,3,0,0, 115,4,0,0,0,12,3,255,128,122,25,95,76,111,97,100, 101,114,66,97,115,105,99,115,46,108,111,97,100,95,109,111, 100,117,108,101,78,41,8,114,137,0,0,0,114,136,0,0, 0,114,138,0,0,0,114,139,0,0,0,114,193,0,0,0, 114,226,0,0,0,114,232,0,0,0,114,235,0,0,0,114, 7,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,222,0,0,0,43,3,0,0,115,14,0,0, + 0,0,0,114,222,0,0,0,44,3,0,0,115,14,0,0, 0,8,0,4,2,8,3,8,8,8,3,12,8,255,128,114, 222,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,3,0,0,0,64,0,0,0,115,74,0, @@ -1216,7 +1216,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 32,32,32,32,32,32,32,78,41,1,114,64,0,0,0,169, 2,114,130,0,0,0,114,58,0,0,0,114,7,0,0,0, 114,7,0,0,0,114,8,0,0,0,218,10,112,97,116,104, - 95,109,116,105,109,101,75,3,0,0,115,4,0,0,0,4, + 95,109,116,105,109,101,76,3,0,0,115,4,0,0,0,4, 6,255,128,122,23,83,111,117,114,99,101,76,111,97,100,101, 114,46,112,97,116,104,95,109,116,105,109,101,99,2,0,0, 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, @@ -1250,7 +1250,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 108,101,100,46,10,32,32,32,32,32,32,32,32,114,180,0, 0,0,78,41,1,114,238,0,0,0,114,237,0,0,0,114, 7,0,0,0,114,7,0,0,0,114,8,0,0,0,218,10, - 112,97,116,104,95,115,116,97,116,115,83,3,0,0,115,4, + 112,97,116,104,95,115,116,97,116,115,84,3,0,0,115,4, 0,0,0,14,12,255,128,122,23,83,111,117,114,99,101,76, 111,97,100,101,114,46,112,97,116,104,95,115,116,97,116,115, 99,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0, @@ -1274,7 +1274,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 4,114,130,0,0,0,114,119,0,0,0,90,10,99,97,99, 104,101,95,112,97,116,104,114,42,0,0,0,114,7,0,0, 0,114,7,0,0,0,114,8,0,0,0,218,15,95,99,97, - 99,104,101,95,98,121,116,101,99,111,100,101,97,3,0,0, + 99,104,101,95,98,121,116,101,99,111,100,101,98,3,0,0, 115,4,0,0,0,12,8,255,128,122,28,83,111,117,114,99, 101,76,111,97,100,101,114,46,95,99,97,99,104,101,95,98, 121,116,101,99,111,100,101,99,3,0,0,0,0,0,0,0, @@ -1291,7 +1291,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 102,105,108,101,115,46,10,32,32,32,32,32,32,32,32,78, 114,7,0,0,0,41,3,114,130,0,0,0,114,58,0,0, 0,114,42,0,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,114,240,0,0,0,107,3,0,0,114,227, + 114,8,0,0,0,114,240,0,0,0,108,3,0,0,114,227, 0,0,0,122,21,83,111,117,114,99,101,76,111,97,100,101, 114,46,115,101,116,95,100,97,116,97,99,2,0,0,0,0, 0,0,0,0,0,0,0,5,0,0,0,10,0,0,0,67, @@ -1311,7 +1311,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,187,0,0,0,41,5,114,130,0,0,0,114,150,0,0, 0,114,58,0,0,0,114,185,0,0,0,218,3,101,120,99, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, - 10,103,101,116,95,115,111,117,114,99,101,114,3,0,0,115, + 10,103,101,116,95,115,111,117,114,99,101,115,3,0,0,115, 26,0,0,0,10,2,2,1,12,1,8,4,14,253,4,1, 2,1,4,255,2,1,2,255,8,128,2,255,255,128,122,23, 83,111,117,114,99,101,76,111,97,100,101,114,46,103,101,116, @@ -1334,7 +1334,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 112,105,108,101,41,4,114,130,0,0,0,114,42,0,0,0, 114,58,0,0,0,114,245,0,0,0,114,7,0,0,0,114, 7,0,0,0,114,8,0,0,0,218,14,115,111,117,114,99, - 101,95,116,111,95,99,111,100,101,124,3,0,0,115,8,0, + 101,95,116,111,95,99,111,100,101,125,3,0,0,115,8,0, 0,0,12,5,4,1,6,255,255,128,122,27,83,111,117,114, 99,101,76,111,97,100,101,114,46,115,111,117,114,99,101,95, 116,111,95,99,111,100,101,99,2,0,0,0,0,0,0,0, @@ -1412,7 +1412,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,17,0,0,0,90,10,98,121,116,101,115,95,100,97, 116,97,90,11,99,111,100,101,95,111,98,106,101,99,116,114, 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,228, - 0,0,0,132,3,0,0,115,170,0,0,0,10,7,4,1, + 0,0,0,133,3,0,0,115,170,0,0,0,10,7,4,1, 4,1,4,1,4,1,4,1,2,1,12,1,14,1,10,1, 2,2,14,1,14,1,6,1,12,2,2,1,14,1,14,1, 4,1,2,3,2,1,6,254,2,4,12,1,16,1,12,1, @@ -1429,7 +1429,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 238,0,0,0,114,239,0,0,0,114,241,0,0,0,114,240, 0,0,0,114,244,0,0,0,114,248,0,0,0,114,228,0, 0,0,114,7,0,0,0,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,114,236,0,0,0,73,3,0,0,115, + 0,114,8,0,0,0,114,236,0,0,0,74,3,0,0,115, 18,0,0,0,8,0,8,2,8,8,8,14,8,10,8,7, 14,10,12,8,255,128,114,236,0,0,0,99,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, @@ -1457,7 +1457,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 32,32,102,105,110,100,101,114,46,78,114,170,0,0,0,41, 3,114,130,0,0,0,114,150,0,0,0,114,58,0,0,0, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 223,0,0,0,222,3,0,0,115,6,0,0,0,6,3,10, + 223,0,0,0,223,3,0,0,115,6,0,0,0,6,3,10, 1,255,128,122,19,70,105,108,101,76,111,97,100,101,114,46, 95,95,105,110,105,116,95,95,99,2,0,0,0,0,0,0, 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, @@ -1466,7 +1466,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,169,2,218,9,95,95,99,108,97,115,115,95,95, 114,143,0,0,0,169,2,114,130,0,0,0,90,5,111,116, 104,101,114,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,218,6,95,95,101,113,95,95,228,3,0,0,243,8, + 0,0,218,6,95,95,101,113,95,95,229,3,0,0,243,8, 0,0,0,12,1,10,1,2,255,255,128,122,17,70,105,108, 101,76,111,97,100,101,114,46,95,95,101,113,95,95,99,1, 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,3, @@ -1475,7 +1475,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,121,0,0,0,169,3,218,4,104,97,115,104,114,128,0, 0,0,114,58,0,0,0,169,1,114,130,0,0,0,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,218,8,95, - 95,104,97,115,104,95,95,232,3,0,0,243,4,0,0,0, + 95,104,97,115,104,95,95,233,3,0,0,243,4,0,0,0, 20,1,255,128,122,19,70,105,108,101,76,111,97,100,101,114, 46,95,95,104,97,115,104,95,95,99,2,0,0,0,0,0, 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, @@ -1489,7 +1489,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 116,101,97,100,46,10,10,32,32,32,32,32,32,32,32,78, 41,3,218,5,115,117,112,101,114,114,254,0,0,0,114,235, 0,0,0,114,234,0,0,0,169,1,114,1,1,0,0,114, - 7,0,0,0,114,8,0,0,0,114,235,0,0,0,235,3, + 7,0,0,0,114,8,0,0,0,114,235,0,0,0,236,3, 0,0,115,4,0,0,0,16,10,255,128,122,22,70,105,108, 101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,100, 117,108,101,99,2,0,0,0,0,0,0,0,0,0,0,0, @@ -1500,7 +1500,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 32,102,111,117,110,100,32,98,121,32,116,104,101,32,102,105, 110,100,101,114,46,78,114,62,0,0,0,114,234,0,0,0, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 190,0,0,0,247,3,0,0,243,4,0,0,0,6,3,255, + 190,0,0,0,248,3,0,0,243,4,0,0,0,6,3,255, 128,122,23,70,105,108,101,76,111,97,100,101,114,46,103,101, 116,95,102,105,108,101,110,97,109,101,99,2,0,0,0,0, 0,0,0,0,0,0,0,3,0,0,0,8,0,0,0,67, @@ -1521,7 +1521,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 112,101,110,95,99,111,100,101,114,97,0,0,0,90,4,114, 101,97,100,114,80,0,0,0,41,3,114,130,0,0,0,114, 58,0,0,0,114,83,0,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,114,242,0,0,0,252,3,0, + 0,0,0,114,8,0,0,0,114,242,0,0,0,253,3,0, 0,115,16,0,0,0,14,2,16,1,22,1,20,128,14,2, 22,1,20,128,255,128,122,19,70,105,108,101,76,111,97,100, 101,114,46,103,101,116,95,100,97,116,97,99,2,0,0,0, @@ -1534,7 +1534,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 130,0,0,0,114,231,0,0,0,114,18,1,0,0,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,218,19,103, 101,116,95,114,101,115,111,117,114,99,101,95,114,101,97,100, - 101,114,5,4,0,0,115,6,0,0,0,12,2,8,1,255, + 101,114,6,4,0,0,115,6,0,0,0,12,2,8,1,255, 128,122,30,70,105,108,101,76,111,97,100,101,114,46,103,101, 116,95,114,101,115,111,117,114,99,101,95,114,101,97,100,101, 114,41,13,114,137,0,0,0,114,136,0,0,0,114,138,0, @@ -1543,7 +1543,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,190,0,0,0,114,242,0,0,0,114,19,1,0,0,90, 13,95,95,99,108,97,115,115,99,101,108,108,95,95,114,7, 0,0,0,114,7,0,0,0,114,12,1,0,0,114,8,0, - 0,0,114,254,0,0,0,217,3,0,0,115,26,0,0,0, + 0,0,114,254,0,0,0,218,3,0,0,115,26,0,0,0, 8,0,4,2,8,3,8,6,8,4,2,3,14,1,2,11, 10,1,8,4,2,9,18,1,255,128,114,254,0,0,0,99, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -1566,7 +1566,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 95,109,116,105,109,101,90,7,115,116,95,115,105,122,101,41, 3,114,130,0,0,0,114,58,0,0,0,114,253,0,0,0, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,114, - 239,0,0,0,15,4,0,0,115,6,0,0,0,8,2,14, + 239,0,0,0,16,4,0,0,115,6,0,0,0,8,2,14, 1,255,128,122,27,83,111,117,114,99,101,70,105,108,101,76, 111,97,100,101,114,46,112,97,116,104,95,115,116,97,116,115, 99,4,0,0,0,0,0,0,0,0,0,0,0,5,0,0, @@ -1576,7 +1576,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 100,101,41,2,114,126,0,0,0,114,240,0,0,0,41,5, 114,130,0,0,0,114,119,0,0,0,114,118,0,0,0,114, 42,0,0,0,114,66,0,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,114,241,0,0,0,20,4,0, + 0,0,0,114,8,0,0,0,114,241,0,0,0,21,4,0, 0,115,6,0,0,0,8,2,16,1,255,128,122,32,83,111, 117,114,99,101,70,105,108,101,76,111,97,100,101,114,46,95, 99,97,99,104,101,95,98,121,116,101,99,111,100,101,114,75, @@ -1612,7 +1612,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,218,6,112,97,114,101,110,116,114,108,0,0,0,114,53, 0,0,0,114,49,0,0,0,114,243,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,114,240,0,0, - 0,25,4,0,0,115,58,0,0,0,12,2,4,1,12,2, + 0,26,4,0,0,115,58,0,0,0,12,2,4,1,12,2, 12,1,10,1,12,254,12,4,10,1,2,1,14,1,12,1, 4,2,14,1,6,3,4,1,4,255,16,2,8,128,2,1, 12,1,18,1,14,1,8,2,2,1,18,255,8,128,2,254, @@ -1621,7 +1621,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 41,7,114,137,0,0,0,114,136,0,0,0,114,138,0,0, 0,114,139,0,0,0,114,239,0,0,0,114,241,0,0,0, 114,240,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,20,1,0,0,11,4, + 7,0,0,0,114,8,0,0,0,114,20,1,0,0,12,4, 0,0,115,12,0,0,0,8,0,4,2,8,2,8,5,18, 5,255,128,114,20,1,0,0,99,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, @@ -1644,7 +1644,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,41,5,114,130,0,0,0,114,150,0,0,0,114, 58,0,0,0,114,42,0,0,0,114,162,0,0,0,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,114,228,0, - 0,0,60,4,0,0,115,24,0,0,0,10,1,10,1,2, + 0,0,61,4,0,0,115,24,0,0,0,10,1,10,1,2, 4,2,1,6,254,12,4,2,1,14,1,2,1,2,1,6, 253,255,128,122,29,83,111,117,114,99,101,108,101,115,115,70, 105,108,101,76,111,97,100,101,114,46,103,101,116,95,99,111, @@ -1654,13 +1654,13 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 97,115,32,116,104,101,114,101,32,105,115,32,110,111,32,115, 111,117,114,99,101,32,99,111,100,101,46,78,114,7,0,0, 0,114,234,0,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,114,244,0,0,0,76,4,0,0,114,25, + 114,8,0,0,0,114,244,0,0,0,77,4,0,0,114,25, 0,0,0,122,31,83,111,117,114,99,101,108,101,115,115,70, 105,108,101,76,111,97,100,101,114,46,103,101,116,95,115,111, 117,114,99,101,78,41,6,114,137,0,0,0,114,136,0,0, 0,114,138,0,0,0,114,139,0,0,0,114,228,0,0,0, 114,244,0,0,0,114,7,0,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,26,1,0,0,56,4, + 7,0,0,0,114,8,0,0,0,114,26,1,0,0,57,4, 0,0,115,10,0,0,0,8,0,4,2,8,2,12,16,255, 128,114,26,1,0,0,99,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,3,0,0,0,64,0,0,0,115, @@ -1682,20 +1682,20 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 100,0,83,0,114,121,0,0,0,114,170,0,0,0,41,3, 114,130,0,0,0,114,128,0,0,0,114,58,0,0,0,114, 7,0,0,0,114,7,0,0,0,114,8,0,0,0,114,223, - 0,0,0,89,4,0,0,115,6,0,0,0,6,1,10,1, + 0,0,0,90,4,0,0,115,6,0,0,0,6,1,10,1, 255,128,122,28,69,120,116,101,110,115,105,111,110,70,105,108, 101,76,111,97,100,101,114,46,95,95,105,110,105,116,95,95, 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, 0,2,0,0,0,67,0,0,0,114,255,0,0,0,114,121, 0,0,0,114,0,1,0,0,114,2,1,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,114,3,1,0, - 0,93,4,0,0,114,4,1,0,0,122,26,69,120,116,101, + 0,94,4,0,0,114,4,1,0,0,122,26,69,120,116,101, 110,115,105,111,110,70,105,108,101,76,111,97,100,101,114,46, 95,95,101,113,95,95,99,1,0,0,0,0,0,0,0,0, 0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,114, 5,1,0,0,114,121,0,0,0,114,6,1,0,0,114,8, 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,9,1,0,0,97,4,0,0,114,10,1,0,0, + 0,0,114,9,1,0,0,98,4,0,0,114,10,1,0,0, 122,28,69,120,116,101,110,115,105,111,110,70,105,108,101,76, 111,97,100,101,114,46,95,95,104,97,115,104,95,95,99,2, 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,5, @@ -1712,7 +1712,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 97,109,105,99,114,160,0,0,0,114,128,0,0,0,114,58, 0,0,0,41,3,114,130,0,0,0,114,198,0,0,0,114, 231,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,226,0,0,0,100,4,0,0,115,16,0,0, + 0,0,0,114,226,0,0,0,101,4,0,0,115,16,0,0, 0,4,2,6,1,4,255,6,2,8,1,4,255,4,2,255, 128,122,33,69,120,116,101,110,115,105,111,110,70,105,108,101, 76,111,97,100,101,114,46,99,114,101,97,116,101,95,109,111, @@ -1730,7 +1730,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 105,99,114,160,0,0,0,114,128,0,0,0,114,58,0,0, 0,169,2,114,130,0,0,0,114,231,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,114,232,0,0, - 0,108,4,0,0,115,10,0,0,0,14,2,6,1,8,1, + 0,109,4,0,0,115,10,0,0,0,14,2,6,1,8,1, 8,255,255,128,122,31,69,120,116,101,110,115,105,111,110,70, 105,108,101,76,111,97,100,101,114,46,101,120,101,99,95,109, 111,100,117,108,101,99,2,0,0,0,0,0,0,0,0,0, @@ -1748,14 +1748,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 78,114,7,0,0,0,169,2,114,5,0,0,0,218,6,115, 117,102,102,105,120,169,1,90,9,102,105,108,101,95,110,97, 109,101,114,7,0,0,0,114,8,0,0,0,114,9,0,0, - 0,117,4,0,0,115,8,0,0,0,4,0,2,1,20,255, + 0,118,4,0,0,115,8,0,0,0,4,0,2,1,20,255, 255,128,122,49,69,120,116,101,110,115,105,111,110,70,105,108, 101,76,111,97,100,101,114,46,105,115,95,112,97,99,107,97, 103,101,46,60,108,111,99,97,108,115,62,46,60,103,101,110, 101,120,112,114,62,78,41,4,114,61,0,0,0,114,58,0, 0,0,218,3,97,110,121,114,219,0,0,0,114,234,0,0, 0,114,7,0,0,0,114,30,1,0,0,114,8,0,0,0, - 114,193,0,0,0,114,4,0,0,115,10,0,0,0,14,2, + 114,193,0,0,0,115,4,0,0,115,10,0,0,0,14,2, 12,1,2,1,8,255,255,128,122,30,69,120,116,101,110,115, 105,111,110,70,105,108,101,76,111,97,100,101,114,46,105,115, 95,112,97,99,107,97,103,101,99,2,0,0,0,0,0,0, @@ -1766,7 +1766,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 110,111,116,32,99,114,101,97,116,101,32,97,32,99,111,100, 101,32,111,98,106,101,99,116,46,78,114,7,0,0,0,114, 234,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,228,0,0,0,120,4,0,0,114,25,0,0, + 0,0,0,114,228,0,0,0,121,4,0,0,114,25,0,0, 0,122,28,69,120,116,101,110,115,105,111,110,70,105,108,101, 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,99, 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, @@ -1776,13 +1776,13 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 115,32,104,97,118,101,32,110,111,32,115,111,117,114,99,101, 32,99,111,100,101,46,78,114,7,0,0,0,114,234,0,0, 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,244,0,0,0,124,4,0,0,114,25,0,0,0,122,30, + 114,244,0,0,0,125,4,0,0,114,25,0,0,0,122,30, 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, 100,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1, 0,0,0,67,0,0,0,114,13,1,0,0,114,14,1,0, 0,114,62,0,0,0,114,234,0,0,0,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,190,0,0,0,128, + 114,7,0,0,0,114,8,0,0,0,114,190,0,0,0,129, 4,0,0,114,15,1,0,0,122,32,69,120,116,101,110,115, 105,111,110,70,105,108,101,76,111,97,100,101,114,46,103,101, 116,95,102,105,108,101,110,97,109,101,78,41,14,114,137,0, @@ -1791,7 +1791,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,226,0,0,0,114,232,0,0,0,114,193,0,0,0,114, 228,0,0,0,114,244,0,0,0,114,147,0,0,0,114,190, 0,0,0,114,7,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,17,1,0,0,81,4,0,0, + 0,0,114,8,0,0,0,114,17,1,0,0,82,4,0,0, 115,26,0,0,0,8,0,4,2,8,6,8,4,8,4,8, 3,8,8,8,6,8,6,8,4,2,4,14,1,255,128,114, 17,1,0,0,99,0,0,0,0,0,0,0,0,0,0,0, @@ -1834,7 +1834,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 102,105,110,100,101,114,169,4,114,130,0,0,0,114,128,0, 0,0,114,58,0,0,0,90,11,112,97,116,104,95,102,105, 110,100,101,114,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,223,0,0,0,141,4,0,0,115,10,0,0, + 0,0,0,114,223,0,0,0,142,4,0,0,115,10,0,0, 0,6,1,6,1,14,1,10,1,255,128,122,23,95,78,97, 109,101,115,112,97,99,101,80,97,116,104,46,95,95,105,110, 105,116,95,95,99,1,0,0,0,0,0,0,0,0,0,0, @@ -1852,7 +1852,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,0,0,218,3,100,111,116,90,2,109,101,114,7,0,0, 0,114,7,0,0,0,114,8,0,0,0,218,23,95,102,105, 110,100,95,112,97,114,101,110,116,95,112,97,116,104,95,110, - 97,109,101,115,147,4,0,0,115,10,0,0,0,18,2,8, + 97,109,101,115,148,4,0,0,115,10,0,0,0,18,2,8, 1,4,2,8,3,255,128,122,38,95,78,97,109,101,115,112, 97,99,101,80,97,116,104,46,95,102,105,110,100,95,112,97, 114,101,110,116,95,112,97,116,104,95,110,97,109,101,115,99, @@ -1865,7 +1865,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 18,112,97,114,101,110,116,95,109,111,100,117,108,101,95,110, 97,109,101,90,14,112,97,116,104,95,97,116,116,114,95,110, 97,109,101,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,35,1,0,0,157,4,0,0,115,6,0,0,0, + 0,0,114,35,1,0,0,158,4,0,0,115,6,0,0,0, 12,1,16,1,255,128,122,31,95,78,97,109,101,115,112,97, 99,101,80,97,116,104,46,95,103,101,116,95,112,97,114,101, 110,116,95,112,97,116,104,99,1,0,0,0,0,0,0,0, @@ -1881,7 +1881,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 34,1,0,0,41,3,114,130,0,0,0,90,11,112,97,114, 101,110,116,95,112,97,116,104,114,198,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,218,12,95,114, - 101,99,97,108,99,117,108,97,116,101,161,4,0,0,115,18, + 101,99,97,108,99,117,108,97,116,101,162,4,0,0,115,18, 0,0,0,12,2,10,1,14,1,18,3,6,1,8,1,6, 1,6,1,255,128,122,27,95,78,97,109,101,115,112,97,99, 101,80,97,116,104,46,95,114,101,99,97,108,99,117,108,97, @@ -1890,7 +1890,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 116,0,124,0,160,1,161,0,131,1,83,0,114,121,0,0, 0,41,2,218,4,105,116,101,114,114,42,1,0,0,114,8, 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,218,8,95,95,105,116,101,114,95,95,174,4,0,0, + 0,0,218,8,95,95,105,116,101,114,95,95,175,4,0,0, 243,4,0,0,0,12,1,255,128,122,23,95,78,97,109,101, 115,112,97,99,101,80,97,116,104,46,95,95,105,116,101,114, 95,95,99,2,0,0,0,0,0,0,0,0,0,0,0,2, @@ -1899,7 +1899,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,169,1,114,42,1,0,0,41,2,114,130,0,0,0,218, 5,105,110,100,101,120,114,7,0,0,0,114,7,0,0,0, 114,8,0,0,0,218,11,95,95,103,101,116,105,116,101,109, - 95,95,177,4,0,0,114,46,1,0,0,122,26,95,78,97, + 95,95,178,4,0,0,114,46,1,0,0,122,26,95,78,97, 109,101,115,112,97,99,101,80,97,116,104,46,95,95,103,101, 116,105,116,101,109,95,95,99,3,0,0,0,0,0,0,0, 0,0,0,0,3,0,0,0,3,0,0,0,67,0,0,0, @@ -1907,7 +1907,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,83,0,114,121,0,0,0,41,1,114,34,1,0,0,41, 3,114,130,0,0,0,114,48,1,0,0,114,58,0,0,0, 114,7,0,0,0,114,7,0,0,0,114,8,0,0,0,218, - 11,95,95,115,101,116,105,116,101,109,95,95,180,4,0,0, + 11,95,95,115,101,116,105,116,101,109,95,95,181,4,0,0, 115,4,0,0,0,14,1,255,128,122,26,95,78,97,109,101, 115,112,97,99,101,80,97,116,104,46,95,95,115,101,116,105, 116,101,109,95,95,99,1,0,0,0,0,0,0,0,0,0, @@ -1915,7 +1915,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,0,0,114,121,0,0,0,41,2,114,4,0,0,0,114, 42,1,0,0,114,8,1,0,0,114,7,0,0,0,114,7, 0,0,0,114,8,0,0,0,218,7,95,95,108,101,110,95, - 95,183,4,0,0,114,46,1,0,0,122,22,95,78,97,109, + 95,184,4,0,0,114,46,1,0,0,122,22,95,78,97,109, 101,115,112,97,99,101,80,97,116,104,46,95,95,108,101,110, 95,95,99,1,0,0,0,0,0,0,0,0,0,0,0,1, 0,0,0,3,0,0,0,67,0,0,0,243,12,0,0,0, @@ -1923,7 +1923,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 20,95,78,97,109,101,115,112,97,99,101,80,97,116,104,40, 123,33,114,125,41,41,2,114,77,0,0,0,114,34,1,0, 0,114,8,1,0,0,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,218,8,95,95,114,101,112,114,95,95,186, + 114,8,0,0,0,218,8,95,95,114,101,112,114,95,95,187, 4,0,0,114,46,1,0,0,122,23,95,78,97,109,101,115, 112,97,99,101,80,97,116,104,46,95,95,114,101,112,114,95, 95,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, @@ -1931,7 +1931,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 1,124,0,160,0,161,0,118,0,83,0,114,121,0,0,0, 114,47,1,0,0,169,2,114,130,0,0,0,218,4,105,116, 101,109,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,218,12,95,95,99,111,110,116,97,105,110,115,95,95,189, + 0,218,12,95,95,99,111,110,116,97,105,110,115,95,95,190, 4,0,0,114,46,1,0,0,122,27,95,78,97,109,101,115, 112,97,99,101,80,97,116,104,46,95,95,99,111,110,116,97, 105,110,115,95,95,99,2,0,0,0,0,0,0,0,0,0, @@ -1939,7 +1939,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,0,124,0,106,0,160,1,124,1,161,1,1,0,100, 0,83,0,114,121,0,0,0,41,2,114,34,1,0,0,114, 197,0,0,0,114,54,1,0,0,114,7,0,0,0,114,7, - 0,0,0,114,8,0,0,0,114,197,0,0,0,192,4,0, + 0,0,0,114,8,0,0,0,114,197,0,0,0,193,4,0, 0,243,4,0,0,0,16,1,255,128,122,21,95,78,97,109, 101,115,112,97,99,101,80,97,116,104,46,97,112,112,101,110, 100,78,41,15,114,137,0,0,0,114,136,0,0,0,114,138, @@ -1948,7 +1948,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,114,49,1,0,0,114,50,1,0,0,114,51,1,0,0, 114,53,1,0,0,114,56,1,0,0,114,197,0,0,0,114, 7,0,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,32,1,0,0,134,4,0,0,115,28,0,0, + 0,0,0,114,32,1,0,0,135,4,0,0,115,28,0,0, 0,8,0,4,1,8,6,8,6,8,10,8,4,8,13,8, 3,8,3,8,3,8,3,8,3,12,3,255,128,114,32,1, 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -1964,7 +1964,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,116,0,124,1,124,2,124,3,131,3,124,0,95,1, 100,0,83,0,114,121,0,0,0,41,2,114,32,1,0,0, 114,34,1,0,0,114,38,1,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,223,0,0,0,198,4, + 7,0,0,0,114,8,0,0,0,114,223,0,0,0,199,4, 0,0,115,4,0,0,0,18,1,255,128,122,25,95,78,97, 109,101,115,112,97,99,101,76,111,97,100,101,114,46,95,95, 105,110,105,116,95,95,99,1,0,0,0,0,0,0,0,0, @@ -1981,20 +1981,20 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 112,97,99,101,41,62,78,41,2,114,77,0,0,0,114,137, 0,0,0,41,1,114,231,0,0,0,114,7,0,0,0,114, 7,0,0,0,114,8,0,0,0,218,11,109,111,100,117,108, - 101,95,114,101,112,114,201,4,0,0,115,4,0,0,0,12, + 101,95,114,101,112,114,202,4,0,0,115,4,0,0,0,12, 7,255,128,122,28,95,78,97,109,101,115,112,97,99,101,76, 111,97,100,101,114,46,109,111,100,117,108,101,95,114,101,112, 114,99,2,0,0,0,0,0,0,0,0,0,0,0,2,0, 0,0,1,0,0,0,67,0,0,0,114,24,0,0,0,41, 2,78,84,114,7,0,0,0,114,234,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,114,193,0,0, - 0,210,4,0,0,243,4,0,0,0,4,1,255,128,122,27, + 0,211,4,0,0,243,4,0,0,0,4,1,255,128,122,27, 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, 0,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, 67,0,0,0,114,24,0,0,0,41,2,78,114,10,0,0, 0,114,7,0,0,0,114,234,0,0,0,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,244,0,0,0,213, + 114,7,0,0,0,114,8,0,0,0,114,244,0,0,0,214, 4,0,0,114,60,1,0,0,122,27,95,78,97,109,101,115, 112,97,99,101,76,111,97,100,101,114,46,103,101,116,95,115, 111,117,114,99,101,99,2,0,0,0,0,0,0,0,0,0, @@ -2004,20 +2004,20 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,105,110,103,62,114,230,0,0,0,84,41,1,114,246,0, 0,0,41,1,114,247,0,0,0,114,234,0,0,0,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,114,228,0, - 0,0,216,4,0,0,114,57,1,0,0,122,25,95,78,97, + 0,0,217,4,0,0,114,57,1,0,0,122,25,95,78,97, 109,101,115,112,97,99,101,76,111,97,100,101,114,46,103,101, 116,95,99,111,100,101,99,2,0,0,0,0,0,0,0,0, 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,114, 24,0,0,0,114,224,0,0,0,114,7,0,0,0,114,225, 0,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,226,0,0,0,219,4,0,0,114,227,0,0,0, + 0,0,114,226,0,0,0,220,4,0,0,114,227,0,0,0, 122,30,95,78,97,109,101,115,112,97,99,101,76,111,97,100, 101,114,46,99,114,101,97,116,101,95,109,111,100,117,108,101, 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,0, 83,0,114,121,0,0,0,114,7,0,0,0,114,27,1,0, 0,114,7,0,0,0,114,7,0,0,0,114,8,0,0,0, - 114,232,0,0,0,222,4,0,0,114,60,1,0,0,122,28, + 114,232,0,0,0,223,4,0,0,114,60,1,0,0,122,28, 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, @@ -2035,7 +2035,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,125,78,41,4,114,146,0,0,0,114,160,0,0,0,114, 34,1,0,0,114,233,0,0,0,114,234,0,0,0,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,114,235,0, - 0,0,225,4,0,0,115,10,0,0,0,6,7,4,1,4, + 0,0,226,4,0,0,115,10,0,0,0,6,7,4,1,4, 255,12,3,255,128,122,28,95,78,97,109,101,115,112,97,99, 101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,100, 117,108,101,78,41,12,114,137,0,0,0,114,136,0,0,0, @@ -2043,7 +2043,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 59,1,0,0,114,193,0,0,0,114,244,0,0,0,114,228, 0,0,0,114,226,0,0,0,114,232,0,0,0,114,235,0, 0,0,114,7,0,0,0,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,114,58,1,0,0,197,4,0,0,115, + 0,114,8,0,0,0,114,58,1,0,0,198,4,0,0,115, 22,0,0,0,8,0,8,1,2,3,10,1,8,8,8,3, 8,3,8,3,8,3,12,3,255,128,114,58,1,0,0,99, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -2080,7 +2080,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 95,99,97,99,104,101,218,5,105,116,101,109,115,114,140,0, 0,0,114,62,1,0,0,41,2,114,128,0,0,0,218,6, 102,105,110,100,101,114,114,7,0,0,0,114,7,0,0,0, - 114,8,0,0,0,114,62,1,0,0,244,4,0,0,115,16, + 114,8,0,0,0,114,62,1,0,0,245,4,0,0,115,16, 0,0,0,22,4,8,1,10,1,10,1,8,1,2,128,4, 252,255,128,122,28,80,97,116,104,70,105,110,100,101,114,46, 105,110,118,97,108,105,100,97,116,101,95,99,97,99,104,101, @@ -2100,7 +2100,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 89,0,0,0,114,149,0,0,0,114,129,0,0,0,41,2, 114,58,0,0,0,90,4,104,111,111,107,114,7,0,0,0, 114,7,0,0,0,114,8,0,0,0,218,11,95,112,97,116, - 104,95,104,111,111,107,115,254,4,0,0,115,20,0,0,0, + 104,95,104,111,111,107,115,255,4,0,0,115,20,0,0,0, 16,3,12,1,10,1,2,1,14,1,12,1,4,1,4,2, 2,253,255,128,122,22,80,97,116,104,70,105,110,100,101,114, 46,95,112,97,116,104,95,104,111,111,107,115,99,2,0,0, @@ -2132,7 +2132,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,41,3,114,209,0,0,0,114,58,0,0,0,114,66, 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, 0,0,218,20,95,112,97,116,104,95,105,109,112,111,114,116, - 101,114,95,99,97,99,104,101,11,5,0,0,115,30,0,0, + 101,114,95,99,97,99,104,101,12,5,0,0,115,30,0,0, 0,8,8,2,1,12,1,12,1,6,3,2,1,12,1,4, 4,12,253,10,1,12,1,4,1,2,253,2,250,255,128,122, 31,80,97,116,104,70,105,110,100,101,114,46,95,112,97,116, @@ -2150,7 +2150,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 209,0,0,0,114,150,0,0,0,114,66,1,0,0,114,151, 0,0,0,114,152,0,0,0,114,198,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,218,16,95,108, - 101,103,97,99,121,95,103,101,116,95,115,112,101,99,33,5, + 101,103,97,99,121,95,103,101,116,95,115,112,101,99,34,5, 0,0,115,20,0,0,0,10,4,16,1,10,2,4,1,8, 1,12,1,12,1,6,1,4,1,255,128,122,27,80,97,116, 104,70,105,110,100,101,114,46,95,108,101,103,97,99,121,95, @@ -2182,7 +2182,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 101,95,112,97,116,104,90,5,101,110,116,114,121,114,66,1, 0,0,114,198,0,0,0,114,152,0,0,0,114,7,0,0, 0,114,7,0,0,0,114,8,0,0,0,218,9,95,103,101, - 116,95,115,112,101,99,48,5,0,0,115,44,0,0,0,4, + 116,95,115,112,101,99,49,5,0,0,115,44,0,0,0,4, 5,8,1,14,1,2,1,10,1,8,1,10,1,14,1,12, 2,8,1,2,1,10,1,8,1,6,1,8,1,8,1,10, 5,2,128,12,2,6,1,4,1,255,128,122,20,80,97,116, @@ -2209,7 +2209,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 32,1,0,0,41,6,114,209,0,0,0,114,150,0,0,0, 114,58,0,0,0,114,213,0,0,0,114,198,0,0,0,114, 74,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,214,0,0,0,80,5,0,0,115,28,0,0, + 0,0,0,114,214,0,0,0,81,5,0,0,115,28,0,0, 0,8,6,6,1,14,1,8,1,4,1,10,1,6,1,4, 1,6,3,16,1,4,1,4,2,4,2,255,128,122,20,80, 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,115, @@ -2229,7 +2229,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 105,110,100,95,115,112,101,99,40,41,32,105,110,115,116,101, 97,100,46,10,10,32,32,32,32,32,32,32,32,78,114,215, 0,0,0,114,216,0,0,0,114,7,0,0,0,114,7,0, - 0,0,114,8,0,0,0,114,217,0,0,0,104,5,0,0, + 0,0,114,8,0,0,0,114,217,0,0,0,105,5,0,0, 115,10,0,0,0,12,8,8,1,4,1,6,1,255,128,122, 22,80,97,116,104,70,105,110,100,101,114,46,102,105,110,100, 95,109,111,100,117,108,101,99,0,0,0,0,0,0,0,0, @@ -2261,7 +2261,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 18,102,105,110,100,95,100,105,115,116,114,105,98,117,116,105, 111,110,115,41,3,114,131,0,0,0,114,132,0,0,0,114, 76,1,0,0,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,114,77,1,0,0,117,5,0,0,115,6,0,0, + 0,0,0,114,77,1,0,0,118,5,0,0,115,6,0,0, 0,12,10,16,1,255,128,122,29,80,97,116,104,70,105,110, 100,101,114,46,102,105,110,100,95,100,105,115,116,114,105,98, 117,116,105,111,110,115,41,1,78,41,2,78,78,41,1,78, @@ -2271,7 +2271,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 72,1,0,0,114,75,1,0,0,114,214,0,0,0,114,217, 0,0,0,114,77,1,0,0,114,7,0,0,0,114,7,0, 0,0,114,7,0,0,0,114,8,0,0,0,114,61,1,0, - 0,240,4,0,0,115,38,0,0,0,8,0,4,2,2,2, + 0,241,4,0,0,115,38,0,0,0,8,0,4,2,2,2, 10,1,2,9,10,1,2,12,10,1,2,21,10,1,2,14, 12,1,2,31,12,1,2,23,12,1,2,12,14,1,255,128, 114,61,1,0,0,99,0,0,0,0,0,0,0,0,0,0, @@ -2316,7 +2316,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,102,2,86,0,1,0,113,2,100,0,83,0,114,121,0, 0,0,114,7,0,0,0,114,28,1,0,0,169,1,114,151, 0,0,0,114,7,0,0,0,114,8,0,0,0,114,9,0, - 0,0,146,5,0,0,114,14,0,0,0,122,38,70,105,108, + 0,0,147,5,0,0,114,14,0,0,0,122,38,70,105,108, 101,70,105,110,100,101,114,46,95,95,105,110,105,116,95,95, 46,60,108,111,99,97,108,115,62,46,60,103,101,110,101,120, 112,114,62,114,86,0,0,0,114,116,0,0,0,78,41,7, @@ -2328,7 +2328,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 58,0,0,0,218,14,108,111,97,100,101,114,95,100,101,116, 97,105,108,115,90,7,108,111,97,100,101,114,115,114,200,0, 0,0,114,7,0,0,0,114,79,1,0,0,114,8,0,0, - 0,114,223,0,0,0,140,5,0,0,115,18,0,0,0,4, + 0,114,223,0,0,0,141,5,0,0,115,18,0,0,0,4, 4,12,1,26,1,6,1,10,2,6,1,8,1,12,1,255, 128,122,19,70,105,108,101,70,105,110,100,101,114,46,95,95, 105,110,105,116,95,95,99,1,0,0,0,0,0,0,0,0, @@ -2338,7 +2338,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 32,100,105,114,101,99,116,111,114,121,32,109,116,105,109,101, 46,114,116,0,0,0,78,41,1,114,81,1,0,0,114,8, 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,62,1,0,0,154,5,0,0,114,69,0,0,0, + 0,0,114,62,1,0,0,155,5,0,0,114,69,0,0,0, 122,28,70,105,108,101,70,105,110,100,101,114,46,105,110,118, 97,108,105,100,97,116,101,95,99,97,99,104,101,115,99,2, 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,3, @@ -2361,7 +2361,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 41,3,114,214,0,0,0,114,151,0,0,0,114,189,0,0, 0,41,3,114,130,0,0,0,114,150,0,0,0,114,198,0, 0,0,114,7,0,0,0,114,7,0,0,0,114,8,0,0, - 0,114,148,0,0,0,160,5,0,0,115,10,0,0,0,10, + 0,114,148,0,0,0,161,5,0,0,115,10,0,0,0,10, 7,8,1,8,1,16,1,255,128,122,22,70,105,108,101,70, 105,110,100,101,114,46,102,105,110,100,95,108,111,97,100,101, 114,99,6,0,0,0,0,0,0,0,0,0,0,0,7,0, @@ -2372,7 +2372,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 199,0,0,0,114,150,0,0,0,114,58,0,0,0,90,4, 115,109,115,108,114,213,0,0,0,114,151,0,0,0,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,114,75,1, - 0,0,172,5,0,0,115,10,0,0,0,10,1,8,1,2, + 0,0,173,5,0,0,115,10,0,0,0,10,1,8,1,2, 1,6,255,255,128,122,20,70,105,108,101,70,105,110,100,101, 114,46,95,103,101,116,95,115,112,101,99,78,99,3,0,0, 0,0,0,0,0,0,0,0,0,14,0,0,0,8,0,0, @@ -2427,7 +2427,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 110,105,116,95,102,105,108,101,110,97,109,101,90,9,102,117, 108,108,95,112,97,116,104,114,198,0,0,0,114,7,0,0, 0,114,7,0,0,0,114,8,0,0,0,114,214,0,0,0, - 177,5,0,0,115,80,0,0,0,4,5,14,1,2,1,24, + 178,5,0,0,115,80,0,0,0,4,5,14,1,2,1,24, 1,14,1,6,1,10,1,8,1,6,1,6,2,6,1,10, 1,6,2,4,1,8,2,12,1,14,1,8,1,10,1,8, 1,24,1,2,255,8,5,14,2,16,1,16,1,14,1,10, @@ -2458,7 +2458,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 104,0,124,0,93,12,125,1,124,1,160,0,161,0,146,2, 113,4,83,0,114,7,0,0,0,41,1,114,117,0,0,0, 41,2,114,5,0,0,0,90,2,102,110,114,7,0,0,0, - 114,7,0,0,0,114,8,0,0,0,114,13,0,0,0,254, + 114,7,0,0,0,114,8,0,0,0,114,13,0,0,0,255, 5,0,0,115,4,0,0,0,20,0,255,128,122,41,70,105, 108,101,70,105,110,100,101,114,46,95,102,105,108,108,95,99, 97,99,104,101,46,60,108,111,99,97,108,115,62,46,60,115, @@ -2476,7 +2476,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,55,1,0,0,114,128,0,0,0,114,39,1,0,0,114, 29,1,0,0,90,8,110,101,119,95,110,97,109,101,114,7, 0,0,0,114,7,0,0,0,114,8,0,0,0,114,86,1, - 0,0,225,5,0,0,115,40,0,0,0,6,2,2,1,22, + 0,0,226,5,0,0,115,40,0,0,0,6,2,2,1,22, 1,18,1,6,3,12,3,12,1,6,7,8,1,16,1,4, 1,18,1,4,2,12,1,6,1,12,1,20,1,4,255,2, 233,255,128,122,22,70,105,108,101,70,105,110,100,101,114,46, @@ -2515,14 +2515,14 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 169,2,114,209,0,0,0,114,85,1,0,0,114,7,0,0, 0,114,8,0,0,0,218,24,112,97,116,104,95,104,111,111, 107,95,102,111,114,95,70,105,108,101,70,105,110,100,101,114, - 10,6,0,0,115,8,0,0,0,8,2,12,1,16,1,255, + 11,6,0,0,115,8,0,0,0,8,2,12,1,16,1,255, 128,122,54,70,105,108,101,70,105,110,100,101,114,46,112,97, 116,104,95,104,111,111,107,46,60,108,111,99,97,108,115,62, 46,112,97,116,104,95,104,111,111,107,95,102,111,114,95,70, 105,108,101,70,105,110,100,101,114,78,114,7,0,0,0,41, 3,114,209,0,0,0,114,85,1,0,0,114,91,1,0,0, 114,7,0,0,0,114,90,1,0,0,114,8,0,0,0,218, - 9,112,97,116,104,95,104,111,111,107,0,6,0,0,115,6, + 9,112,97,116,104,95,104,111,111,107,1,6,0,0,115,6, 0,0,0,14,10,4,6,255,128,122,20,70,105,108,101,70, 105,110,100,101,114,46,112,97,116,104,95,104,111,111,107,99, 1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, @@ -2530,7 +2530,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 122,16,70,105,108,101,70,105,110,100,101,114,40,123,33,114, 125,41,41,2,114,77,0,0,0,114,58,0,0,0,114,8, 1,0,0,114,7,0,0,0,114,7,0,0,0,114,8,0, - 0,0,114,53,1,0,0,18,6,0,0,114,46,1,0,0, + 0,0,114,53,1,0,0,19,6,0,0,114,46,1,0,0, 122,19,70,105,108,101,70,105,110,100,101,114,46,95,95,114, 101,112,114,95,95,41,1,78,41,15,114,137,0,0,0,114, 136,0,0,0,114,138,0,0,0,114,139,0,0,0,114,223, @@ -2538,7 +2538,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,114,148,0,0,0,114,75,1,0,0,114,214,0,0, 0,114,86,1,0,0,114,221,0,0,0,114,92,1,0,0, 114,53,1,0,0,114,7,0,0,0,114,7,0,0,0,114, - 7,0,0,0,114,8,0,0,0,114,78,1,0,0,131,5, + 7,0,0,0,114,8,0,0,0,114,78,1,0,0,132,5, 0,0,115,26,0,0,0,8,0,4,2,8,7,8,14,4, 4,8,2,8,12,10,5,8,48,2,31,10,1,12,17,255, 128,114,78,1,0,0,99,4,0,0,0,0,0,0,0,0, @@ -2562,7 +2562,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 97,109,101,90,9,99,112,97,116,104,110,97,109,101,114,151, 0,0,0,114,198,0,0,0,114,7,0,0,0,114,7,0, 0,0,114,8,0,0,0,218,14,95,102,105,120,95,117,112, - 95,109,111,100,117,108,101,24,6,0,0,115,38,0,0,0, + 95,109,111,100,117,108,101,25,6,0,0,115,38,0,0,0, 10,2,10,1,4,1,4,1,8,1,8,1,12,1,10,2, 4,1,14,1,2,1,8,1,8,1,8,1,14,1,12,1, 6,2,2,254,255,128,114,97,1,0,0,99,0,0,0,0, @@ -2582,7 +2582,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 0,0,114,101,0,0,0,41,3,90,10,101,120,116,101,110, 115,105,111,110,115,90,6,115,111,117,114,99,101,90,8,98, 121,116,101,99,111,100,101,114,7,0,0,0,114,7,0,0, - 0,114,8,0,0,0,114,195,0,0,0,47,6,0,0,115, + 0,114,8,0,0,0,114,195,0,0,0,48,6,0,0,115, 10,0,0,0,12,5,8,1,8,1,10,1,255,128,114,195, 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0,1,0,0,0,67,0,0,0,115,8,0,0, @@ -2591,7 +2591,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,97,112,95,109,111,100,117,108,101,114,7,0,0,0,114, 7,0,0,0,114,8,0,0,0,218,21,95,115,101,116,95, 98,111,111,116,115,116,114,97,112,95,109,111,100,117,108,101, - 58,6,0,0,115,4,0,0,0,8,2,255,128,114,100,1, + 59,6,0,0,115,4,0,0,0,8,2,255,128,114,100,1, 0,0,99,1,0,0,0,0,0,0,0,0,0,0,0,2, 0,0,0,4,0,0,0,67,0,0,0,115,50,0,0,0, 116,0,124,0,131,1,1,0,116,1,131,0,125,1,116,2, @@ -2606,7 +2606,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 114,197,0,0,0,114,61,1,0,0,41,2,114,99,1,0, 0,90,17,115,117,112,112,111,114,116,101,100,95,108,111,97, 100,101,114,115,114,7,0,0,0,114,7,0,0,0,114,8, - 0,0,0,218,8,95,105,110,115,116,97,108,108,63,6,0, + 0,0,0,218,8,95,105,110,115,116,97,108,108,64,6,0, 0,115,10,0,0,0,8,2,6,1,20,1,16,1,255,128, 114,102,1,0,0,41,1,114,75,0,0,0,41,1,78,41, 3,78,78,78,41,2,114,0,0,0,0,114,0,0,0,0, @@ -2649,7 +2649,7 @@ const unsigned char _Py_M__importlib_bootstrap_external[] = { 2,4,3,10,1,6,2,22,2,8,1,10,1,14,1,4, 4,4,1,2,1,2,1,4,255,8,4,6,16,8,3,8, 5,8,5,8,6,8,6,8,12,8,10,8,9,8,5,8, - 7,10,9,10,22,0,127,16,24,12,1,4,2,4,1,6, + 7,10,9,10,22,0,127,16,25,12,1,4,2,4,1,6, 2,6,1,10,1,8,2,6,2,8,2,16,2,8,71,8, 40,8,19,8,12,8,12,8,31,8,17,8,33,8,28,10, 24,10,13,10,10,8,11,6,14,4,3,2,1,12,255,14, diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 8495871..692442a 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -29,11 +29,11 @@ static void *opcode_targets[256] = { &&TARGET_BINARY_TRUE_DIVIDE, &&TARGET_INPLACE_FLOOR_DIVIDE, &&TARGET_INPLACE_TRUE_DIVIDE, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_GET_LEN, + &&TARGET_MATCH_MAPPING, + &&TARGET_MATCH_SEQUENCE, + &&TARGET_MATCH_KEYS, + &&TARGET_COPY_DICT_WITHOUT_KEYS, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -151,7 +151,7 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_MATCH_CLASS, &&_unknown_opcode, &&TARGET_SETUP_ASYNC_WITH, &&TARGET_FORMAT_VALUE, diff --git a/Python/pystate.c b/Python/pystate.c index 1623bab..e7c085d 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -308,6 +308,8 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) Py_CLEAR(interp->importlib); Py_CLEAR(interp->import_func); Py_CLEAR(interp->dict); + Py_CLEAR(interp->map_abc); + Py_CLEAR(interp->seq_abc); #ifdef HAVE_FORK Py_CLEAR(interp->before_forkers); Py_CLEAR(interp->after_forkers_parent); diff --git a/Python/symtable.c b/Python/symtable.c index cce1b1b..10a47d1 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -207,6 +207,7 @@ static int symtable_visit_argannotations(struct symtable *st, asdl_arg_seq *args static int symtable_implicit_arg(struct symtable *st, int pos); static int symtable_visit_annotations(struct symtable *st, arguments_ty, expr_ty); static int symtable_visit_withitem(struct symtable *st, withitem_ty item); +static int symtable_visit_match_case(struct symtable *st, match_case_ty m); static identifier top = NULL, lambda = NULL, genexpr = NULL, @@ -239,6 +240,7 @@ symtable_new(void) goto fail; st->st_cur = NULL; st->st_private = NULL; + st->in_pattern = 0; return st; fail: PySymtable_Free(st); @@ -1294,6 +1296,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (s->v.If.orelse) VISIT_SEQ(st, stmt, s->v.If.orelse); break; + case Match_kind: + VISIT(st, expr, s->v.Match.subject); + VISIT_SEQ(st, match_case, s->v.Match.cases); + break; case Raise_kind: if (s->v.Raise.exc) { VISIT(st, expr, s->v.Raise.exc); @@ -1648,6 +1654,13 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT(st, expr, e->v.Slice.step) break; case Name_kind: + // Don't make "_" a local when used in a pattern: + if (st->in_pattern && + e->v.Name.ctx == Store && + _PyUnicode_EqualToASCIIString(e->v.Name.id, "_")) + { + break; + } if (!symtable_add_def(st, e->v.Name.id, e->v.Name.ctx == Load ? USE : DEF_LOCAL)) VISIT_QUIT(st, 0); @@ -1667,6 +1680,13 @@ symtable_visit_expr(struct symtable *st, expr_ty e) case Tuple_kind: VISIT_SEQ(st, expr, e->v.Tuple.elts); break; + case MatchAs_kind: + VISIT(st, expr, e->v.MatchAs.pattern); + symtable_add_def(st, e->v.MatchAs.name, DEF_LOCAL); + break; + case MatchOr_kind: + VISIT_SEQ(st, expr, e->v.MatchOr.patterns); + break; } VISIT_QUIT(st, 1); } @@ -1785,6 +1805,20 @@ symtable_visit_withitem(struct symtable *st, withitem_ty item) return 1; } +static int +symtable_visit_match_case(struct symtable *st, match_case_ty m) +{ + assert(!st->in_pattern); + st->in_pattern = 1; + VISIT(st, expr, m->pattern); + assert(st->in_pattern); + st->in_pattern = 0; + if (m->guard) { + VISIT(st, expr, m->guard); + } + VISIT_SEQ(st, stmt, m->body); + return 1; +} static int symtable_visit_alias(struct symtable *st, alias_ty a) |