diff options
Diffstat (limited to 'Python/compile.c')
| -rw-r--r-- | Python/compile.c | 193 | 
1 files changed, 170 insertions, 23 deletions
| diff --git a/Python/compile.c b/Python/compile.c index 2c4f7d7b41..84b79a2fff 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;      } @@ -1309,7 +1314,11 @@ compiler_isdocstring(stmt_ty s)  {      if (s->kind != Expr_kind)          return 0; -    return s->v.Expr.value->kind == Str_kind; +    if (s->v.Expr.value->kind == Str_kind) +        return 1; +    if (s->v.Expr.value->kind == Constant_kind) +        return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value); +    return 0;  }  /* Compile a sequence of statements, checking for a docstring. */ @@ -1683,8 +1692,12 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)      st = (stmt_ty)asdl_seq_GET(body, 0);      docstring = compiler_isdocstring(st); -    if (docstring && c->c_optimize < 2) -        first_const = st->v.Expr.value->v.Str.s; +    if (docstring && c->c_optimize < 2) { +        if (st->v.Expr.value->kind == Constant_kind) +            first_const = st->v.Expr.value->v.Constant.value; +        else +            first_const = st->v.Expr.value->v.Str.s; +    }      if (compiler_add_o(c, c->u->u_consts, first_const) < 0)      {          compiler_exit_scope(c);          return 0; @@ -2595,6 +2608,55 @@ compiler_assert(struct compiler *c, stmt_ty s)  }  static int +compiler_visit_stmt_expr(struct compiler *c, expr_ty value) +{ +    if (c->c_interactive && c->c_nestlevel <= 1) { +        VISIT(c, expr, value); +        ADDOP(c, PRINT_EXPR); +        return 1; +    } + +    switch (value->kind) +    { +    case Str_kind: +    case Ellipsis_kind: +        /* Issue #26204: ignore string statement, but don't emit a +         * SyntaxWarning. Triple quoted strings is a common syntax for +         * multiline comments. +         * +         * Don't emit warning on "def f(): ..." neither. It's a legit syntax +         * for abstract function. */ +        return 1; + +    case Bytes_kind: +    case Num_kind: +    case NameConstant_kind: +    case Constant_kind: +    { +        PyObject *msg = PyUnicode_FromString("ignore constant statement"); +        if (msg == NULL) +            return 0; +        if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, +                                     msg, +                                     c->c_filename, c->u->u_lineno, +                                     NULL, NULL) == -1) { +            Py_DECREF(msg); +            return 0; +        } +        Py_DECREF(msg); +        return 1; +    } + +    default: +        break; +    } + +    VISIT(c, expr, value); +    ADDOP(c, POP_TOP); +    return 1; +} + +static int  compiler_visit_stmt(struct compiler *c, stmt_ty s)  {      Py_ssize_t i, n; @@ -2664,16 +2726,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)      case Nonlocal_kind:          break;      case Expr_kind: -        if (c->c_interactive && c->c_nestlevel <= 1) { -            VISIT(c, expr, s->v.Expr.value); -            ADDOP(c, PRINT_EXPR); -        } -        else if (s->v.Expr.value->kind != Str_kind && -                 s->v.Expr.value->kind != Num_kind) { -            VISIT(c, expr, s->v.Expr.value); -            ADDOP(c, POP_TOP); -        } -        break; +        return compiler_visit_stmt_expr(c, s->v.Expr.value);      case Pass_kind:          break;      case Break_kind: @@ -3169,6 +3222,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, @@ -3545,6 +3673,8 @@ expr_constant(struct compiler *c, expr_ty e)      switch (e->kind) {      case Ellipsis_kind:          return 1; +    case Constant_kind: +        return PyObject_IsTrue(e->v.Constant.value);      case Num_kind:          return PyObject_IsTrue(e->v.Num.n);      case Str_kind: @@ -3588,9 +3718,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   */ @@ -3832,12 +3962,19 @@ compiler_visit_expr(struct compiler *c, expr_ty e)          return compiler_compare(c, e);      case Call_kind:          return compiler_call(c, e); +    case Constant_kind: +        ADDOP_O(c, LOAD_CONST, e->v.Constant.value, consts); +        break;      case Num_kind:          ADDOP_O(c, LOAD_CONST, e->v.Num.n, consts);          break;      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; @@ -4329,7 +4466,6 @@ assemble_lnotab(struct assembler *a, struct instr *i)      d_lineno = i->i_lineno - a->a_lineno;      assert(d_bytecode >= 0); -    assert(d_lineno >= 0);      if(d_bytecode == 0 && d_lineno == 0)          return 1; @@ -4359,9 +4495,21 @@ assemble_lnotab(struct assembler *a, struct instr *i)          d_bytecode -= ncodes * 255;          a->a_lnotab_off += ncodes * 2;      } -    assert(d_bytecode <= 255); -    if (d_lineno > 255) { -        int j, nbytes, ncodes = d_lineno / 255; +    assert(0 <= d_bytecode && d_bytecode <= 255); + +    if (d_lineno < -128 || 127 < d_lineno) { +        int j, nbytes, ncodes, k; +        if (d_lineno < 0) { +            k = -128; +            /* use division on positive numbers */ +            ncodes = (-d_lineno) / 128; +        } +        else { +            k = 127; +            ncodes = d_lineno / 127; +        } +        d_lineno -= ncodes * k; +        assert(ncodes >= 1);          nbytes = a->a_lnotab_off + 2 * ncodes;          len = PyBytes_GET_SIZE(a->a_lnotab);          if (nbytes >= len) { @@ -4379,15 +4527,15 @@ assemble_lnotab(struct assembler *a, struct instr *i)          lnotab = (unsigned char *)                     PyBytes_AS_STRING(a->a_lnotab) + a->a_lnotab_off;          *lnotab++ = d_bytecode; -        *lnotab++ = 255; +        *lnotab++ = k;          d_bytecode = 0;          for (j = 1; j < ncodes; j++) {              *lnotab++ = 0; -            *lnotab++ = 255; +            *lnotab++ = k;          } -        d_lineno -= ncodes * 255;          a->a_lnotab_off += ncodes * 2;      } +    assert(-128 <= d_lineno && d_lineno <= 127);      len = PyBytes_GET_SIZE(a->a_lnotab);      if (a->a_lnotab_off + 2 >= len) { @@ -4745,4 +4893,3 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags,  {      return PyAST_CompileEx(mod, filename, flags, -1, arena);  } - | 
