diff options
Diffstat (limited to 'Python/compile.c')
| -rw-r--r-- | Python/compile.c | 89 | 
1 files changed, 86 insertions, 3 deletions
| diff --git a/Python/compile.c b/Python/compile.c index 7631f4e..0f619c4 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -731,6 +731,7 @@ compiler_set_qualname(struct compiler *c)      return 1;  } +  /* Allocate a new block and return a pointer to it.     Returns NULL on error.  */ @@ -1066,6 +1067,10 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)              return 1;          case GET_YIELD_FROM_ITER:              return 0; +        case FORMAT_VALUE: +            /* If there's a fmt_spec on the stack, we go from 2->1, +               else 1->1. */ +            return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0;          default:              return PY_INVALID_STACK_EFFECT;      } @@ -3208,6 +3213,81 @@ compiler_call(struct compiler *c, expr_ty e)                                  e->v.Call.keywords);  } +static int +compiler_joined_str(struct compiler *c, expr_ty e) +{ +    /* Concatenate parts of a string using ''.join(parts). There are +       probably better ways of doing this. + +       This is used for constructs like "'x=' f'{42}'", which have to +       be evaluated at compile time. */ + +    static PyObject *empty_string; +    static PyObject *join_string; + +    if (!empty_string) { +        empty_string = PyUnicode_FromString(""); +        if (!empty_string) +            return 0; +    } +    if (!join_string) { +        join_string = PyUnicode_FromString("join"); +        if (!join_string) +            return 0; +    } + +    ADDOP_O(c, LOAD_CONST, empty_string, consts); +    ADDOP_NAME(c, LOAD_ATTR, join_string, names); +    VISIT_SEQ(c, expr, e->v.JoinedStr.values); +    ADDOP_I(c, BUILD_LIST, asdl_seq_LEN(e->v.JoinedStr.values)); +    ADDOP_I(c, CALL_FUNCTION, 1); +    return 1; +} + +/* Used to implement f-strings. Format a single value. */ +static int +compiler_formatted_value(struct 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 2 bits: +       None: 000  0x0  FVC_NONE +       !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 oparg; + +    /* Evaluate the expression to be formatted. */ +    VISIT(c, expr, e->v.FormattedValue.value); + +    switch (e->v.FormattedValue.conversion) { +    case 's': oparg = FVC_STR;   break; +    case 'r': oparg = FVC_REPR;  break; +    case 'a': oparg = FVC_ASCII; break; +    case -1:  oparg = FVC_NONE;  break; +    default: +        PyErr_SetString(PyExc_SystemError, +                        "Unrecognized conversion character"); +        return 0; +    } +    if (e->v.FormattedValue.format_spec) { +        /* Evaluate the format spec, and update our opcode arg. */ +        VISIT(c, expr, e->v.FormattedValue.format_spec); +        oparg |= FVS_HAVE_SPEC; +    } + +    /* And push our opcode and oparg */ +    ADDOP_I(c, FORMAT_VALUE, oparg); +    return 1; +} +  /* shared code between compiler_call and compiler_class */  static int  compiler_call_helper(struct compiler *c, @@ -3627,9 +3707,9 @@ expr_constant(struct compiler *c, expr_ty e)         BLOCK     finally:         if an exception was raised: -       exc = copy of (exception, instance, traceback) +           exc = copy of (exception, instance, traceback)         else: -       exc = (None, None, None) +           exc = (None, None, None)         if not (await exit(*exc)):             raise   */ @@ -3877,6 +3957,10 @@ compiler_visit_expr(struct compiler *c, expr_ty e)      case Str_kind:          ADDOP_O(c, LOAD_CONST, e->v.Str.s, consts);          break; +    case JoinedStr_kind: +        return compiler_joined_str(c, e); +    case FormattedValue_kind: +        return compiler_formatted_value(c, e);      case Bytes_kind:          ADDOP_O(c, LOAD_CONST, e->v.Bytes.s, consts);          break; @@ -4783,4 +4867,3 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags,  {      return PyAST_CompileEx(mod, filename, flags, -1, arena);  } - | 
