aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/codegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/codegen.c')
-rw-r--r--Python/codegen.c110
1 files changed, 95 insertions, 15 deletions
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) {