diff options
Diffstat (limited to 'Python')
-rw-r--r-- | Python/Python-ast.c | 349 | ||||
-rw-r--r-- | Python/ast.c | 13 | ||||
-rw-r--r-- | Python/ast_opt.c | 7 | ||||
-rw-r--r-- | Python/ast_unparse.c | 201 | ||||
-rw-r--r-- | Python/bltinmodule.c | 2 | ||||
-rw-r--r-- | Python/bytecodes.c | 298 | ||||
-rw-r--r-- | Python/ceval.c | 8 | ||||
-rw-r--r-- | Python/codecs.c | 18 | ||||
-rw-r--r-- | Python/codegen.c | 110 | ||||
-rw-r--r-- | Python/executor_cases.c.h | 83 | ||||
-rw-r--r-- | Python/gc.c | 5 | ||||
-rw-r--r-- | Python/gc_free_threading.c | 5 | ||||
-rw-r--r-- | Python/generated_cases.c.h | 113 | ||||
-rw-r--r-- | Python/hamt.c | 6 | ||||
-rw-r--r-- | Python/instruction_sequence.c | 2 | ||||
-rw-r--r-- | Python/intrinsics.c | 1 | ||||
-rw-r--r-- | Python/jit.c | 2 | ||||
-rw-r--r-- | Python/opcode_targets.h | 16 | ||||
-rw-r--r-- | Python/optimizer_cases.c.h | 18 | ||||
-rw-r--r-- | Python/pylifecycle.c | 10 | ||||
-rw-r--r-- | Python/pystate.c | 5 | ||||
-rw-r--r-- | Python/symtable.c | 8 | ||||
-rw-r--r-- | Python/traceback.c | 2 |
23 files changed, 1046 insertions, 236 deletions
diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 98dcdc4ed0b..94d9a76d283 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -92,6 +92,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->In_singleton); Py_CLEAR(state->In_type); Py_CLEAR(state->Interactive_type); + Py_CLEAR(state->Interpolation_type); Py_CLEAR(state->Invert_singleton); Py_CLEAR(state->Invert_type); Py_CLEAR(state->IsNot_singleton); @@ -154,6 +155,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->Sub_singleton); Py_CLEAR(state->Sub_type); Py_CLEAR(state->Subscript_type); + Py_CLEAR(state->TemplateStr_type); Py_CLEAR(state->TryStar_type); Py_CLEAR(state->Try_type); Py_CLEAR(state->Tuple_type); @@ -259,6 +261,7 @@ void _PyAST_Fini(PyInterpreterState *interp) Py_CLEAR(state->slice); Py_CLEAR(state->step); Py_CLEAR(state->stmt_type); + Py_CLEAR(state->str); Py_CLEAR(state->subject); Py_CLEAR(state->tag); Py_CLEAR(state->target); @@ -357,6 +360,7 @@ static int init_identifiers(struct ast_state *state) if ((state->simple = PyUnicode_InternFromString("simple")) == NULL) return -1; if ((state->slice = PyUnicode_InternFromString("slice")) == NULL) return -1; if ((state->step = PyUnicode_InternFromString("step")) == NULL) return -1; + if ((state->str = PyUnicode_InternFromString("str")) == NULL) return -1; if ((state->subject = PyUnicode_InternFromString("subject")) == NULL) return -1; if ((state->tag = PyUnicode_InternFromString("tag")) == NULL) return -1; if ((state->target = PyUnicode_InternFromString("target")) == NULL) return -1; @@ -619,9 +623,18 @@ static const char * const FormattedValue_fields[]={ "conversion", "format_spec", }; +static const char * const Interpolation_fields[]={ + "value", + "str", + "conversion", + "format_spec", +}; static const char * const JoinedStr_fields[]={ "values", }; +static const char * const TemplateStr_fields[]={ + "values", +}; static const char * const Constant_fields[]={ "value", "kind", @@ -3174,6 +3187,70 @@ add_ast_annotations(struct ast_state *state) return 0; } Py_DECREF(FormattedValue_annotations); + PyObject *Interpolation_annotations = PyDict_New(); + if (!Interpolation_annotations) return 0; + { + PyObject *type = state->expr_type; + Py_INCREF(type); + cond = PyDict_SetItemString(Interpolation_annotations, "value", type) + == 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(Interpolation_annotations); + return 0; + } + } + { + PyObject *type = (PyObject *)&PyBaseObject_Type; + Py_INCREF(type); + cond = PyDict_SetItemString(Interpolation_annotations, "str", type) == + 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(Interpolation_annotations); + return 0; + } + } + { + PyObject *type = (PyObject *)&PyLong_Type; + Py_INCREF(type); + cond = PyDict_SetItemString(Interpolation_annotations, "conversion", + type) == 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(Interpolation_annotations); + return 0; + } + } + { + PyObject *type = state->expr_type; + type = _Py_union_type_or(type, Py_None); + cond = type != NULL; + if (!cond) { + Py_DECREF(Interpolation_annotations); + return 0; + } + cond = PyDict_SetItemString(Interpolation_annotations, "format_spec", + type) == 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(Interpolation_annotations); + return 0; + } + } + cond = PyObject_SetAttrString(state->Interpolation_type, "_field_types", + Interpolation_annotations) == 0; + if (!cond) { + Py_DECREF(Interpolation_annotations); + return 0; + } + cond = PyObject_SetAttrString(state->Interpolation_type, "__annotations__", + Interpolation_annotations) == 0; + if (!cond) { + Py_DECREF(Interpolation_annotations); + return 0; + } + Py_DECREF(Interpolation_annotations); PyObject *JoinedStr_annotations = PyDict_New(); if (!JoinedStr_annotations) return 0; { @@ -3204,6 +3281,37 @@ add_ast_annotations(struct ast_state *state) return 0; } Py_DECREF(JoinedStr_annotations); + PyObject *TemplateStr_annotations = PyDict_New(); + if (!TemplateStr_annotations) return 0; + { + PyObject *type = state->expr_type; + type = Py_GenericAlias((PyObject *)&PyList_Type, type); + cond = type != NULL; + if (!cond) { + Py_DECREF(TemplateStr_annotations); + return 0; + } + cond = PyDict_SetItemString(TemplateStr_annotations, "values", type) == + 0; + Py_DECREF(type); + if (!cond) { + Py_DECREF(TemplateStr_annotations); + return 0; + } + } + cond = PyObject_SetAttrString(state->TemplateStr_type, "_field_types", + TemplateStr_annotations) == 0; + if (!cond) { + Py_DECREF(TemplateStr_annotations); + return 0; + } + cond = PyObject_SetAttrString(state->TemplateStr_type, "__annotations__", + TemplateStr_annotations) == 0; + if (!cond) { + Py_DECREF(TemplateStr_annotations); + return 0; + } + Py_DECREF(TemplateStr_annotations); PyObject *Constant_annotations = PyDict_New(); if (!Constant_annotations) return 0; { @@ -6266,7 +6374,9 @@ init_types(void *arg) " | Compare(expr left, cmpop* ops, expr* comparators)\n" " | Call(expr func, expr* args, keyword* keywords)\n" " | FormattedValue(expr value, int conversion, expr? format_spec)\n" + " | Interpolation(expr value, constant str, int conversion, expr? format_spec)\n" " | JoinedStr(expr* values)\n" + " | TemplateStr(expr* values)\n" " | Constant(constant value, string? kind)\n" " | Attribute(expr value, identifier attr, expr_context ctx)\n" " | Subscript(expr value, expr slice, expr_context ctx)\n" @@ -6361,10 +6471,22 @@ init_types(void *arg) if (PyObject_SetAttr(state->FormattedValue_type, state->format_spec, Py_None) == -1) return -1; + state->Interpolation_type = make_type(state, "Interpolation", + state->expr_type, + Interpolation_fields, 4, + "Interpolation(expr value, constant str, int conversion, expr? format_spec)"); + if (!state->Interpolation_type) return -1; + if (PyObject_SetAttr(state->Interpolation_type, state->format_spec, + Py_None) == -1) + return -1; state->JoinedStr_type = make_type(state, "JoinedStr", state->expr_type, JoinedStr_fields, 1, "JoinedStr(expr* values)"); if (!state->JoinedStr_type) return -1; + state->TemplateStr_type = make_type(state, "TemplateStr", state->expr_type, + TemplateStr_fields, 1, + "TemplateStr(expr* values)"); + if (!state->TemplateStr_type) return -1; state->Constant_type = make_type(state, "Constant", state->expr_type, Constant_fields, 2, "Constant(constant value, string? kind)"); @@ -8039,6 +8161,37 @@ _PyAST_FormattedValue(expr_ty value, int conversion, expr_ty format_spec, int } expr_ty +_PyAST_Interpolation(expr_ty value, constant str, int conversion, expr_ty + format_spec, int lineno, int col_offset, int end_lineno, + int end_col_offset, PyArena *arena) +{ + expr_ty p; + if (!value) { + PyErr_SetString(PyExc_ValueError, + "field 'value' is required for Interpolation"); + return NULL; + } + if (!str) { + PyErr_SetString(PyExc_ValueError, + "field 'str' is required for Interpolation"); + return NULL; + } + p = (expr_ty)_PyArena_Malloc(arena, sizeof(*p)); + if (!p) + return NULL; + p->kind = Interpolation_kind; + p->v.Interpolation.value = value; + p->v.Interpolation.str = str; + p->v.Interpolation.conversion = conversion; + p->v.Interpolation.format_spec = format_spec; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + +expr_ty _PyAST_JoinedStr(asdl_expr_seq * values, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena) { @@ -8056,6 +8209,23 @@ _PyAST_JoinedStr(asdl_expr_seq * values, int lineno, int col_offset, int } expr_ty +_PyAST_TemplateStr(asdl_expr_seq * values, 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 = TemplateStr_kind; + p->v.TemplateStr.values = values; + p->lineno = lineno; + p->col_offset = col_offset; + p->end_lineno = end_lineno; + p->end_col_offset = end_col_offset; + return p; +} + +expr_ty _PyAST_Constant(constant value, string kind, int lineno, int col_offset, int end_lineno, int end_col_offset, PyArena *arena) { @@ -9674,6 +9844,31 @@ ast2obj_expr(struct ast_state *state, void* _o) goto failed; Py_DECREF(value); break; + case Interpolation_kind: + tp = (PyTypeObject *)state->Interpolation_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_expr(state, o->v.Interpolation.value); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->value, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_constant(state, o->v.Interpolation.str); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->str, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_int(state, o->v.Interpolation.conversion); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->conversion, value) == -1) + goto failed; + Py_DECREF(value); + value = ast2obj_expr(state, o->v.Interpolation.format_spec); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->format_spec, value) == -1) + goto failed; + Py_DECREF(value); + break; case JoinedStr_kind: tp = (PyTypeObject *)state->JoinedStr_type; result = PyType_GenericNew(tp, NULL, NULL); @@ -9685,6 +9880,17 @@ ast2obj_expr(struct ast_state *state, void* _o) goto failed; Py_DECREF(value); break; + case TemplateStr_kind: + tp = (PyTypeObject *)state->TemplateStr_type; + result = PyType_GenericNew(tp, NULL, NULL); + if (!result) goto failed; + value = ast2obj_list(state, (asdl_seq*)o->v.TemplateStr.values, + ast2obj_expr); + if (!value) goto failed; + if (PyObject_SetAttr(result, state->values, value) == -1) + goto failed; + Py_DECREF(value); + break; case Constant_kind: tp = (PyTypeObject *)state->Constant_type; result = PyType_GenericNew(tp, NULL, NULL); @@ -14793,6 +14999,91 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (*out == NULL) goto failed; return 0; } + tp = state->Interpolation_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return -1; + } + if (isinstance) { + expr_ty value; + constant str; + int conversion; + expr_ty format_spec; + + if (PyObject_GetOptionalAttr(obj, state->value, &tmp) < 0) { + return -1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Interpolation"); + return -1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { + goto failed; + } + res = obj2ast_expr(state, tmp, &value, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (PyObject_GetOptionalAttr(obj, state->str, &tmp) < 0) { + return -1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"str\" missing from Interpolation"); + return -1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { + goto failed; + } + res = obj2ast_constant(state, tmp, &str, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (PyObject_GetOptionalAttr(obj, state->conversion, &tmp) < 0) { + return -1; + } + if (tmp == NULL) { + PyErr_SetString(PyExc_TypeError, "required field \"conversion\" missing from Interpolation"); + return -1; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { + goto failed; + } + res = obj2ast_int(state, tmp, &conversion, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + if (PyObject_GetOptionalAttr(obj, state->format_spec, &tmp) < 0) { + return -1; + } + if (tmp == NULL || tmp == Py_None) { + Py_CLEAR(tmp); + format_spec = NULL; + } + else { + int res; + if (_Py_EnterRecursiveCall(" while traversing 'Interpolation' node")) { + goto failed; + } + res = obj2ast_expr(state, tmp, &format_spec, arena); + _Py_LeaveRecursiveCall(); + if (res != 0) goto failed; + Py_CLEAR(tmp); + } + *out = _PyAST_Interpolation(value, str, conversion, format_spec, + lineno, col_offset, end_lineno, + end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } tp = state->JoinedStr_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -14844,6 +15135,57 @@ obj2ast_expr(struct ast_state *state, PyObject* obj, expr_ty* out, PyArena* if (*out == NULL) goto failed; return 0; } + tp = state->TemplateStr_type; + isinstance = PyObject_IsInstance(obj, tp); + if (isinstance == -1) { + return -1; + } + if (isinstance) { + asdl_expr_seq* values; + + if (PyObject_GetOptionalAttr(obj, state->values, &tmp) < 0) { + return -1; + } + if (tmp == NULL) { + tmp = PyList_New(0); + if (tmp == NULL) { + return -1; + } + } + { + int res; + Py_ssize_t len; + Py_ssize_t i; + if (!PyList_Check(tmp)) { + PyErr_Format(PyExc_TypeError, "TemplateStr field \"values\" must be a list, not a %.200s", _PyType_Name(Py_TYPE(tmp))); + goto failed; + } + len = PyList_GET_SIZE(tmp); + values = _Py_asdl_expr_seq_new(len, arena); + if (values == NULL) goto failed; + for (i = 0; i < len; i++) { + expr_ty val; + PyObject *tmp2 = Py_NewRef(PyList_GET_ITEM(tmp, i)); + if (_Py_EnterRecursiveCall(" while traversing 'TemplateStr' node")) { + goto failed; + } + res = obj2ast_expr(state, tmp2, &val, arena); + _Py_LeaveRecursiveCall(); + Py_DECREF(tmp2); + if (res != 0) goto failed; + if (len != PyList_GET_SIZE(tmp)) { + PyErr_SetString(PyExc_RuntimeError, "TemplateStr field \"values\" changed size during iteration"); + goto failed; + } + asdl_seq_SET(values, i, val); + } + Py_CLEAR(tmp); + } + *out = _PyAST_TemplateStr(values, lineno, col_offset, end_lineno, + end_col_offset, arena); + if (*out == NULL) goto failed; + return 0; + } tp = state->Constant_type; isinstance = PyObject_IsInstance(obj, tp); if (isinstance == -1) { @@ -17794,9 +18136,16 @@ astmodule_exec(PyObject *m) < 0) { return -1; } + if (PyModule_AddObjectRef(m, "Interpolation", state->Interpolation_type) < + 0) { + return -1; + } if (PyModule_AddObjectRef(m, "JoinedStr", state->JoinedStr_type) < 0) { return -1; } + if (PyModule_AddObjectRef(m, "TemplateStr", state->TemplateStr_type) < 0) { + return -1; + } if (PyModule_AddObjectRef(m, "Constant", state->Constant_type) < 0) { return -1; } diff --git a/Python/ast.c b/Python/ast.c index 7ee884357b4..e01dd0de51e 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -345,6 +345,9 @@ validate_expr(expr_ty exp, expr_context_ty ctx) case JoinedStr_kind: ret = validate_exprs(exp->v.JoinedStr.values, Load, 0); break; + case TemplateStr_kind: + ret = validate_exprs(exp->v.TemplateStr.values, Load, 0); + break; case FormattedValue_kind: if (validate_expr(exp->v.FormattedValue.value, Load) == 0) return 0; @@ -354,6 +357,15 @@ validate_expr(expr_ty exp, expr_context_ty ctx) } ret = 1; break; + case Interpolation_kind: + if (validate_expr(exp->v.Interpolation.value, Load) == 0) + return 0; + if (exp->v.Interpolation.format_spec) { + ret = validate_expr(exp->v.Interpolation.format_spec, Load); + break; + } + ret = 1; + break; case Attribute_kind: ret = validate_expr(exp->v.Attribute.value, Load); break; @@ -512,6 +524,7 @@ validate_pattern_match_value(expr_ty exp) } break; case JoinedStr_kind: + case TemplateStr_kind: // Handled in the later stages return 1; default: diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 807de98ab5e..4d5e5589ac0 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -558,9 +558,16 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) CALL(astfold_expr, expr_ty, node_->v.FormattedValue.value); CALL_OPT(astfold_expr, expr_ty, node_->v.FormattedValue.format_spec); break; + case Interpolation_kind: + CALL(astfold_expr, expr_ty, node_->v.Interpolation.value); + CALL_OPT(astfold_expr, expr_ty, node_->v.Interpolation.format_spec); + break; case JoinedStr_kind: CALL_SEQ(astfold_expr, expr, node_->v.JoinedStr.values); break; + case TemplateStr_kind: + CALL_SEQ(astfold_expr, expr, node_->v.TemplateStr.values); + break; case Attribute_kind: CALL(astfold_expr, expr_ty, node_->v.Attribute.value); break; diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c index f3c669c33eb..c121ec096ae 100644 --- a/Python/ast_unparse.c +++ b/Python/ast_unparse.c @@ -18,8 +18,12 @@ expr_as_unicode(expr_ty e, int level); static int append_ast_expr(PyUnicodeWriter *writer, expr_ty e, int level); static int +append_templatestr(PyUnicodeWriter *writer, expr_ty e); +static int append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec); static int +append_interpolation(PyUnicodeWriter *writer, expr_ty e); +static int append_formattedvalue(PyUnicodeWriter *writer, expr_ty e); static int append_ast_slice(PyUnicodeWriter *writer, expr_ty e); @@ -621,11 +625,15 @@ append_fstring_element(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) return append_fstring_unicode(writer, e->v.Constant.value); case JoinedStr_kind: return append_joinedstr(writer, e, is_format_spec); + case TemplateStr_kind: + return append_templatestr(writer, e); case FormattedValue_kind: return append_formattedvalue(writer, e); + case Interpolation_kind: + return append_interpolation(writer, e); default: PyErr_SetString(PyExc_SystemError, - "unknown expression kind inside f-string"); + "unknown expression kind inside f-string or t-string"); return -1; } } @@ -633,7 +641,7 @@ append_fstring_element(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) /* Build body separately to enable wrapping the entire stream of Strs, Constants and FormattedValues in one opening and one closing quote. */ static PyObject * -build_fstring_body(asdl_expr_seq *values, bool is_format_spec) +build_ftstring_body(asdl_expr_seq *values, bool is_format_spec) { PyUnicodeWriter *body_writer = PyUnicodeWriter_Create(256); if (body_writer == NULL) { @@ -655,10 +663,98 @@ build_fstring_body(asdl_expr_seq *values, bool is_format_spec) } static int +_write_values_subarray(PyUnicodeWriter *writer, asdl_expr_seq *values, Py_ssize_t first_idx, + Py_ssize_t last_idx, char prefix, PyArena *arena) +{ + int result = -1; + + asdl_expr_seq *new_values = _Py_asdl_expr_seq_new(last_idx - first_idx + 1, arena); + if (!new_values) { + return result; + } + + Py_ssize_t j = 0; + for (Py_ssize_t i = first_idx; i <= last_idx; ++i) { + asdl_seq_SET(new_values, j++, asdl_seq_GET(values, i)); + } + + PyObject *body = build_ftstring_body(new_values, false); + if (!body) { + return result; + } + + if (-1 != append_char(writer, prefix) && + -1 != append_repr(writer, body)) + { + result = 0; + } + Py_DECREF(body); + return result; +} + +static int +append_templatestr(PyUnicodeWriter *writer, expr_ty e) +{ + PyArena *arena = _PyArena_New(); + if (!arena) { + return -1; + } + + Py_ssize_t last_idx = 0; + Py_ssize_t len = asdl_seq_LEN(e->v.TemplateStr.values); + for (Py_ssize_t i = 0; i < len; i++) { + expr_ty value = asdl_seq_GET(e->v.TemplateStr.values, i); + + // Handle implicit concat of t-strings with f-strings + if (value->kind == FormattedValue_kind) { + if (i > last_idx) { + // Create a new TemplateStr with the values between last_idx and i + // and append it to the writer. + if (_write_values_subarray(writer, e->v.TemplateStr.values, + last_idx, i - 1, 't', arena) == -1) { + goto error; + } + + if (append_charp(writer, " ") == -1) { + goto error; + } + } + + // Append the FormattedValue to the writer. + if (_write_values_subarray(writer, e->v.TemplateStr.values, + i, i, 'f', arena) == -1) { + goto error; + } + + if (i + 1 < len) { + if (append_charp(writer, " ") == -1) { + goto error; + } + } + + last_idx = i + 1; + } + } + + if (last_idx < len) { + if (_write_values_subarray(writer, e->v.TemplateStr.values, + last_idx, len - 1, 't', arena) == -1) { + goto error; + } + } + + return 0; + +error: + _PyArena_Free(arena); + return -1; +} + +static int append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) { int result = -1; - PyObject *body = build_fstring_body(e->v.JoinedStr.values, is_format_spec); + PyObject *body = build_ftstring_body(e->v.JoinedStr.values, is_format_spec); if (!body) { return -1; } @@ -678,13 +774,12 @@ append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) } static int -append_formattedvalue(PyUnicodeWriter *writer, expr_ty e) +append_interpolation_value(PyUnicodeWriter *writer, expr_ty e) { - const char *conversion; const char *outer_brace = "{"; /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis around a lambda with ':' */ - PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, PR_TEST + 1); + PyObject *temp_fv_str = expr_as_unicode(e, PR_TEST + 1); if (!temp_fv_str) { return -1; } @@ -702,35 +797,81 @@ append_formattedvalue(PyUnicodeWriter *writer, expr_ty e) return -1; } Py_DECREF(temp_fv_str); + return 0; +} - if (e->v.FormattedValue.conversion > 0) { - switch (e->v.FormattedValue.conversion) { - case 'a': - conversion = "!a"; - break; - case 'r': - conversion = "!r"; - break; - case 's': - conversion = "!s"; - break; - default: - PyErr_SetString(PyExc_SystemError, - "unknown f-value conversion kind"); - return -1; - } - APPEND_STR(conversion); +static int +append_interpolation_conversion(PyUnicodeWriter *writer, int conversion) +{ + if (conversion < 0) { + return 0; } - if (e->v.FormattedValue.format_spec) { + + const char *conversion_str; + switch (conversion) { + case 'a': + conversion_str = "!a"; + break; + case 'r': + conversion_str = "!r"; + break; + case 's': + conversion_str = "!s"; + break; + default: + PyErr_SetString(PyExc_SystemError, + "unknown f-value conversion kind"); + return -1; + } + APPEND_STR(conversion_str); + return 0; +} + +static int +append_interpolation_format_spec(PyUnicodeWriter *writer, expr_ty e) +{ + if (e) { if (-1 == PyUnicodeWriter_WriteChar(writer, ':') || - -1 == append_fstring_element(writer, - e->v.FormattedValue.format_spec, - true - )) + -1 == append_fstring_element(writer, e, true)) { return -1; } } + return 0; +} + +static int +append_interpolation(PyUnicodeWriter *writer, expr_ty e) +{ + if (-1 == append_interpolation_value(writer, e->v.Interpolation.value)) { + return -1; + } + + if (-1 == append_interpolation_conversion(writer, e->v.Interpolation.conversion)) { + return -1; + } + + if (-1 == append_interpolation_format_spec(writer, e->v.Interpolation.format_spec)) { + return -1; + } + + APPEND_STR_FINISH("}"); +} + +static int +append_formattedvalue(PyUnicodeWriter *writer, expr_ty e) +{ + if (-1 == append_interpolation_value(writer, e->v.FormattedValue.value)) { + return -1; + } + + if (-1 == append_interpolation_conversion(writer, e->v.FormattedValue.conversion)) { + return -1; + } + + if (-1 == append_interpolation_format_spec(writer, e->v.FormattedValue.format_spec)) { + return -1; + } APPEND_CHAR_FINISH('}'); } @@ -901,8 +1042,12 @@ append_ast_expr(PyUnicodeWriter *writer, expr_ty e, int level) return append_ast_constant(writer, e->v.Constant.value); case JoinedStr_kind: return append_joinedstr(writer, e, false); + case TemplateStr_kind: + return append_templatestr(writer, e); case FormattedValue_kind: return append_formattedvalue(writer, e); + case Interpolation_kind: + return append_interpolation(writer, e); /* The following exprs can be assignment targets. */ case Attribute_kind: return append_ast_attribute(writer, e); diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 8ed0a96270b..3221d5acf96 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -566,11 +566,9 @@ filter_dealloc(PyObject *self) { filterobject *lz = _filterobject_CAST(self); PyObject_GC_UnTrack(lz); - Py_TRASHCAN_BEGIN(lz, filter_dealloc) Py_XDECREF(lz->func); Py_XDECREF(lz->it); Py_TYPE(lz)->tp_free(lz); - Py_TRASHCAN_END } static int diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 6592bc57ed2..496a53dbabe 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -16,6 +16,7 @@ #include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS #include "pycore_function.h" #include "pycore_instruments.h" +#include "pycore_interpolation.h" // _PyInterpolation_Build() #include "pycore_intrinsics.h" #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_moduleobject.h" // PyModuleObject @@ -30,6 +31,7 @@ #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs #include "pycore_stackref.h" +#include "pycore_template.h" // _PyTemplate_Build() #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_typeobject.h" // _PySuper_Lookup() @@ -156,7 +158,7 @@ dummy_func( QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { int err = _Py_HandlePending(tstate); - ERROR_IF(err != 0, error); + ERROR_IF(err != 0); } } @@ -166,7 +168,7 @@ dummy_func( QSBR_QUIESCENT_STATE(tstate); if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) { int err = _Py_HandlePending(tstate); - ERROR_IF(err != 0, error); + ERROR_IF(err != 0); } } } @@ -200,7 +202,7 @@ dummy_func( ((_PyThreadStateImpl *)tstate)->tlbc_index) { _Py_CODEUNIT *bytecode = _PyEval_GetExecutableCode(tstate, _PyFrame_GetCode(frame)); - ERROR_IF(bytecode == NULL, error); + ERROR_IF(bytecode == NULL); ptrdiff_t off = this_instr - _PyFrame_GetBytecode(frame); frame->tlbc_index = ((_PyThreadStateImpl *)tstate)->tlbc_index; frame->instr_ptr = bytecode + off; @@ -236,7 +238,7 @@ dummy_func( op(_MONITOR_RESUME, (--)) { int err = _Py_call_instrumentation( tstate, oparg > 0, frame, this_instr); - ERROR_IF(err, error); + ERROR_IF(err); if (frame->instr_ptr != this_instr) { /* Instrumentation has jumped */ next_instr = frame->instr_ptr; @@ -260,7 +262,7 @@ dummy_func( UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) ); - ERROR_IF(1, error); + ERROR_IF(true); } value = PyStackRef_DUP(value_s); } @@ -446,7 +448,7 @@ dummy_func( inst(UNARY_NEGATIVE, (value -- res)) { PyObject *res_o = PyNumber_Negative(PyStackRef_AsPyObjectBorrow(value)); PyStackRef_CLOSE(value); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -481,7 +483,7 @@ dummy_func( op(_TO_BOOL, (value -- res)) { int err = PyObject_IsTrue(PyStackRef_AsPyObjectBorrow(value)); PyStackRef_CLOSE(value); - ERROR_IF(err < 0, error); + ERROR_IF(err < 0); res = err ? PyStackRef_True : PyStackRef_False; } @@ -576,7 +578,7 @@ dummy_func( inst(UNARY_INVERT, (value -- res)) { PyObject *res_o = PyNumber_Invert(PyStackRef_AsPyObjectBorrow(value)); PyStackRef_CLOSE(value); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -618,7 +620,7 @@ dummy_func( PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); INPUTS_DEAD(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -633,7 +635,7 @@ dummy_func( PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); INPUTS_DEAD(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -648,7 +650,7 @@ dummy_func( PyStackRef_CLOSE_SPECIALIZED(right, _PyLong_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyLong_ExactDealloc); INPUTS_DEAD(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -681,7 +683,7 @@ dummy_func( ((PyFloatObject *)right_o)->ob_fval; res = _PyFloat_FromDouble_ConsumeInputs(left, right, dres); INPUTS_DEAD(); - ERROR_IF(PyStackRef_IsNull(res), error); + ERROR_IF(PyStackRef_IsNull(res)); } pure op(_BINARY_OP_ADD_FLOAT, (left, right -- res)) { @@ -696,7 +698,7 @@ dummy_func( ((PyFloatObject *)right_o)->ob_fval; res = _PyFloat_FromDouble_ConsumeInputs(left, right, dres); INPUTS_DEAD(); - ERROR_IF(PyStackRef_IsNull(res), error); + ERROR_IF(PyStackRef_IsNull(res)); } pure op(_BINARY_OP_SUBTRACT_FLOAT, (left, right -- res)) { @@ -711,7 +713,7 @@ dummy_func( ((PyFloatObject *)right_o)->ob_fval; res = _PyFloat_FromDouble_ConsumeInputs(left, right, dres); INPUTS_DEAD(); - ERROR_IF(PyStackRef_IsNull(res), error); + ERROR_IF(PyStackRef_IsNull(res)); } macro(BINARY_OP_MULTIPLY_FLOAT) = @@ -732,7 +734,7 @@ dummy_func( PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc); PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc); INPUTS_DEAD(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -780,7 +782,7 @@ dummy_func( PyUnicode_Append(&temp, right_o); *target_local = PyStackRef_FromPyObjectSteal(temp); Py_DECREF(right_o); - ERROR_IF(PyStackRef_IsNull(*target_local), error); + ERROR_IF(PyStackRef_IsNull(*target_local)); #if TIER_ONE // The STORE_FAST is already done. This is done here in tier one, // and during trace projection in tier two: @@ -839,7 +841,7 @@ dummy_func( Py_DECREF(slice); } PyStackRef_CLOSE(container); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -864,7 +866,7 @@ dummy_func( Py_DECREF(slice); } DECREF_INPUTS(); - ERROR_IF(err, error); + ERROR_IF(err); } macro(STORE_SLICE) = _SPECIALIZE_STORE_SLICE + _STORE_SLICE; @@ -978,7 +980,7 @@ dummy_func( _PyErr_SetKeyError(sub); } DECREF_INPUTS(); - ERROR_IF(rc <= 0, error); // not found or error + ERROR_IF(rc <= 0); // not found or error res = PyStackRef_FromPyObjectSteal(res_o); } @@ -1016,13 +1018,13 @@ dummy_func( inst(LIST_APPEND, (list, unused[oparg-1], v -- list, unused[oparg-1])) { int err = _PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list), PyStackRef_AsPyObjectSteal(v)); - ERROR_IF(err < 0, error); + ERROR_IF(err < 0); } inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) { int err = _PySet_AddTakeRef((PySetObject *)PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectSteal(v)); - ERROR_IF(err, error); + ERROR_IF(err); } family(STORE_SUBSCR, INLINE_CACHE_ENTRIES_STORE_SUBSCR) = { @@ -1046,7 +1048,7 @@ dummy_func( /* container[sub] = v */ int err = PyObject_SetItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub), PyStackRef_AsPyObjectBorrow(v)); DECREF_INPUTS(); - ERROR_IF(err, error); + ERROR_IF(err); } macro(STORE_SUBSCR) = _SPECIALIZE_STORE_SUBSCR + _STORE_SUBSCR; @@ -1095,7 +1097,7 @@ dummy_func( PyStackRef_AsPyObjectSteal(sub), PyStackRef_AsPyObjectSteal(value)); PyStackRef_CLOSE(dict_st); - ERROR_IF(err, error); + ERROR_IF(err); } inst(DELETE_SUBSCR, (container, sub --)) { @@ -1103,14 +1105,14 @@ dummy_func( int err = PyObject_DelItem(PyStackRef_AsPyObjectBorrow(container), PyStackRef_AsPyObjectBorrow(sub)); DECREF_INPUTS(); - ERROR_IF(err, error); + ERROR_IF(err); } inst(CALL_INTRINSIC_1, (value -- res)) { assert(oparg <= MAX_INTRINSIC_1); PyObject *res_o = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, PyStackRef_AsPyObjectBorrow(value)); PyStackRef_CLOSE(value); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -1121,7 +1123,7 @@ dummy_func( PyObject *res_o = _PyIntrinsics_BinaryFunctions[oparg].func(tstate, value2, value1); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -1135,7 +1137,7 @@ dummy_func( monitor_reraise(tstate, frame, this_instr); goto exception_unwind; } - ERROR_IF(true, error); + ERROR_IF(true); } tier1 inst(INTERPRETER_EXIT, (retval --)) { @@ -1173,7 +1175,7 @@ dummy_func( int err = _Py_call_instrumentation_arg( tstate, PY_MONITORING_EVENT_PY_RETURN, frame, this_instr, PyStackRef_AsPyObjectBorrow(val)); - ERROR_IF(err, error); + ERROR_IF(err); } macro(INSTRUMENTED_RETURN_VALUE) = @@ -1196,12 +1198,12 @@ dummy_func( "__aiter__ method, got %.100s", type->tp_name); PyStackRef_CLOSE(obj); - ERROR_IF(true, error); + ERROR_IF(true); } iter_o = (*getter)(obj_o); PyStackRef_CLOSE(obj); - ERROR_IF(iter_o == NULL, error); + ERROR_IF(iter_o == NULL); if (Py_TYPE(iter_o)->tp_as_async == NULL || Py_TYPE(iter_o)->tp_as_async->am_anext == NULL) { @@ -1211,7 +1213,7 @@ dummy_func( "that does not implement __anext__: %.100s", Py_TYPE(iter_o)->tp_name); Py_DECREF(iter_o); - ERROR_IF(true, error); + ERROR_IF(true); } iter = PyStackRef_FromPyObjectSteal(iter_o); } @@ -1227,7 +1229,7 @@ dummy_func( inst(GET_AWAITABLE, (iterable -- iter)) { PyObject *iter_o = _PyEval_GetAwaitable(PyStackRef_AsPyObjectBorrow(iterable), oparg); PyStackRef_CLOSE(iterable); - ERROR_IF(iter_o == NULL, error); + ERROR_IF(iter_o == NULL); iter = PyStackRef_FromPyObjectSteal(iter_o); } @@ -1289,7 +1291,7 @@ dummy_func( } else { PyStackRef_CLOSE(v); - ERROR_IF(true, error); + ERROR_IF(true); } } PyStackRef_CLOSE(v); @@ -1450,11 +1452,11 @@ dummy_func( inst(LOAD_BUILD_CLASS, ( -- bc)) { PyObject *bc_o; int err = PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc_o); - ERROR_IF(err < 0, error); + ERROR_IF(err < 0); if (bc_o == NULL) { _PyErr_SetString(tstate, PyExc_NameError, "__build_class__ not found"); - ERROR_IF(true, error); + ERROR_IF(true); } bc = PyStackRef_FromPyObjectSteal(bc_o); } @@ -1467,7 +1469,7 @@ dummy_func( _PyErr_Format(tstate, PyExc_SystemError, "no locals found when storing %R", name); PyStackRef_CLOSE(v); - ERROR_IF(true, error); + ERROR_IF(true); } if (PyDict_CheckExact(ns)) { err = PyDict_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); @@ -1476,7 +1478,7 @@ dummy_func( err = PyObject_SetItem(ns, name, PyStackRef_AsPyObjectBorrow(v)); } PyStackRef_CLOSE(v); - ERROR_IF(err, error); + ERROR_IF(err); } inst(DELETE_NAME, (--)) { @@ -1522,7 +1524,7 @@ dummy_func( PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); int res = _PyEval_UnpackIterableStackRef(tstate, seq_o, oparg, -1, top); Py_DECREF(seq_o); - ERROR_IF(res == 0, error); + ERROR_IF(res == 0); } macro(UNPACK_SEQUENCE) = _SPECIALIZE_UNPACK_SEQUENCE + _UNPACK_SEQUENCE; @@ -1580,7 +1582,7 @@ dummy_func( PyObject *seq_o = PyStackRef_AsPyObjectSteal(seq); int res = _PyEval_UnpackIterableStackRef(tstate, seq_o, oparg & 0xFF, oparg >> 8, top); Py_DECREF(seq_o); - ERROR_IF(res == 0, error); + ERROR_IF(res == 0); } family(STORE_ATTR, INLINE_CACHE_ENTRIES_STORE_ATTR) = { @@ -1607,7 +1609,7 @@ dummy_func( int err = PyObject_SetAttr(PyStackRef_AsPyObjectBorrow(owner), name, PyStackRef_AsPyObjectBorrow(v)); DECREF_INPUTS(); - ERROR_IF(err, error); + ERROR_IF(err); } macro(STORE_ATTR) = _SPECIALIZE_STORE_ATTR + unused/3 + _STORE_ATTR; @@ -1616,14 +1618,14 @@ dummy_func( PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyObject_DelAttr(PyStackRef_AsPyObjectBorrow(owner), name); PyStackRef_CLOSE(owner); - ERROR_IF(err, error); + ERROR_IF(err); } inst(STORE_GLOBAL, (v --)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); int err = PyDict_SetItem(GLOBALS(), name, PyStackRef_AsPyObjectBorrow(v)); PyStackRef_CLOSE(v); - ERROR_IF(err, error); + ERROR_IF(err); } inst(DELETE_GLOBAL, (--)) { @@ -1645,7 +1647,7 @@ dummy_func( if (l == NULL) { _PyErr_SetString(tstate, PyExc_SystemError, "no locals found"); - ERROR_IF(true, error); + ERROR_IF(true); } locals = PyStackRef_FromPyObjectNew(l); } @@ -1655,7 +1657,7 @@ dummy_func( PyObject *v_o; int err = PyMapping_GetOptionalItem(PyStackRef_AsPyObjectBorrow(mod_or_class_dict), name, &v_o); PyStackRef_CLOSE(mod_or_class_dict); - ERROR_IF(err < 0, error); + ERROR_IF(err < 0); if (v_o == NULL) { if (PyDict_CheckExact(GLOBALS()) && PyDict_CheckExact(BUILTINS())) @@ -1677,16 +1679,16 @@ dummy_func( /* Slow-path if globals or builtins is not a dict */ /* namespace 1: globals */ int err = PyMapping_GetOptionalItem(GLOBALS(), name, &v_o); - ERROR_IF(err < 0, error); + ERROR_IF(err < 0); if (v_o == NULL) { /* namespace 2: builtins */ int err = PyMapping_GetOptionalItem(BUILTINS(), name, &v_o); - ERROR_IF(err < 0, error); + ERROR_IF(err < 0); if (v_o == NULL) { _PyEval_FormatExcCheckArg( tstate, PyExc_NameError, NAME_ERROR_MSG, name); - ERROR_IF(true, error); + ERROR_IF(true); } } } @@ -1697,7 +1699,7 @@ dummy_func( inst(LOAD_NAME, (-- v)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *v_o = _PyEval_LoadName(tstate, frame, name); - ERROR_IF(v_o == NULL, error); + ERROR_IF(v_o == NULL); v = PyStackRef_FromPyObjectSteal(v_o); } @@ -1723,7 +1725,7 @@ dummy_func( op(_LOAD_GLOBAL, ( -- res[1])) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1); _PyEval_LoadGlobalStackRef(GLOBALS(), BUILTINS(), name, res); - ERROR_IF(PyStackRef_IsNull(*res), error); + ERROR_IF(PyStackRef_IsNull(*res)); } op(_PUSH_NULL_CONDITIONAL, ( -- null[oparg & 1])) { @@ -1806,7 +1808,7 @@ dummy_func( UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(_PyFrame_GetCode(frame)->co_localsplusnames, oparg) ); - ERROR_IF(1, error); + ERROR_IF(true); } _PyStackRef tmp = GETLOCAL(oparg); GETLOCAL(oparg) = PyStackRef_NULL; @@ -1867,7 +1869,7 @@ dummy_func( value = _PyCell_GetStackRef(cell); if (PyStackRef_IsNull(value)) { _PyEval_FormatExcUnbound(tstate, _PyFrame_GetCode(frame), oparg); - ERROR_IF(true, error); + ERROR_IF(true); } } @@ -1894,15 +1896,49 @@ dummy_func( STACKREFS_TO_PYOBJECTS(pieces, oparg, pieces_o); if (CONVERSION_FAILED(pieces_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *str_o = _PyUnicode_JoinArray(&_Py_STR(empty), pieces_o, oparg); STACKREFS_TO_PYOBJECTS_CLEANUP(pieces_o); DECREF_INPUTS(); - ERROR_IF(str_o == NULL, error); + ERROR_IF(str_o == NULL); str = PyStackRef_FromPyObjectSteal(str_o); } + inst(BUILD_INTERPOLATION, (value, str, format[oparg & 1] -- interpolation)) { + PyObject *value_o = PyStackRef_AsPyObjectBorrow(value); + PyObject *str_o = PyStackRef_AsPyObjectBorrow(str); + int conversion = oparg >> 2; + PyObject *format_o; + if (oparg & 1) { + format_o = PyStackRef_AsPyObjectBorrow(format[0]); + } + else { + format_o = &_Py_STR(empty); + } + PyObject *interpolation_o = _PyInterpolation_Build(value_o, str_o, conversion, format_o); + if (oparg & 1) { + PyStackRef_CLOSE(format[0]); + } + else { + DEAD(format); + } + PyStackRef_CLOSE(str); + PyStackRef_CLOSE(value); + ERROR_IF(interpolation_o == NULL); + interpolation = PyStackRef_FromPyObjectSteal(interpolation_o); + } + + inst(BUILD_TEMPLATE, (strings, interpolations -- template)) { + PyObject *strings_o = PyStackRef_AsPyObjectBorrow(strings); + PyObject *interpolations_o = PyStackRef_AsPyObjectBorrow(interpolations); + PyObject *template_o = _PyTemplate_Build(strings_o, interpolations_o); + PyStackRef_CLOSE(interpolations); + PyStackRef_CLOSE(strings); + ERROR_IF(template_o == NULL); + template = PyStackRef_FromPyObjectSteal(template_o); + } + inst(BUILD_TUPLE, (values[oparg] -- tup)) { PyObject *tup_o = _PyTuple_FromStackRefStealOnSuccess(values, oparg); if (tup_o == NULL) { @@ -1937,7 +1973,7 @@ dummy_func( Py_TYPE(iterable)->tp_name); } PyStackRef_CLOSE(iterable_st); - ERROR_IF(true, error); + ERROR_IF(true); } assert(Py_IsNone(none_val)); PyStackRef_CLOSE(iterable_st); @@ -1947,14 +1983,14 @@ dummy_func( int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), PyStackRef_AsPyObjectBorrow(iterable)); PyStackRef_CLOSE(iterable); - ERROR_IF(err < 0, error); + ERROR_IF(err < 0); } inst(BUILD_SET, (values[oparg] -- set)) { PyObject *set_o = PySet_New(NULL); if (set_o == NULL) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } int err = 0; @@ -1971,7 +2007,7 @@ dummy_func( DEAD(values); if (err) { Py_DECREF(set_o); - ERROR_IF(true, error); + ERROR_IF(true); } INPUTS_DEAD(); @@ -1982,7 +2018,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS(values, oparg*2, values_o); if (CONVERSION_FAILED(values_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *map_o = _PyDict_FromItems( values_o, 2, @@ -1990,7 +2026,7 @@ dummy_func( oparg); STACKREFS_TO_PYOBJECTS_CLEANUP(values_o); DECREF_INPUTS(); - ERROR_IF(map_o == NULL, error); + ERROR_IF(map_o == NULL); map = PyStackRef_FromPyObjectStealMortal(map_o); } @@ -1999,18 +2035,18 @@ dummy_func( if (LOCALS() == NULL) { _PyErr_Format(tstate, PyExc_SystemError, "no locals found when setting up annotations"); - ERROR_IF(true, error); + ERROR_IF(true); } /* check if __annotations__ in locals()... */ int err = PyMapping_GetOptionalItem(LOCALS(), &_Py_ID(__annotations__), &ann_dict); - ERROR_IF(err < 0, error); + ERROR_IF(err < 0); if (ann_dict == NULL) { ann_dict = PyDict_New(); - ERROR_IF(ann_dict == NULL, error); + ERROR_IF(ann_dict == NULL); err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__), ann_dict); Py_DECREF(ann_dict); - ERROR_IF(err, error); + ERROR_IF(err); } else { Py_DECREF(ann_dict); @@ -2034,7 +2070,7 @@ dummy_func( Py_TYPE(update_o)->tp_name); } PyStackRef_CLOSE(update); - ERROR_IF(true, error); + ERROR_IF(true); } PyStackRef_CLOSE(update); } @@ -2048,7 +2084,7 @@ dummy_func( if (err < 0) { _PyEval_FormatKwargsError(tstate, callable_o, update_o); PyStackRef_CLOSE(update); - ERROR_IF(true, error); + ERROR_IF(true); } PyStackRef_CLOSE(update); } @@ -2063,7 +2099,7 @@ dummy_func( PyStackRef_AsPyObjectSteal(key), PyStackRef_AsPyObjectSteal(value) ); - ERROR_IF(err != 0, error); + ERROR_IF(err != 0); } macro(INSTRUMENTED_LOAD_SUPER_ATTR) = @@ -2101,7 +2137,7 @@ dummy_func( frame, this_instr, global_super, arg); if (err) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } } // we make no attempt to optimize here; specializations should @@ -2125,11 +2161,11 @@ dummy_func( } } DECREF_INPUTS(); - ERROR_IF(super == NULL, error); + ERROR_IF(super == NULL); PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyObject *attr_o = PyObject_GetAttr(super, name); Py_DECREF(super); - ERROR_IF(attr_o == NULL, error); + ERROR_IF(attr_o == NULL); attr = PyStackRef_FromPyObjectSteal(attr_o); } @@ -2150,7 +2186,7 @@ dummy_func( PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2); PyObject *attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL); DECREF_INPUTS(); - ERROR_IF(attr == NULL, error); + ERROR_IF(attr == NULL); attr_st = PyStackRef_FromPyObjectSteal(attr); } @@ -2236,7 +2272,7 @@ dummy_func( meth | NULL | arg1 | ... | argN */ PyStackRef_CLOSE(owner); - ERROR_IF(attr_o == NULL, error); + ERROR_IF(attr_o == NULL); self_or_null[0] = PyStackRef_NULL; } } @@ -2244,7 +2280,7 @@ dummy_func( /* Classic, pushes one value. */ attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name); PyStackRef_CLOSE(owner); - ERROR_IF(attr_o == NULL, error); + ERROR_IF(attr_o == NULL); } attr = PyStackRef_FromPyObjectSteal(attr_o); } @@ -2608,11 +2644,11 @@ dummy_func( assert((oparg >> 5) <= Py_GE); PyObject *res_o = PyObject_RichCompare(left_o, right_o, oparg >> 5); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); if (oparg & 16) { int res_bool = PyObject_IsTrue(res_o); Py_DECREF(res_o); - ERROR_IF(res_bool < 0, error); + ERROR_IF(res_bool < 0); res = res_bool ? PyStackRef_True : PyStackRef_False; } else { @@ -2706,7 +2742,7 @@ dummy_func( int res = PySequence_Contains(right_o, left_o); DECREF_INPUTS(); - ERROR_IF(res < 0, error); + ERROR_IF(res < 0); b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; } @@ -2740,7 +2776,7 @@ dummy_func( // Note: both set and frozenset use the same seq_contains method! int res = _PySet_Contains((PySetObject *)right_o, left_o); DECREF_INPUTS(); - ERROR_IF(res < 0, error); + ERROR_IF(res < 0); b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; } @@ -2754,7 +2790,7 @@ dummy_func( STAT_INC(CONTAINS_OP, hit); int res = PyDict_Contains(right_o, left_o); DECREF_INPUTS(); - ERROR_IF(res < 0, error); + ERROR_IF(res < 0); b = (res ^ oparg) ? PyStackRef_True : PyStackRef_False; } @@ -2764,7 +2800,7 @@ dummy_func( int err = _PyEval_CheckExceptStarTypeValid(tstate, match_type); if (err < 0) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *match_o = NULL; @@ -2772,10 +2808,10 @@ dummy_func( int res = _PyEval_ExceptionGroupMatch(frame, exc_value, match_type, &match_o, &rest_o); DECREF_INPUTS(); - ERROR_IF(res < 0, error); + ERROR_IF(res < 0); assert((match_o == NULL) == (rest_o == NULL)); - ERROR_IF(match_o == NULL, error); + ERROR_IF(match_o == NULL); if (!Py_IsNone(match_o)) { PyErr_SetHandledException(match_o); @@ -2805,14 +2841,14 @@ dummy_func( PyStackRef_AsPyObjectBorrow(fromlist), PyStackRef_AsPyObjectBorrow(level)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } inst(IMPORT_FROM, (from -- from, res)) { PyObject *name = GETITEM(FRAME_CO_NAMES, oparg); PyObject *res_o = _PyEval_ImportFrom(tstate, PyStackRef_AsPyObjectBorrow(from), name); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -2850,7 +2886,7 @@ dummy_func( int optimized = _PyOptimizer_Optimize(frame, start, &executor, 0); if (optimized <= 0) { this_instr[1].counter = restart_backoff_counter(counter); - ERROR_IF(optimized < 0, error); + ERROR_IF(optimized < 0); } else { this_instr[1].counter = initial_jump_backoff_counter(); @@ -2976,9 +3012,9 @@ dummy_func( inst(GET_LEN, (obj -- obj, len)) { // PUSH(len(TOS)) Py_ssize_t len_i = PyObject_Length(PyStackRef_AsPyObjectBorrow(obj)); - ERROR_IF(len_i < 0, error); + ERROR_IF(len_i < 0); PyObject *len_o = PyLong_FromSsize_t(len_i); - ERROR_IF(len_o == NULL, error); + ERROR_IF(len_o == NULL); len = PyStackRef_FromPyObjectSteal(len_o); } @@ -2996,7 +3032,7 @@ dummy_func( attrs = PyStackRef_FromPyObjectSteal(attrs_o); } else { - ERROR_IF(_PyErr_Occurred(tstate), error); // Error! + ERROR_IF(_PyErr_Occurred(tstate)); // Error! attrs = PyStackRef_None; // Failure! } } @@ -3015,7 +3051,7 @@ dummy_func( // On successful match, PUSH(values). Otherwise, PUSH(None). PyObject *values_or_none_o = _PyEval_MatchKeys(tstate, PyStackRef_AsPyObjectBorrow(subject), PyStackRef_AsPyObjectBorrow(keys)); - ERROR_IF(values_or_none_o == NULL, error); + ERROR_IF(values_or_none_o == NULL); values_or_none = PyStackRef_FromPyObjectSteal(values_or_none_o); } @@ -3026,7 +3062,7 @@ dummy_func( /* before: [obj]; after [getiter(obj)] */ PyObject *iter_o = PyObject_GetIter(PyStackRef_AsPyObjectBorrow(iterable)); PyStackRef_CLOSE(iterable); - ERROR_IF(iter_o == NULL, error); + ERROR_IF(iter_o == NULL); iter = PyStackRef_FromPyObjectSteal(iter_o); } @@ -3377,7 +3413,7 @@ dummy_func( r->start = value + r->step; r->len--; PyObject *res = PyLong_FromLong(value); - ERROR_IF(res == NULL, error); + ERROR_IF(res == NULL); next = PyStackRef_FromPyObjectSteal(res); } @@ -3470,7 +3506,7 @@ dummy_func( PyObject *res_o = PyObject_Vectorcall(exit_func_o, stack + 2 - has_self, (3 + has_self) | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); Py_XDECREF(original_tb); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3704,7 +3740,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, @@ -3730,7 +3766,7 @@ dummy_func( } assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -3752,7 +3788,7 @@ dummy_func( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, function, arg0 ); - ERROR_IF(err, error); + ERROR_IF(err); } macro(CALL) = _SPECIALIZE_CALL + unused/2 + _MAYBE_EXPAND_METHOD + _DO_CALL + _CHECK_PERIODIC; @@ -3857,7 +3893,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, @@ -3866,7 +3902,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4009,7 +4045,7 @@ dummy_func( (void)callable; // Silence compiler warnings about unused variables (void)null; PyStackRef_CLOSE(arg); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4037,7 +4073,7 @@ dummy_func( (void)callable; // Silence compiler warnings about unused variables (void)null; PyStackRef_CLOSE(arg); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4130,12 +4166,12 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *res_o = tp->tp_vectorcall((PyObject *)tp, args_o, total_args, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4170,7 +4206,7 @@ dummy_func( DEAD(args); DEAD(self_or_null); PyStackRef_CLOSE(callable); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4198,7 +4234,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *res_o = _PyCFunctionFast_CAST(cfunc)( PyCFunction_GET_SELF(callable_o), @@ -4207,7 +4243,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4237,13 +4273,13 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *res_o = cfunc(PyCFunction_GET_SELF(callable_o), args_o, total_args, NULL); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4325,7 +4361,7 @@ dummy_func( UNLOCK_OBJECT(self_o); PyStackRef_CLOSE(self); PyStackRef_CLOSE(callable); - ERROR_IF(err, error); + ERROR_IF(err); #if TIER_ONE // Skip the following POP_TOP. This is done here in tier one, and // during trace projection in tier two: @@ -4363,7 +4399,7 @@ dummy_func( _Py_LeaveRecursiveCallTstate(tstate); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4397,7 +4433,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyCFunctionFastWithKeywords cfunc = _PyCFunctionFastWithKeywords_CAST(meth->ml_meth); @@ -4405,7 +4441,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4443,7 +4479,7 @@ dummy_func( DEAD(args); DEAD(self_or_null); PyStackRef_CLOSE(callable); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4477,14 +4513,14 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyCFunctionFast cfunc = _PyCFunctionFast_CAST(meth->ml_meth); PyObject *res_o = cfunc(self, (args_o + 1), nargs); STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4517,7 +4553,7 @@ dummy_func( int err = _Py_call_instrumentation_2args( tstate, PY_MONITORING_EVENT_CALL, frame, this_instr, function, arg); - ERROR_IF(err, error); + ERROR_IF(err); } op(_MAYBE_EXPAND_METHOD_KW, (callable, self_or_null, unused[oparg], unused -- callable, self_or_null, unused[oparg], unused)) { @@ -4574,7 +4610,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *res_o = PyObject_Vectorcall( callable_o, args_o, @@ -4599,7 +4635,7 @@ dummy_func( } } DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4629,7 +4665,7 @@ dummy_func( DEAD(self_or_null); DEAD(callable); SYNC_SP(); - ERROR_IF(temp == NULL, error); + ERROR_IF(temp == NULL); new_frame = temp; } @@ -4727,7 +4763,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o); if (CONVERSION_FAILED(args_o)) { DECREF_INPUTS(); - ERROR_IF(true, error); + ERROR_IF(true); } PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames); int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o); @@ -4739,7 +4775,7 @@ dummy_func( STACKREFS_TO_PYOBJECTS_CLEANUP(args_o); assert((res_o != NULL) ^ (_PyErr_Occurred(tstate) != NULL)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -4842,7 +4878,7 @@ dummy_func( PyStackRef_CLOSE(callargs_st); DEAD(null); PyStackRef_CLOSE(func_st); - ERROR_IF(result_o == NULL, error); + ERROR_IF(result_o == NULL); result = PyStackRef_FromPyObjectSteal(result_o); } @@ -4863,7 +4899,7 @@ dummy_func( PyFunction_New(codeobj, GLOBALS()); PyStackRef_CLOSE(codeobj_st); - ERROR_IF(func_obj == NULL, error); + ERROR_IF(func_obj == NULL); _PyFunction_SetVersion( func_obj, ((PyCodeObject *)codeobj)->co_version); @@ -4887,7 +4923,7 @@ dummy_func( assert(PyStackRef_FunctionCheck(frame->f_funcobj)); PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj); PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func); - ERROR_IF(gen == NULL, error); + ERROR_IF(gen == NULL); assert(STACK_LEVEL() == 0); SAVE_STACK(); _PyInterpreterFrame *gen_frame = &gen->gi_iframe; @@ -4912,7 +4948,7 @@ dummy_func( PyObject *step_o = oparg == 3 ? PyStackRef_AsPyObjectBorrow(args[2]) : NULL; PyObject *slice_o = PySlice_New(start_o, stop_o, step_o); DECREF_INPUTS(); - ERROR_IF(slice_o == NULL, error); + ERROR_IF(slice_o == NULL); slice = PyStackRef_FromPyObjectStealMortal(slice_o); } @@ -4922,7 +4958,7 @@ dummy_func( conv_fn = _PyEval_ConversionFuncs[oparg]; PyObject *result_o = conv_fn(PyStackRef_AsPyObjectBorrow(value)); PyStackRef_CLOSE(value); - ERROR_IF(result_o == NULL, error); + ERROR_IF(result_o == NULL); result = PyStackRef_FromPyObjectSteal(result_o); } @@ -4933,7 +4969,7 @@ dummy_func( if (!PyUnicode_CheckExact(value_o)) { PyObject *res_o = PyObject_Format(value_o, NULL); PyStackRef_CLOSE(value); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } else { @@ -4945,7 +4981,7 @@ dummy_func( inst(FORMAT_WITH_SPEC, (value, fmt_spec -- res)) { PyObject *res_o = PyObject_Format(PyStackRef_AsPyObjectBorrow(value), PyStackRef_AsPyObjectBorrow(fmt_spec)); DECREF_INPUTS(); - ERROR_IF(res_o == NULL, error); + ERROR_IF(res_o == NULL); res = PyStackRef_FromPyObjectSteal(res_o); } @@ -5024,7 +5060,7 @@ dummy_func( inst(INSTRUMENTED_INSTRUCTION, ( -- )) { int next_opcode = _Py_call_instrumentation_instruction( tstate, frame, this_instr); - ERROR_IF(next_opcode < 0, error); + ERROR_IF(next_opcode < 0); next_instr = this_instr; if (_PyOpcode_Caches[next_opcode]) { PAUSE_ADAPTIVE_COUNTER(next_instr[1].counter); @@ -5296,18 +5332,6 @@ dummy_func( assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version)); } - label(pop_4_error) { - stack_pointer -= 4; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } - - label(pop_3_error) { - stack_pointer -= 3; - assert(WITHIN_STACK_BOUNDS()); - goto error; - } - label(pop_2_error) { stack_pointer -= 2; assert(WITHIN_STACK_BOUNDS()); diff --git a/Python/ceval.c b/Python/ceval.c index 19a1c9529dd..4a75b60c9f0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -19,6 +19,7 @@ #include "pycore_import.h" // _PyImport_IsDefaultImportFunc() #include "pycore_instruments.h" #include "pycore_interpframe.h" // _PyFrame_SetStackPointer() +#include "pycore_interpolation.h" // _PyInterpolation_Build() #include "pycore_intrinsics.h" #include "pycore_jit.h" #include "pycore_list.h" // _PyList_GetItemRef() @@ -36,6 +37,7 @@ #include "pycore_setobject.h" // _PySet_Update() #include "pycore_sliceobject.h" // _PyBuildSlice_ConsumeRefs #include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString() +#include "pycore_template.h" // _PyTemplate_Build() #include "pycore_traceback.h" // _PyTraceBack_FromFrame #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "pycore_uop_ids.h" // Uops @@ -480,12 +482,6 @@ _Py_CheckRecursiveCall(PyThreadState *tstate, const char *where) _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; uintptr_t here_addr = _Py_get_machine_stack_pointer(); assert(_tstate->c_stack_soft_limit != 0); - if (_tstate->c_stack_hard_limit == 0) { - _Py_InitializeRecursionLimits(tstate); - } - if (here_addr >= _tstate->c_stack_soft_limit) { - return 0; - } assert(_tstate->c_stack_hard_limit != 0); if (here_addr < _tstate->c_stack_hard_limit) { /* Overflowing while handling an overflow. Give up. */ diff --git a/Python/codecs.c b/Python/codecs.c index 265f5214e5b..caf8d9d5f3c 100644 --- a/Python/codecs.c +++ b/Python/codecs.c @@ -540,11 +540,19 @@ PyObject * _PyCodec_LookupTextEncoding(const char *encoding, Py_DECREF(attr); if (is_text_codec <= 0) { Py_DECREF(codec); - if (!is_text_codec) - PyErr_Format(PyExc_LookupError, - "'%.400s' is not a text encoding; " - "use %s to handle arbitrary codecs", - encoding, alternate_command); + if (!is_text_codec) { + if (alternate_command != NULL) { + PyErr_Format(PyExc_LookupError, + "'%.400s' is not a text encoding; " + "use %s to handle arbitrary codecs", + encoding, alternate_command); + } + else { + PyErr_Format(PyExc_LookupError, + "'%.400s' is not a text encoding", + encoding); + } + } return NULL; } } diff --git a/Python/codegen.c b/Python/codegen.c index a7e412f7032..c7662538408 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -3607,7 +3607,9 @@ infer_type(expr_ty e) case Lambda_kind: return &PyFunction_Type; case JoinedStr_kind: + case TemplateStr_kind: case FormattedValue_kind: + case Interpolation_kind: return &PyUnicode_Type; case Constant_kind: return Py_TYPE(e->v.Constant.value); @@ -3630,7 +3632,9 @@ check_caller(compiler *c, expr_ty e) case SetComp_kind: case GeneratorExp_kind: case JoinedStr_kind: - case FormattedValue_kind: { + case TemplateStr_kind: + case FormattedValue_kind: + case Interpolation_kind: { location loc = LOC(e); return _PyCompile_Warn(c, loc, "'%.200s' object is not callable; " "perhaps you missed a comma?", @@ -3693,7 +3697,9 @@ check_index(compiler *c, expr_ty e, expr_ty s) case List_kind: case ListComp_kind: case JoinedStr_kind: - case FormattedValue_kind: { + case TemplateStr_kind: + case FormattedValue_kind: + case Interpolation_kind: { location loc = LOC(e); return _PyCompile_Warn(c, loc, "%.200s indices must be integers " "or slices, not %.200s; " @@ -4044,6 +4050,59 @@ codegen_call(compiler *c, expr_ty e) } static int +codegen_template_str(compiler *c, expr_ty e) +{ + location loc = LOC(e); + expr_ty value; + + Py_ssize_t value_count = asdl_seq_LEN(e->v.TemplateStr.values); + int last_was_interpolation = 1; + Py_ssize_t stringslen = 0; + for (Py_ssize_t i = 0; i < value_count; i++) { + value = asdl_seq_GET(e->v.TemplateStr.values, i); + if (value->kind == Interpolation_kind) { + if (last_was_interpolation) { + ADDOP_LOAD_CONST(c, loc, Py_NewRef(&_Py_STR(empty))); + stringslen++; + } + last_was_interpolation = 1; + } + else { + VISIT(c, expr, value); + Py_ssize_t j; + for (j = i + 1; j < value_count; j++) { + value = asdl_seq_GET(e->v.TemplateStr.values, j); + if (value->kind == Interpolation_kind) { + break; + } + VISIT(c, expr, value); + ADDOP_INPLACE(c, loc, Add); + } + i = j - 1; + stringslen++; + last_was_interpolation = 0; + } + } + if (last_was_interpolation) { + ADDOP_LOAD_CONST(c, loc, Py_NewRef(&_Py_STR(empty))); + stringslen++; + } + ADDOP_I(c, loc, BUILD_TUPLE, stringslen); + + Py_ssize_t interpolationslen = 0; + for (Py_ssize_t i = 0; i < value_count; i++) { + value = asdl_seq_GET(e->v.TemplateStr.values, i); + if (value->kind == Interpolation_kind) { + VISIT(c, expr, value); + interpolationslen++; + } + } + ADDOP_I(c, loc, BUILD_TUPLE, interpolationslen); + ADDOP(c, loc, BUILD_TEMPLATE); + return SUCCESS; +} + +static int codegen_joined_str(compiler *c, expr_ty e) { location loc = LOC(e); @@ -4072,24 +4131,41 @@ codegen_joined_str(compiler *c, expr_ty e) return SUCCESS; } -/* Used to implement f-strings. Format a single value. */ static int -codegen_formatted_value(compiler *c, expr_ty e) +codegen_interpolation(compiler *c, expr_ty e) { - /* Our oparg encodes 2 pieces of information: the conversion - character, and whether or not a format_spec was provided. + location loc = LOC(e); - Convert the conversion char to 3 bits: - : 000 0x0 FVC_NONE The default if nothing specified. - !s : 001 0x1 FVC_STR - !r : 010 0x2 FVC_REPR - !a : 011 0x3 FVC_ASCII + VISIT(c, expr, e->v.Interpolation.value); + ADDOP_LOAD_CONST(c, loc, e->v.Interpolation.str); - next bit is whether or not we have a format spec: - yes : 100 0x4 - no : 000 0x0 - */ + int oparg = 2; + if (e->v.Interpolation.format_spec) { + oparg++; + VISIT(c, expr, e->v.Interpolation.format_spec); + } + + int conversion = e->v.Interpolation.conversion; + if (conversion != -1) { + switch (conversion) { + case 's': oparg |= FVC_STR << 2; break; + case 'r': oparg |= FVC_REPR << 2; break; + case 'a': oparg |= FVC_ASCII << 2; break; + default: + PyErr_Format(PyExc_SystemError, + "Unrecognized conversion character %d", conversion); + return ERROR; + } + } + + ADDOP_I(c, loc, BUILD_INTERPOLATION, oparg); + return SUCCESS; +} +/* Used to implement f-strings. Format a single value. */ +static int +codegen_formatted_value(compiler *c, expr_ty e) +{ int conversion = e->v.FormattedValue.conversion; int oparg; @@ -5182,8 +5258,12 @@ codegen_visit_expr(compiler *c, expr_ty e) break; case JoinedStr_kind: return codegen_joined_str(c, e); + case TemplateStr_kind: + return codegen_template_str(c, e); case FormattedValue_kind: return codegen_formatted_value(c, e); + case Interpolation_kind: + return codegen_interpolation(c, e); /* The following exprs can be assignment targets. */ case Attribute_kind: if (e->v.Attribute.ctx == Load) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 4e57906c84a..b37a87542fb 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -2604,6 +2604,89 @@ break; } + case _BUILD_INTERPOLATION: { + _PyStackRef *format; + _PyStackRef str; + _PyStackRef value; + _PyStackRef interpolation; + oparg = CURRENT_OPARG(); + format = &stack_pointer[-(oparg & 1)]; + str = stack_pointer[-1 - (oparg & 1)]; + value = stack_pointer[-2 - (oparg & 1)]; + PyObject *value_o = PyStackRef_AsPyObjectBorrow(value); + PyObject *str_o = PyStackRef_AsPyObjectBorrow(str); + int conversion = oparg >> 2; + PyObject *format_o; + if (oparg & 1) { + format_o = PyStackRef_AsPyObjectBorrow(format[0]); + } + else { + format_o = &_Py_STR(empty); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *interpolation_o = _PyInterpolation_Build(value_o, str_o, conversion, format_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (oparg & 1) { + stack_pointer += -(oparg & 1); + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(format[0]); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + stack_pointer += -(oparg & 1); + } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(str); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (interpolation_o == NULL) { + JUMP_TO_ERROR(); + } + interpolation = PyStackRef_FromPyObjectSteal(interpolation_o); + stack_pointer[0] = interpolation; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _BUILD_TEMPLATE: { + _PyStackRef interpolations; + _PyStackRef strings; + _PyStackRef template; + interpolations = stack_pointer[-1]; + strings = stack_pointer[-2]; + PyObject *strings_o = PyStackRef_AsPyObjectBorrow(strings); + PyObject *interpolations_o = PyStackRef_AsPyObjectBorrow(interpolations); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *template_o = _PyTemplate_Build(strings_o, interpolations_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(interpolations); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(strings); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (template_o == NULL) { + JUMP_TO_ERROR(); + } + template = PyStackRef_FromPyObjectSteal(template_o); + stack_pointer[0] = template; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + case _BUILD_TUPLE: { _PyStackRef *values; _PyStackRef tup; diff --git a/Python/gc.c b/Python/gc.c index 58224acff2c..b7b48c8af39 100644 --- a/Python/gc.c +++ b/Python/gc.c @@ -2207,9 +2207,8 @@ void PyObject_GC_UnTrack(void *op_raw) { PyObject *op = _PyObject_CAST(op_raw); - /* Obscure: the Py_TRASHCAN mechanism requires that we be able to - * call PyObject_GC_UnTrack twice on an object. - */ + /* The code for some objects, such as tuples, is a bit + * sloppy about when the object is tracked and untracked. */ if (_PyObject_GC_IS_TRACKED(op)) { _PyObject_GC_UNTRACK(op); } diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index d22307ae4ff..2db75e0fd41 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -2511,9 +2511,8 @@ void PyObject_GC_UnTrack(void *op_raw) { PyObject *op = _PyObject_CAST(op_raw); - /* Obscure: the Py_TRASHCAN mechanism requires that we be able to - * call PyObject_GC_UnTrack twice on an object. - */ + /* The code for some objects, such as tuples, is a bit + * sloppy about when the object is tracked and untracked. */ if (_PyObject_GC_IS_TRACKED(op)) { _PyObject_GC_UNTRACK(op); } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 7d3e6c7cbc9..6841fbcc22e 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1088,6 +1088,64 @@ DISPATCH(); } + TARGET(BUILD_INTERPOLATION) { + #if Py_TAIL_CALL_INTERP + int opcode = BUILD_INTERPOLATION; + (void)(opcode); + #endif + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BUILD_INTERPOLATION); + _PyStackRef value; + _PyStackRef str; + _PyStackRef *format; + _PyStackRef interpolation; + format = &stack_pointer[-(oparg & 1)]; + str = stack_pointer[-1 - (oparg & 1)]; + value = stack_pointer[-2 - (oparg & 1)]; + PyObject *value_o = PyStackRef_AsPyObjectBorrow(value); + PyObject *str_o = PyStackRef_AsPyObjectBorrow(str); + int conversion = oparg >> 2; + PyObject *format_o; + if (oparg & 1) { + format_o = PyStackRef_AsPyObjectBorrow(format[0]); + } + else { + format_o = &_Py_STR(empty); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *interpolation_o = _PyInterpolation_Build(value_o, str_o, conversion, format_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (oparg & 1) { + stack_pointer += -(oparg & 1); + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(format[0]); + stack_pointer = _PyFrame_GetStackPointer(frame); + } + else { + stack_pointer += -(oparg & 1); + } + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(str); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(value); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (interpolation_o == NULL) { + JUMP_TO_LABEL(error); + } + interpolation = PyStackRef_FromPyObjectSteal(interpolation_o); + stack_pointer[0] = interpolation; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + DISPATCH(); + } + TARGET(BUILD_LIST) { #if Py_TAIL_CALL_INTERP int opcode = BUILD_LIST; @@ -1303,6 +1361,44 @@ DISPATCH(); } + TARGET(BUILD_TEMPLATE) { + #if Py_TAIL_CALL_INTERP + int opcode = BUILD_TEMPLATE; + (void)(opcode); + #endif + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(BUILD_TEMPLATE); + _PyStackRef strings; + _PyStackRef interpolations; + _PyStackRef template; + interpolations = stack_pointer[-1]; + strings = stack_pointer[-2]; + PyObject *strings_o = PyStackRef_AsPyObjectBorrow(strings); + PyObject *interpolations_o = PyStackRef_AsPyObjectBorrow(interpolations); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyObject *template_o = _PyTemplate_Build(strings_o, interpolations_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(interpolations); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(strings); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (template_o == NULL) { + JUMP_TO_LABEL(error); + } + template = PyStackRef_FromPyObjectSteal(template_o); + stack_pointer[0] = template; + stack_pointer += 1; + assert(WITHIN_STACK_BOUNDS()); + DISPATCH(); + } + TARGET(BUILD_TUPLE) { #if Py_TAIL_CALL_INTERP int opcode = BUILD_TUPLE; @@ -7464,9 +7560,6 @@ PyObject *result = PyStackRef_AsPyObjectSteal(retval); LLTRACE_RESUME_FRAME(); return result; - stack_pointer += -1; - assert(WITHIN_STACK_BOUNDS()); - DISPATCH(); } TARGET(IS_OP) { @@ -12137,20 +12230,6 @@ JUMP_TO_LABEL(error); #endif /* Py_TAIL_CALL_INTERP */ /* BEGIN LABELS */ - LABEL(pop_4_error) - { - stack_pointer -= 4; - assert(WITHIN_STACK_BOUNDS()); - JUMP_TO_LABEL(error); - } - - LABEL(pop_3_error) - { - stack_pointer -= 3; - assert(WITHIN_STACK_BOUNDS()); - JUMP_TO_LABEL(error); - } - LABEL(pop_2_error) { stack_pointer -= 2; diff --git a/Python/hamt.c b/Python/hamt.c index e4d1e1663dd..f9bbf63961d 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -1118,7 +1118,6 @@ hamt_node_bitmap_dealloc(PyObject *self) } PyObject_GC_UnTrack(self); - Py_TRASHCAN_BEGIN(self, hamt_node_bitmap_dealloc) if (len > 0) { i = len; @@ -1128,7 +1127,6 @@ hamt_node_bitmap_dealloc(PyObject *self) } Py_TYPE(self)->tp_free(self); - Py_TRASHCAN_END } #ifdef Py_DEBUG @@ -1508,7 +1506,6 @@ hamt_node_collision_dealloc(PyObject *self) /* Collision's tp_dealloc */ Py_ssize_t len = Py_SIZE(self); PyObject_GC_UnTrack(self); - Py_TRASHCAN_BEGIN(self, hamt_node_collision_dealloc) if (len > 0) { PyHamtNode_Collision *node = _PyHamtNode_Collision_CAST(self); while (--len >= 0) { @@ -1516,7 +1513,6 @@ hamt_node_collision_dealloc(PyObject *self) } } Py_TYPE(self)->tp_free(self); - Py_TRASHCAN_END } #ifdef Py_DEBUG @@ -1878,13 +1874,11 @@ hamt_node_array_dealloc(PyObject *self) { /* Array's tp_dealloc */ PyObject_GC_UnTrack(self); - Py_TRASHCAN_BEGIN(self, hamt_node_array_dealloc) PyHamtNode_Array *obj = _PyHamtNode_Array_CAST(self); for (Py_ssize_t i = 0; i < HAMT_ARRAY_NODE_SIZE; i++) { Py_XDECREF(obj->a_array[i]); } Py_TYPE(self)->tp_free(self); - Py_TRASHCAN_END } #ifdef Py_DEBUG diff --git a/Python/instruction_sequence.c b/Python/instruction_sequence.c index b068e4fa3db..e2db46b4893 100644 --- a/Python/instruction_sequence.c +++ b/Python/instruction_sequence.c @@ -419,10 +419,8 @@ inst_seq_dealloc(PyObject *op) { _PyInstructionSequence *seq = (_PyInstructionSequence *)op; PyObject_GC_UnTrack(seq); - Py_TRASHCAN_BEGIN(seq, inst_seq_dealloc) PyInstructionSequence_Fini(seq); PyObject_GC_Del(seq); - Py_TRASHCAN_END } static int diff --git a/Python/intrinsics.c b/Python/intrinsics.c index 1c7d7ee6c12..ff44ba0ee64 100644 --- a/Python/intrinsics.c +++ b/Python/intrinsics.c @@ -28,7 +28,6 @@ static PyObject * print_expr(PyThreadState* Py_UNUSED(ignored), PyObject *value) { PyObject *hook = _PySys_GetRequiredAttr(&_Py_ID(displayhook)); - // Can't use ERROR_IF here. if (hook == NULL) { return NULL; } diff --git a/Python/jit.c b/Python/jit.c index 8a91d2f62a4..e232cc1f7d9 100644 --- a/Python/jit.c +++ b/Python/jit.c @@ -12,6 +12,7 @@ #include "pycore_frame.h" #include "pycore_function.h" #include "pycore_interpframe.h" +#include "pycore_interpolation.h" #include "pycore_intrinsics.h" #include "pycore_list.h" #include "pycore_long.h" @@ -21,6 +22,7 @@ #include "pycore_pyerrors.h" #include "pycore_setobject.h" #include "pycore_sliceobject.h" +#include "pycore_template.h" #include "pycore_tuple.h" #include "pycore_unicodeobject.h" diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 5b9fb794c6b..8c2dfb46077 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -2,8 +2,9 @@ static void *opcode_targets[256] = { &&TARGET_CACHE, &&TARGET_BINARY_SLICE, - &&TARGET_CALL_FUNCTION_EX, + &&TARGET_BUILD_TEMPLATE, &&TARGET_BINARY_OP_INPLACE_ADD_UNICODE, + &&TARGET_CALL_FUNCTION_EX, &&TARGET_CHECK_EG_MATCH, &&TARGET_CHECK_EXC_MATCH, &&TARGET_CLEANUP_THROW, @@ -16,8 +17,8 @@ static void *opcode_targets[256] = { &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_GET_ITER, - &&TARGET_GET_LEN, &&TARGET_RESERVED, + &&TARGET_GET_LEN, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_INTERPRETER_EXIT, &&TARGET_LOAD_BUILD_CLASS, @@ -44,6 +45,7 @@ static void *opcode_targets[256] = { &&TARGET_UNARY_NOT, &&TARGET_WITH_EXCEPT_START, &&TARGET_BINARY_OP, + &&TARGET_BUILD_INTERPOLATION, &&TARGET_BUILD_LIST, &&TARGET_BUILD_MAP, &&TARGET_BUILD_SET, @@ -126,8 +128,6 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -260,8 +260,6 @@ static void *opcode_targets[256] = { #else /* Py_TAIL_CALL_INTERP */ static py_tail_call_funcptr INSTRUCTION_TABLE[256]; -Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_4_error(TAIL_CALL_PARAMS); -Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_3_error(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_2_error(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_pop_1_error(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_error(TAIL_CALL_PARAMS); @@ -285,11 +283,13 @@ Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBSCR_TUPLE_INT(TAIL_ Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBTRACT_FLOAT(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_OP_SUBTRACT_INT(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BINARY_SLICE(TAIL_CALL_PARAMS); +Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_INTERPOLATION(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_LIST(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_MAP(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_SET(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_SLICE(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_STRING(TAIL_CALL_PARAMS); +Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_TEMPLATE(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_BUILD_TUPLE(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CACHE(TAIL_CALL_PARAMS); Py_PRESERVE_NONE_CC static PyObject *_TAIL_CALL_CALL(TAIL_CALL_PARAMS); @@ -521,11 +521,13 @@ static py_tail_call_funcptr INSTRUCTION_TABLE[256] = { [BINARY_OP_SUBTRACT_FLOAT] = _TAIL_CALL_BINARY_OP_SUBTRACT_FLOAT, [BINARY_OP_SUBTRACT_INT] = _TAIL_CALL_BINARY_OP_SUBTRACT_INT, [BINARY_SLICE] = _TAIL_CALL_BINARY_SLICE, + [BUILD_INTERPOLATION] = _TAIL_CALL_BUILD_INTERPOLATION, [BUILD_LIST] = _TAIL_CALL_BUILD_LIST, [BUILD_MAP] = _TAIL_CALL_BUILD_MAP, [BUILD_SET] = _TAIL_CALL_BUILD_SET, [BUILD_SLICE] = _TAIL_CALL_BUILD_SLICE, [BUILD_STRING] = _TAIL_CALL_BUILD_STRING, + [BUILD_TEMPLATE] = _TAIL_CALL_BUILD_TEMPLATE, [BUILD_TUPLE] = _TAIL_CALL_BUILD_TUPLE, [CACHE] = _TAIL_CALL_CACHE, [CALL] = _TAIL_CALL_CALL, @@ -729,8 +731,6 @@ static py_tail_call_funcptr INSTRUCTION_TABLE[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, - [119] = _TAIL_CALL_UNKNOWN_OPCODE, - [120] = _TAIL_CALL_UNKNOWN_OPCODE, [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 679240b6efa..b8391c59aaf 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -1039,6 +1039,24 @@ break; } + case _BUILD_INTERPOLATION: { + JitOptSymbol *interpolation; + interpolation = sym_new_not_null(ctx); + stack_pointer[-2 - (oparg & 1)] = interpolation; + stack_pointer += -1 - (oparg & 1); + assert(WITHIN_STACK_BOUNDS()); + break; + } + + case _BUILD_TEMPLATE: { + JitOptSymbol *template; + template = sym_new_not_null(ctx); + stack_pointer[-2] = template; + stack_pointer += -1; + assert(WITHIN_STACK_BOUNDS()); + break; + } + case _BUILD_TUPLE: { JitOptSymbol **values; JitOptSymbol *tup; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 0871e147169..c4c1d9fd9e1 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -13,6 +13,7 @@ #include "pycore_freelist.h" // _PyObject_ClearFreeLists() #include "pycore_global_objects_fini_generated.h" // _PyStaticObjects_CheckRefcnt() #include "pycore_initconfig.h" // _PyStatus_OK() +#include "pycore_interpolation.h" // _PyInterpolation_InitTypes() #include "pycore_long.h" // _PyLong_InitTypes() #include "pycore_object.h" // _PyDebug_PrintTotalRefs() #include "pycore_obmalloc.h" // _PyMem_init_obmalloc() @@ -754,6 +755,11 @@ pycore_init_types(PyInterpreterState *interp) return status; } + status = _PyInterpolation_InitTypes(interp); + if (_PyStatus_EXCEPTION(status)) { + return status; + } + return _PyStatus_OK(); } @@ -848,6 +854,10 @@ error: static PyStatus pycore_interp_init(PyThreadState *tstate) { + _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; + if (_tstate->c_stack_hard_limit == 0) { + _Py_InitializeRecursionLimits(tstate); + } PyInterpreterState *interp = tstate->interp; PyStatus status; PyObject *sysmod = NULL; diff --git a/Python/pystate.c b/Python/pystate.c index b0c79ba9d3e..5685957b160 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -2168,7 +2168,10 @@ _PyThreadState_Attach(PyThreadState *tstate) if (current_fast_get() != NULL) { Py_FatalError("non-NULL old thread state"); } - + _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate; + if (_tstate->c_stack_hard_limit == 0) { + _Py_InitializeRecursionLimits(tstate); + } while (1) { _PyEval_AcquireLock(tstate); diff --git a/Python/symtable.c b/Python/symtable.c index 2f13f35072a..f633e281019 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -2510,9 +2510,17 @@ symtable_visit_expr(struct symtable *st, expr_ty e) if (e->v.FormattedValue.format_spec) VISIT(st, expr, e->v.FormattedValue.format_spec); break; + case Interpolation_kind: + VISIT(st, expr, e->v.Interpolation.value); + if (e->v.Interpolation.format_spec) + VISIT(st, expr, e->v.Interpolation.format_spec); + break; case JoinedStr_kind: VISIT_SEQ(st, expr, e->v.JoinedStr.values); break; + case TemplateStr_kind: + VISIT_SEQ(st, expr, e->v.TemplateStr.values); + break; case Constant_kind: /* Nothing to do here. */ break; diff --git a/Python/traceback.c b/Python/traceback.c index 0ac0b28201c..c06cb1a5908 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -236,11 +236,9 @@ tb_dealloc(PyObject *op) { PyTracebackObject *tb = _PyTracebackObject_CAST(op); PyObject_GC_UnTrack(tb); - Py_TRASHCAN_BEGIN(tb, tb_dealloc) Py_XDECREF(tb->tb_next); Py_XDECREF(tb->tb_frame); PyObject_GC_Del(tb); - Py_TRASHCAN_END } static int |