mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-132661: Implement PEP 750 (#132662)
Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com> Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com> Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> Co-authored-by: Wingy <git@wingysam.xyz> Co-authored-by: Koudai Aono <koxudaxi@gmail.com> Co-authored-by: Dave Peck <davepeck@gmail.com> Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu> Co-authored-by: Paul Everitt <pauleveritt@me.com> Co-authored-by: sobolevn <mail@sobolevn.me>
This commit is contained in:
parent
5ea9010e89
commit
60202609a2
81 changed files with 7716 additions and 3761 deletions
349
Python/Python-ast.c
generated
349
Python/Python-ast.c
generated
|
@ -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)");
|
||||
|
@ -8038,6 +8160,37 @@ _PyAST_FormattedValue(expr_ty value, int conversion, expr_ty format_spec, int
|
|||
return p;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -8055,6 +8208,23 @@ _PyAST_JoinedStr(asdl_expr_seq * values, int lineno, int col_offset, int
|
|||
return p;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
13
Python/ast.c
13
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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
@ -654,11 +662,99 @@ build_fstring_body(asdl_expr_seq *values, bool is_format_spec)
|
|||
return PyUnicodeWriter_Finish(body_writer);
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
@ -1903,6 +1905,40 @@ dummy_func(
|
|||
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) {
|
||||
|
|
|
@ -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
|
||||
|
|
112
Python/codegen.c
112
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; "
|
||||
|
@ -4043,6 +4049,59 @@ codegen_call(compiler *c, expr_ty e)
|
|||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -4072,24 +4131,41 @@ codegen_joined_str(compiler *c, expr_ty e)
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
codegen_interpolation(compiler *c, expr_ty e)
|
||||
{
|
||||
location loc = LOC(e);
|
||||
|
||||
VISIT(c, expr, e->v.Interpolation.value);
|
||||
ADDOP_LOAD_CONST(c, loc, e->v.Interpolation.str);
|
||||
|
||||
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)
|
||||
{
|
||||
/* Our oparg encodes 2 pieces of information: the conversion
|
||||
character, and whether or not a format_spec was provided.
|
||||
|
||||
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
|
||||
|
||||
next bit is whether or not we have a format spec:
|
||||
yes : 100 0x4
|
||||
no : 000 0x0
|
||||
*/
|
||||
|
||||
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) {
|
||||
|
|
83
Python/executor_cases.c.h
generated
83
Python/executor_cases.c.h
generated
|
@ -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;
|
||||
|
|
96
Python/generated_cases.c.h
generated
96
Python/generated_cases.c.h
generated
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
14
Python/opcode_targets.h
generated
14
Python/opcode_targets.h
generated
|
@ -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,
|
||||
|
@ -285,11 +285,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 +523,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 +733,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,
|
||||
|
|
18
Python/optimizer_cases.c.h
generated
18
Python/optimizer_cases.c.h
generated
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue