summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c627
1 files changed, 512 insertions, 115 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 686510c..cbc23aa 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -30,8 +30,6 @@
#include "symtable.h"
#include "opcode.h"
-int Py_OptimizeFlag = 0;
-
#define DEFAULT_BLOCK_SIZE 16
#define DEFAULT_BLOCKS 8
#define DEFAULT_CODE_SIZE 128
@@ -94,6 +92,7 @@ enum {
COMPILER_SCOPE_MODULE,
COMPILER_SCOPE_CLASS,
COMPILER_SCOPE_FUNCTION,
+ COMPILER_SCOPE_ASYNC_FUNCTION,
COMPILER_SCOPE_LAMBDA,
COMPILER_SCOPE_COMPREHENSION,
};
@@ -195,11 +194,11 @@ static int inplace_binop(struct compiler *, operator_ty);
static int expr_constant(struct compiler *, expr_ty);
static int compiler_with(struct compiler *, stmt_ty, int);
+static int compiler_async_with(struct compiler *, stmt_ty, int);
+static int compiler_async_for(struct compiler *, stmt_ty);
static int compiler_call_helper(struct compiler *c, Py_ssize_t n,
asdl_seq *args,
- asdl_seq *keywords,
- expr_ty starargs,
- expr_ty kwargs);
+ asdl_seq *keywords);
static int compiler_try_except(struct compiler *, stmt_ty);
static int compiler_set_qualname(struct compiler *);
@@ -677,7 +676,9 @@ compiler_set_qualname(struct compiler *c)
parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
assert(parent);
- if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) {
+ if (u->u_scope_type == COMPILER_SCOPE_FUNCTION
+ || u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION
+ || u->u_scope_type == COMPILER_SCOPE_CLASS) {
assert(u->u_name);
mangled = _Py_Mangle(parent->u_private, u->u_name);
if (!mangled)
@@ -691,6 +692,7 @@ compiler_set_qualname(struct compiler *c)
if (!force_global) {
if (parent->u_scope_type == COMPILER_SCOPE_FUNCTION
+ || parent->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION
|| parent->u_scope_type == COMPILER_SCOPE_LAMBDA) {
dot_locals_str = _PyUnicode_FromId(&dot_locals);
if (dot_locals_str == NULL)
@@ -881,6 +883,7 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
case BINARY_POWER:
case BINARY_MULTIPLY:
+ case BINARY_MATRIX_MULTIPLY:
case BINARY_MODULO:
case BINARY_ADD:
case BINARY_SUBTRACT:
@@ -895,12 +898,11 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
case INPLACE_ADD:
case INPLACE_SUBTRACT:
case INPLACE_MULTIPLY:
+ case INPLACE_MATRIX_MULTIPLY:
case INPLACE_MODULO:
return -1;
case STORE_SUBSCR:
return -3;
- case STORE_MAP:
- return -2;
case DELETE_SUBSCR:
return -2;
@@ -929,7 +931,9 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return 0;
case SETUP_WITH:
return 7;
- case WITH_CLEANUP:
+ case WITH_CLEANUP_START:
+ return 1;
+ case WITH_CLEANUP_FINISH:
return -1; /* XXX Sometimes more */
case RETURN_VALUE:
return -1;
@@ -973,6 +977,13 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
case BUILD_LIST:
case BUILD_SET:
return 1-oparg;
+ case BUILD_LIST_UNPACK:
+ case BUILD_TUPLE_UNPACK:
+ case BUILD_SET_UNPACK:
+ case BUILD_MAP_UNPACK:
+ return 1 - oparg;
+ case BUILD_MAP_UNPACK_WITH_CALL:
+ return 1 - (oparg & 0xFF);
case BUILD_MAP:
return 1;
case LOAD_ATTR:
@@ -1043,6 +1054,16 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
return -1;
case DELETE_DEREF:
return 0;
+ case GET_AWAITABLE:
+ return 0;
+ case SETUP_ASYNC_WITH:
+ return 6;
+ case BEFORE_ASYNC_WITH:
+ return 1;
+ case GET_AITER:
+ return 0;
+ case GET_ANEXT:
+ return 1;
default:
return PY_INVALID_STACK_EFFECT;
}
@@ -1637,19 +1658,43 @@ error:
}
static int
-compiler_function(struct compiler *c, stmt_ty s)
+compiler_function(struct compiler *c, stmt_ty s, int is_async)
{
PyCodeObject *co;
PyObject *qualname, *first_const = Py_None;
- arguments_ty args = s->v.FunctionDef.args;
- expr_ty returns = s->v.FunctionDef.returns;
- asdl_seq* decos = s->v.FunctionDef.decorator_list;
+ arguments_ty args;
+ expr_ty returns;
+ identifier name;
+ asdl_seq* decos;
+ asdl_seq *body;
stmt_ty st;
Py_ssize_t i, n, arglength;
int docstring, kw_default_count = 0;
int num_annotations;
+ int scope_type;
- assert(s->kind == FunctionDef_kind);
+
+ if (is_async) {
+ assert(s->kind == AsyncFunctionDef_kind);
+
+ args = s->v.AsyncFunctionDef.args;
+ returns = s->v.AsyncFunctionDef.returns;
+ decos = s->v.AsyncFunctionDef.decorator_list;
+ name = s->v.AsyncFunctionDef.name;
+ body = s->v.AsyncFunctionDef.body;
+
+ scope_type = COMPILER_SCOPE_ASYNC_FUNCTION;
+ } else {
+ assert(s->kind == FunctionDef_kind);
+
+ args = s->v.FunctionDef.args;
+ returns = s->v.FunctionDef.returns;
+ decos = s->v.FunctionDef.decorator_list;
+ name = s->v.FunctionDef.name;
+ body = s->v.FunctionDef.body;
+
+ scope_type = COMPILER_SCOPE_FUNCTION;
+ }
if (!compiler_decorators(c, decos))
return 0;
@@ -1667,12 +1712,12 @@ compiler_function(struct compiler *c, stmt_ty s)
return 0;
assert((num_annotations & 0xFFFF) == num_annotations);
- if (!compiler_enter_scope(c, s->v.FunctionDef.name,
- COMPILER_SCOPE_FUNCTION, (void *)s,
+ if (!compiler_enter_scope(c, name,
+ scope_type, (void *)s,
s->lineno))
return 0;
- st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, 0);
+ 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;
@@ -1683,10 +1728,10 @@ compiler_function(struct compiler *c, stmt_ty s)
c->u->u_argcount = asdl_seq_LEN(args->args);
c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
- n = asdl_seq_LEN(s->v.FunctionDef.body);
+ n = asdl_seq_LEN(body);
/* if there was a docstring, we need to skip the first statement */
for (i = docstring; i < n; i++) {
- st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, i);
+ st = (stmt_ty)asdl_seq_GET(body, i);
VISIT_IN_SCOPE(c, stmt, st);
}
co = assemble(c, 1);
@@ -1706,12 +1751,19 @@ compiler_function(struct compiler *c, stmt_ty s)
Py_DECREF(qualname);
Py_DECREF(co);
+ if (is_async) {
+ co->co_flags |= CO_COROUTINE;
+ /* An async function is always a generator, even
+ if there is no 'yield' expressions in it. */
+ co->co_flags |= CO_GENERATOR;
+ }
+
/* decorators */
for (i = 0; i < asdl_seq_LEN(decos); i++) {
ADDOP_I(c, CALL_FUNCTION, 1);
}
- return compiler_nameop(c, s->v.FunctionDef.name, Store);
+ return compiler_nameop(c, name, Store);
}
static int
@@ -1821,9 +1873,7 @@ compiler_class(struct compiler *c, stmt_ty s)
/* 5. generate the rest of the code for the call */
if (!compiler_call_helper(c, 2,
s->v.ClassDef.bases,
- s->v.ClassDef.keywords,
- s->v.ClassDef.starargs,
- s->v.ClassDef.kwargs))
+ s->v.ClassDef.keywords))
return 0;
/* 6. apply decorators */
@@ -1938,7 +1988,7 @@ compiler_if(struct compiler *c, stmt_ty s)
} else if (constant == 1) {
VISIT_SEQ(c, stmt, s->v.If.body);
} else {
- if (s->v.If.orelse) {
+ if (asdl_seq_LEN(s->v.If.orelse)) {
next = compiler_new_block(c);
if (next == NULL)
return 0;
@@ -1948,8 +1998,8 @@ compiler_if(struct compiler *c, stmt_ty s)
VISIT(c, expr, s->v.If.test);
ADDOP_JABS(c, POP_JUMP_IF_FALSE, next);
VISIT_SEQ(c, stmt, s->v.If.body);
- ADDOP_JREL(c, JUMP_FORWARD, end);
- if (s->v.If.orelse) {
+ if (asdl_seq_LEN(s->v.If.orelse)) {
+ ADDOP_JREL(c, JUMP_FORWARD, end);
compiler_use_next_block(c, next);
VISIT_SEQ(c, stmt, s->v.If.orelse);
}
@@ -1986,6 +2036,92 @@ compiler_for(struct compiler *c, stmt_ty s)
return 1;
}
+
+static int
+compiler_async_for(struct compiler *c, stmt_ty s)
+{
+ static PyObject *stopiter_error = NULL;
+ basicblock *try, *except, *end, *after_try, *try_cleanup,
+ *after_loop, *after_loop_else;
+
+ if (stopiter_error == NULL) {
+ stopiter_error = PyUnicode_InternFromString("StopAsyncIteration");
+ if (stopiter_error == NULL)
+ return 0;
+ }
+
+ try = compiler_new_block(c);
+ except = compiler_new_block(c);
+ end = compiler_new_block(c);
+ after_try = compiler_new_block(c);
+ try_cleanup = compiler_new_block(c);
+ after_loop = compiler_new_block(c);
+ after_loop_else = compiler_new_block(c);
+
+ if (try == NULL || except == NULL || end == NULL
+ || after_try == NULL || try_cleanup == NULL)
+ return 0;
+
+ ADDOP_JREL(c, SETUP_LOOP, after_loop);
+ if (!compiler_push_fblock(c, LOOP, try))
+ return 0;
+
+ VISIT(c, expr, s->v.AsyncFor.iter);
+ ADDOP(c, GET_AITER);
+ ADDOP_O(c, LOAD_CONST, Py_None, consts);
+ ADDOP(c, YIELD_FROM);
+
+ compiler_use_next_block(c, try);
+
+
+ ADDOP_JREL(c, SETUP_EXCEPT, except);
+ if (!compiler_push_fblock(c, EXCEPT, try))
+ return 0;
+
+ ADDOP(c, GET_ANEXT);
+ ADDOP_O(c, LOAD_CONST, Py_None, consts);
+ ADDOP(c, YIELD_FROM);
+ VISIT(c, expr, s->v.AsyncFor.target);
+ ADDOP(c, POP_BLOCK);
+ compiler_pop_fblock(c, EXCEPT, try);
+ ADDOP_JREL(c, JUMP_FORWARD, after_try);
+
+
+ compiler_use_next_block(c, except);
+ ADDOP(c, DUP_TOP);
+ ADDOP_O(c, LOAD_GLOBAL, stopiter_error, names);
+ ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH);
+ ADDOP_JABS(c, POP_JUMP_IF_FALSE, try_cleanup);
+
+ ADDOP(c, POP_TOP);
+ ADDOP(c, POP_TOP);
+ ADDOP(c, POP_TOP);
+ ADDOP(c, POP_EXCEPT); /* for SETUP_EXCEPT */
+ ADDOP(c, POP_BLOCK); /* for SETUP_LOOP */
+ ADDOP_JABS(c, JUMP_ABSOLUTE, after_loop_else);
+
+
+ compiler_use_next_block(c, try_cleanup);
+ ADDOP(c, END_FINALLY);
+
+ compiler_use_next_block(c, after_try);
+ VISIT_SEQ(c, stmt, s->v.AsyncFor.body);
+ ADDOP_JABS(c, JUMP_ABSOLUTE, try);
+
+ ADDOP(c, POP_BLOCK); /* for SETUP_LOOP */
+ compiler_pop_fblock(c, LOOP, try);
+
+ compiler_use_next_block(c, after_loop);
+ ADDOP_JABS(c, JUMP_ABSOLUTE, end);
+
+ compiler_use_next_block(c, after_loop_else);
+ VISIT_SEQ(c, stmt, s->v.For.orelse);
+
+ compiler_use_next_block(c, end);
+
+ return 1;
+}
+
static int
compiler_while(struct compiler *c, stmt_ty s)
{
@@ -2512,7 +2648,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
switch (s->kind) {
case FunctionDef_kind:
- return compiler_function(c, s);
+ return compiler_function(c, s, 0);
case ClassDef_kind:
return compiler_class(c, s);
case Return_kind:
@@ -2591,7 +2727,14 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
return compiler_continue(c);
case With_kind:
return compiler_with(c, s, 0);
+ case AsyncFunctionDef_kind:
+ return compiler_function(c, s, 1);
+ case AsyncWith_kind:
+ return compiler_async_with(c, s, 0);
+ case AsyncFor_kind:
+ return compiler_async_for(c, s);
}
+
return 1;
}
@@ -2624,6 +2767,8 @@ binop(struct compiler *c, operator_ty op)
return BINARY_SUBTRACT;
case Mult:
return BINARY_MULTIPLY;
+ case MatMult:
+ return BINARY_MATRIX_MULTIPLY;
case Div:
return BINARY_TRUE_DIVIDE;
case Mod:
@@ -2688,6 +2833,8 @@ inplace_binop(struct compiler *c, operator_ty op)
return INPLACE_SUBTRACT;
case Mult:
return INPLACE_MULTIPLY;
+ case MatMult:
+ return INPLACE_MATRIX_MULTIPLY;
case Div:
return INPLACE_TRUE_DIVIDE;
case Mod:
@@ -2749,8 +2896,7 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx)
optype = OP_FAST;
break;
case GLOBAL_IMPLICIT:
- if (c->u->u_ste->ste_type == FunctionBlock &&
- !c->u->u_ste->ste_unoptimized)
+ if (c->u->u_ste->ste_type == FunctionBlock)
optype = OP_GLOBAL;
break;
case GLOBAL_EXPLICIT:
@@ -2868,67 +3014,145 @@ compiler_boolop(struct compiler *c, expr_ty e)
}
static int
-compiler_list(struct compiler *c, expr_ty e)
+starunpack_helper(struct compiler *c, asdl_seq *elts,
+ int single_op, int inner_op, int outer_op)
{
- Py_ssize_t n = asdl_seq_LEN(e->v.List.elts);
- if (e->v.List.ctx == Store) {
- int i, seen_star = 0;
- for (i = 0; i < n; i++) {
- expr_ty elt = asdl_seq_GET(e->v.List.elts, i);
- if (elt->kind == Starred_kind && !seen_star) {
- if ((i >= (1 << 8)) ||
- (n-i-1 >= (INT_MAX >> 8)))
- return compiler_error(c,
- "too many expressions in "
- "star-unpacking assignment");
- ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8)));
- seen_star = 1;
- asdl_seq_SET(e->v.List.elts, i, elt->v.Starred.value);
- } else if (elt->kind == Starred_kind) {
- return compiler_error(c,
- "two starred expressions in assignment");
+ Py_ssize_t n = asdl_seq_LEN(elts);
+ Py_ssize_t i, nsubitems = 0, nseen = 0;
+ for (i = 0; i < n; i++) {
+ expr_ty elt = asdl_seq_GET(elts, i);
+ if (elt->kind == Starred_kind) {
+ if (nseen) {
+ ADDOP_I(c, inner_op, nseen);
+ nseen = 0;
+ nsubitems++;
}
+ VISIT(c, expr, elt->v.Starred.value);
+ nsubitems++;
+ }
+ else {
+ VISIT(c, expr, elt);
+ nseen++;
+ }
+ }
+ if (nsubitems) {
+ if (nseen) {
+ ADDOP_I(c, inner_op, nseen);
+ nsubitems++;
+ }
+ ADDOP_I(c, outer_op, nsubitems);
+ }
+ else
+ ADDOP_I(c, single_op, nseen);
+ return 1;
+}
+
+static int
+assignment_helper(struct compiler *c, asdl_seq *elts)
+{
+ Py_ssize_t n = asdl_seq_LEN(elts);
+ Py_ssize_t i;
+ int seen_star = 0;
+ for (i = 0; i < n; i++) {
+ expr_ty elt = asdl_seq_GET(elts, i);
+ if (elt->kind == Starred_kind && !seen_star) {
+ if ((i >= (1 << 8)) ||
+ (n-i-1 >= (INT_MAX >> 8)))
+ return compiler_error(c,
+ "too many expressions in "
+ "star-unpacking assignment");
+ ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8)));
+ seen_star = 1;
+ asdl_seq_SET(elts, i, elt->v.Starred.value);
}
- if (!seen_star) {
- ADDOP_I(c, UNPACK_SEQUENCE, n);
+ else if (elt->kind == Starred_kind) {
+ return compiler_error(c,
+ "two starred expressions in assignment");
}
}
- VISIT_SEQ(c, expr, e->v.List.elts);
- if (e->v.List.ctx == Load) {
- ADDOP_I(c, BUILD_LIST, n);
+ if (!seen_star) {
+ ADDOP_I(c, UNPACK_SEQUENCE, n);
}
+ VISIT_SEQ(c, expr, elts);
+ return 1;
+}
+
+static int
+compiler_list(struct compiler *c, expr_ty e)
+{
+ asdl_seq *elts = e->v.List.elts;
+ if (e->v.List.ctx == Store) {
+ return assignment_helper(c, elts);
+ }
+ else if (e->v.List.ctx == Load) {
+ return starunpack_helper(c, elts,
+ BUILD_LIST, BUILD_TUPLE, BUILD_LIST_UNPACK);
+ }
+ else
+ VISIT_SEQ(c, expr, elts);
return 1;
}
static int
compiler_tuple(struct compiler *c, expr_ty e)
{
- Py_ssize_t n = asdl_seq_LEN(e->v.Tuple.elts);
+ asdl_seq *elts = e->v.Tuple.elts;
if (e->v.Tuple.ctx == Store) {
- int i, seen_star = 0;
- for (i = 0; i < n; i++) {
- expr_ty elt = asdl_seq_GET(e->v.Tuple.elts, i);
- if (elt->kind == Starred_kind && !seen_star) {
- if ((i >= (1 << 8)) ||
- (n-i-1 >= (INT_MAX >> 8)))
- return compiler_error(c,
- "too many expressions in "
- "star-unpacking assignment");
- ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8)));
- seen_star = 1;
- asdl_seq_SET(e->v.Tuple.elts, i, elt->v.Starred.value);
- } else if (elt->kind == Starred_kind) {
- return compiler_error(c,
- "two starred expressions in assignment");
- }
+ return assignment_helper(c, elts);
+ }
+ else if (e->v.Tuple.ctx == Load) {
+ return starunpack_helper(c, elts,
+ BUILD_TUPLE, BUILD_TUPLE, BUILD_TUPLE_UNPACK);
+ }
+ else
+ VISIT_SEQ(c, expr, elts);
+ return 1;
+}
+
+static int
+compiler_set(struct compiler *c, expr_ty e)
+{
+ return starunpack_helper(c, e->v.Set.elts, BUILD_SET,
+ BUILD_SET, BUILD_SET_UNPACK);
+}
+
+static int
+compiler_dict(struct compiler *c, expr_ty e)
+{
+ Py_ssize_t i, n, containers, elements;
+ int is_unpacking = 0;
+ n = asdl_seq_LEN(e->v.Dict.values);
+ containers = 0;
+ elements = 0;
+ for (i = 0; i < n; i++) {
+ is_unpacking = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i) == NULL;
+ if (elements == 0xFFFF || (elements && is_unpacking)) {
+ ADDOP_I(c, BUILD_MAP, elements);
+ containers++;
+ elements = 0;
+ }
+ if (is_unpacking) {
+ VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));
+ containers++;
}
- if (!seen_star) {
- ADDOP_I(c, UNPACK_SEQUENCE, n);
+ else {
+ VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.keys, i));
+ VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));
+ elements++;
}
}
- VISIT_SEQ(c, expr, e->v.Tuple.elts);
- if (e->v.Tuple.ctx == Load) {
- ADDOP_I(c, BUILD_TUPLE, n);
+ if (elements || containers == 0) {
+ ADDOP_I(c, BUILD_MAP, elements);
+ containers++;
+ }
+ /* If there is more than one dict, they need to be merged into a new
+ * dict. If there is one dict and it's an unpacking, then it needs
+ * to be copied into a new dict." */
+ while (containers > 1 || is_unpacking) {
+ int oparg = containers < 255 ? containers : 255;
+ ADDOP_I(c, BUILD_MAP_UNPACK, oparg);
+ containers -= (oparg - 1);
+ is_unpacking = 0;
}
return 1;
}
@@ -2984,9 +3208,7 @@ compiler_call(struct compiler *c, expr_ty e)
VISIT(c, expr, e->v.Call.func);
return compiler_call_helper(c, 0,
e->v.Call.args,
- e->v.Call.keywords,
- e->v.Call.starargs,
- e->v.Call.kwargs);
+ e->v.Call.keywords);
}
/* shared code between compiler_call and compiler_class */
@@ -2994,26 +3216,102 @@ static int
compiler_call_helper(struct compiler *c,
Py_ssize_t n, /* Args already pushed */
asdl_seq *args,
- asdl_seq *keywords,
- expr_ty starargs,
- expr_ty kwargs)
+ asdl_seq *keywords)
{
int code = 0;
-
- n += asdl_seq_LEN(args);
- VISIT_SEQ(c, expr, args);
- if (keywords) {
- VISIT_SEQ(c, keyword, keywords);
- n |= asdl_seq_LEN(keywords) << 8;
+ Py_ssize_t nelts, i, nseen, nkw;
+
+ /* the number of tuples and dictionaries on the stack */
+ Py_ssize_t nsubargs = 0, nsubkwargs = 0;
+
+ nkw = 0;
+ nseen = 0; /* the number of positional arguments on the stack */
+ nelts = asdl_seq_LEN(args);
+ for (i = 0; i < nelts; i++) {
+ expr_ty elt = asdl_seq_GET(args, i);
+ if (elt->kind == Starred_kind) {
+ /* A star-arg. If we've seen positional arguments,
+ pack the positional arguments into a
+ tuple. */
+ if (nseen) {
+ ADDOP_I(c, BUILD_TUPLE, nseen);
+ nseen = 0;
+ nsubargs++;
+ }
+ VISIT(c, expr, elt->v.Starred.value);
+ nsubargs++;
+ }
+ else if (nsubargs) {
+ /* We've seen star-args already, so we
+ count towards items-to-pack-into-tuple. */
+ VISIT(c, expr, elt);
+ nseen++;
+ }
+ else {
+ /* Positional arguments before star-arguments
+ are left on the stack. */
+ VISIT(c, expr, elt);
+ n++;
+ }
}
- if (starargs) {
- VISIT(c, expr, starargs);
+ if (nseen) {
+ /* Pack up any trailing positional arguments. */
+ ADDOP_I(c, BUILD_TUPLE, nseen);
+ nsubargs++;
+ }
+ if (nsubargs) {
code |= 1;
+ if (nsubargs > 1) {
+ /* If we ended up with more than one stararg, we need
+ to concatenate them into a single sequence. */
+ ADDOP_I(c, BUILD_LIST_UNPACK, nsubargs);
+ }
+ }
+
+ /* Same dance again for keyword arguments */
+ nseen = 0; /* the number of keyword arguments on the stack following */
+ nelts = asdl_seq_LEN(keywords);
+ for (i = 0; i < nelts; i++) {
+ keyword_ty kw = asdl_seq_GET(keywords, i);
+ if (kw->arg == NULL) {
+ /* A keyword argument unpacking. */
+ if (nseen) {
+ ADDOP_I(c, BUILD_MAP, nseen);
+ nseen = 0;
+ nsubkwargs++;
+ }
+ VISIT(c, expr, kw->value);
+ nsubkwargs++;
+ }
+ else if (nsubkwargs) {
+ /* A keyword argument and we already have a dict. */
+ ADDOP_O(c, LOAD_CONST, kw->arg, consts);
+ VISIT(c, expr, kw->value);
+ nseen++;
+ }
+ else {
+ /* keyword argument */
+ VISIT(c, keyword, kw)
+ nkw++;
+ }
+ }
+ if (nseen) {
+ /* Pack up any trailing keyword arguments. */
+ ADDOP_I(c, BUILD_MAP, nseen);
+ nsubkwargs++;
}
- if (kwargs) {
- VISIT(c, expr, kwargs);
+ if (nsubkwargs) {
code |= 2;
+ if (nsubkwargs > 1) {
+ /* Pack it all up */
+ int function_pos = n + (code & 1) + nkw + 1;
+ ADDOP_I(c, BUILD_MAP_UNPACK_WITH_CALL, nsubkwargs | (function_pos << 8));
+ }
}
+ assert(n < 1<<8);
+ assert(nkw < 1<<24);
+ n |= nkw << 8;
+
switch (code) {
case 0:
ADDOP_I(c, CALL_FUNCTION, n);
@@ -3138,8 +3436,9 @@ compiler_comprehension_generator(struct compiler *c,
}
static int
-compiler_comprehension(struct compiler *c, expr_ty e, int type, identifier name,
- asdl_seq *generators, expr_ty elt, expr_ty val)
+compiler_comprehension(struct compiler *c, expr_ty e, int type,
+ identifier name, asdl_seq *generators, expr_ty elt,
+ expr_ty val)
{
PyCodeObject *co = NULL;
expr_ty outermost_iter;
@@ -3312,6 +3611,102 @@ expr_constant(struct compiler *c, expr_ty e)
}
}
+
+/*
+ Implements the async with statement.
+
+ The semantics outlined in that PEP are as follows:
+
+ async with EXPR as VAR:
+ BLOCK
+
+ It is implemented roughly as:
+
+ context = EXPR
+ exit = context.__aexit__ # not calling it
+ value = await context.__aenter__()
+ try:
+ VAR = value # if VAR present in the syntax
+ BLOCK
+ finally:
+ if an exception was raised:
+ exc = copy of (exception, instance, traceback)
+ else:
+ exc = (None, None, None)
+ if not (await exit(*exc)):
+ raise
+ */
+static int
+compiler_async_with(struct compiler *c, stmt_ty s, int pos)
+{
+ basicblock *block, *finally;
+ withitem_ty item = asdl_seq_GET(s->v.AsyncWith.items, pos);
+
+ assert(s->kind == AsyncWith_kind);
+
+ block = compiler_new_block(c);
+ finally = compiler_new_block(c);
+ if (!block || !finally)
+ return 0;
+
+ /* Evaluate EXPR */
+ VISIT(c, expr, item->context_expr);
+
+ ADDOP(c, BEFORE_ASYNC_WITH);
+ ADDOP(c, GET_AWAITABLE);
+ ADDOP_O(c, LOAD_CONST, Py_None, consts);
+ ADDOP(c, YIELD_FROM);
+
+ ADDOP_JREL(c, SETUP_ASYNC_WITH, finally);
+
+ /* SETUP_ASYNC_WITH pushes a finally block. */
+ compiler_use_next_block(c, block);
+ if (!compiler_push_fblock(c, FINALLY_TRY, block)) {
+ return 0;
+ }
+
+ if (item->optional_vars) {
+ VISIT(c, expr, item->optional_vars);
+ }
+ else {
+ /* Discard result from context.__aenter__() */
+ ADDOP(c, POP_TOP);
+ }
+
+ pos++;
+ if (pos == asdl_seq_LEN(s->v.AsyncWith.items))
+ /* BLOCK code */
+ VISIT_SEQ(c, stmt, s->v.AsyncWith.body)
+ else if (!compiler_async_with(c, s, pos))
+ return 0;
+
+ /* End of try block; start the finally block */
+ ADDOP(c, POP_BLOCK);
+ compiler_pop_fblock(c, FINALLY_TRY, block);
+
+ ADDOP_O(c, LOAD_CONST, Py_None, consts);
+ compiler_use_next_block(c, finally);
+ if (!compiler_push_fblock(c, FINALLY_END, finally))
+ return 0;
+
+ /* Finally block starts; context.__exit__ is on the stack under
+ the exception or return information. Just issue our magic
+ opcode. */
+ ADDOP(c, WITH_CLEANUP_START);
+
+ ADDOP(c, GET_AWAITABLE);
+ ADDOP_O(c, LOAD_CONST, Py_None, consts);
+ ADDOP(c, YIELD_FROM);
+
+ ADDOP(c, WITH_CLEANUP_FINISH);
+
+ /* Finally block ends. */
+ ADDOP(c, END_FINALLY);
+ compiler_pop_fblock(c, FINALLY_END, finally);
+ return 1;
+}
+
+
/*
Implements the with statement from PEP 343.
@@ -3385,7 +3780,8 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
/* Finally block starts; context.__exit__ is on the stack under
the exception or return information. Just issue our magic
opcode. */
- ADDOP(c, WITH_CLEANUP);
+ ADDOP(c, WITH_CLEANUP_START);
+ ADDOP(c, WITH_CLEANUP_FINISH);
/* Finally block ends. */
ADDOP(c, END_FINALLY);
@@ -3396,8 +3792,6 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
static int
compiler_visit_expr(struct compiler *c, expr_ty e)
{
- Py_ssize_t i, n;
-
/* If expr e has a different line number than the last expr/stmt,
set a new line number for the next instruction.
*/
@@ -3424,23 +3818,9 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
case IfExp_kind:
return compiler_ifexp(c, e);
case Dict_kind:
- n = asdl_seq_LEN(e->v.Dict.values);
- /* BUILD_MAP parameter is only used to preallocate the dictionary,
- it doesn't need to be exact */
- ADDOP_I(c, BUILD_MAP, (n>0xFFFF ? 0xFFFF : n));
- for (i = 0; i < n; i++) {
- VISIT(c, expr,
- (expr_ty)asdl_seq_GET(e->v.Dict.values, i));
- VISIT(c, expr,
- (expr_ty)asdl_seq_GET(e->v.Dict.keys, i));
- ADDOP(c, STORE_MAP);
- }
- break;
+ return compiler_dict(c, e);
case Set_kind:
- n = asdl_seq_LEN(e->v.Set.elts);
- VISIT_SEQ(c, expr, e->v.Set.elts);
- ADDOP_I(c, BUILD_SET, n);
- break;
+ return compiler_set(c, e);
case GeneratorExp_kind:
return compiler_genexp(c, e);
case ListComp_kind:
@@ -3452,6 +3832,8 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
case Yield_kind:
if (c->u->u_ste->ste_type != FunctionBlock)
return compiler_error(c, "'yield' outside function");
+ if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION)
+ return compiler_error(c, "'yield' inside async function");
if (e->v.Yield.value) {
VISIT(c, expr, e->v.Yield.value);
}
@@ -3463,11 +3845,28 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
case YieldFrom_kind:
if (c->u->u_ste->ste_type != FunctionBlock)
return compiler_error(c, "'yield' outside function");
+
+ if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION)
+ return compiler_error(c, "'yield from' inside async function");
+
VISIT(c, expr, e->v.YieldFrom.value);
ADDOP(c, GET_ITER);
ADDOP_O(c, LOAD_CONST, Py_None, consts);
ADDOP(c, YIELD_FROM);
break;
+ case Await_kind:
+ if (c->u->u_ste->ste_type != FunctionBlock)
+ return compiler_error(c, "'await' outside function");
+
+ /* this check won't be triggered while we have AWAIT token */
+ if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION)
+ return compiler_error(c, "'await' outside async function");
+
+ VISIT(c, expr, e->v.Await.value);
+ ADDOP(c, GET_AWAITABLE);
+ ADDOP_O(c, LOAD_CONST, Py_None, consts);
+ ADDOP(c, YIELD_FROM);
+ break;
case Compare_kind:
return compiler_compare(c, e);
case Call_kind:
@@ -3551,7 +3950,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
"starred assignment target must be in a list or tuple");
default:
return compiler_error(c,
- "can use starred expression only as assignment target");
+ "can't use starred expression here");
}
break;
case Name_kind:
@@ -4181,9 +4580,7 @@ compute_code_flags(struct compiler *c)
int flags = 0;
Py_ssize_t n;
if (ste->ste_type == FunctionBlock) {
- flags |= CO_NEWLOCALS;
- if (!ste->ste_unoptimized)
- flags |= CO_OPTIMIZED;
+ flags |= CO_NEWLOCALS | CO_OPTIMIZED;
if (ste->ste_nested)
flags |= CO_NESTED;
if (ste->ste_generator)