summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c220
1 files changed, 167 insertions, 53 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 2c4f7d7..e86b293 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -171,7 +171,6 @@ static int compiler_addop(struct compiler *, int);
static int compiler_addop_o(struct compiler *, int, PyObject *, PyObject *);
static int compiler_addop_i(struct compiler *, int, Py_ssize_t);
static int compiler_addop_j(struct compiler *, int, basicblock *, int);
-static basicblock *compiler_use_new_block(struct compiler *);
static int compiler_error(struct compiler *, const char *);
static int compiler_nameop(struct compiler *, identifier, expr_context_ty);
@@ -523,6 +522,7 @@ compiler_enter_scope(struct compiler *c, identifier name,
int scope_type, void *key, int lineno)
{
struct compiler_unit *u;
+ basicblock *block;
u = (struct compiler_unit *)PyObject_Malloc(sizeof(
struct compiler_unit));
@@ -620,8 +620,11 @@ compiler_enter_scope(struct compiler *c, identifier name,
c->u = u;
c->c_nestlevel++;
- if (compiler_use_new_block(c) == NULL)
+
+ block = compiler_new_block(c);
+ if (block == NULL)
return 0;
+ c->u->u_curblock = block;
if (u->u_scope_type != COMPILER_SCOPE_MODULE) {
if (!compiler_set_qualname(c))
@@ -731,6 +734,7 @@ compiler_set_qualname(struct compiler *c)
return 1;
}
+
/* Allocate a new block and return a pointer to it.
Returns NULL on error.
*/
@@ -755,16 +759,6 @@ compiler_new_block(struct compiler *c)
}
static basicblock *
-compiler_use_new_block(struct compiler *c)
-{
- basicblock *block = compiler_new_block(c);
- if (block == NULL)
- return NULL;
- c->u->u_curblock = block;
- return block;
-}
-
-static basicblock *
compiler_next_block(struct compiler *c)
{
basicblock *block = compiler_new_block(c);
@@ -1066,6 +1060,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;
}
@@ -1165,10 +1163,14 @@ compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg)
struct instr *i;
int off;
- /* Integer arguments are limit to 16-bit. There is an extension for 32-bit
- integer arguments. */
- assert((-2147483647-1) <= oparg);
- assert(oparg <= 2147483647);
+ /* oparg value is unsigned, but a signed C int is usually used to store
+ it in the C code (like Python/ceval.c).
+
+ Limit to 32-bit signed C int (rather than INT_MAX) for portability.
+
+ The argument of a concrete bytecode instruction is limited to 16-bit.
+ EXTENDED_ARG is used for 32-bit arguments. */
+ assert(0 <= oparg && oparg <= 2147483647);
off = compiler_next_instr(c, c->u->u_curblock);
if (off < 0)
@@ -1203,22 +1205,12 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute)
return 1;
}
-/* The distinction between NEW_BLOCK and NEXT_BLOCK is subtle. (I'd
- like to find better names.) NEW_BLOCK() creates a new block and sets
- it as the current block. NEXT_BLOCK() also creates an implicit jump
- from the current block to the new block.
-*/
+/* NEXT_BLOCK() creates an implicit jump from the current block
+ to the new block.
-/* The returns inside these macros make it impossible to decref objects
- created in the local function. Local objects should use the arena.
+ The returns inside this macro make it impossible to decref objects
+ created in the local function. Local objects should use the arena.
*/
-
-
-#define NEW_BLOCK(C) { \
- if (compiler_use_new_block((C)) == NULL) \
- return 0; \
-}
-
#define NEXT_BLOCK(C) { \
if (compiler_next_block((C)) == NULL) \
return 0; \
@@ -1309,7 +1301,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 +1679,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 +2595,35 @@ 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 Num_kind:
+ case Ellipsis_kind:
+ case Bytes_kind:
+ case NameConstant_kind:
+ case Constant_kind:
+ /* ignore constant statement */
+ 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 +2693,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 +3189,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 +3640,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 +3685,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 +3929,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 +4433,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 +4462,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 +4494,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 +4860,3 @@ PyAST_Compile(mod_ty mod, const char *filename, PyCompilerFlags *flags,
{
return PyAST_CompileEx(mod, filename, flags, -1, arena);
}
-