From 3f16b927b6791867124ec969049fde4d61df0157 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 9 Apr 2014 23:55:56 -0400 Subject: PEP 465: a dedicated infix operator for matrix multiplication (closes #21176) --- Python/compile.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 9978eb3a1d..9d3646eb91 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -881,6 +881,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,6 +896,7 @@ 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: @@ -2625,6 +2627,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: @@ -2689,6 +2693,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: -- cgit v1.2.1 From 770db9926387f77e8ff8f86586077093df430a81 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 18 Sep 2014 03:06:50 +0200 Subject: Closes #11471: avoid generating a JUMP_FORWARD instruction at the end of an if-block if there is no else-clause. Original patch by Eugene Toder. --- Python/compile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 9cc13995ef..e46ec6ceda 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1940,7 +1940,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; @@ -1950,8 +1950,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); } -- cgit v1.2.1 From 6e9be5f210237c3f6dc67bc6f84db6f0324c1054 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 18 Nov 2014 23:34:33 +0200 Subject: Issue #22453: Removed non-documented macro PyObject_REPR(). --- Python/compile.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index e46ec6ceda..ac9decc143 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1414,12 +1414,12 @@ get_ref_type(struct compiler *c, PyObject *name) PyOS_snprintf(buf, sizeof(buf), "unknown scope for %.100s in %.100s(%s)\n" "symbols: %s\nlocals: %s\nglobals: %s", - PyBytes_AS_STRING(name), - PyBytes_AS_STRING(c->u->u_name), - PyObject_REPR(c->u->u_ste->ste_id), - PyObject_REPR(c->u->u_ste->ste_symbols), - PyObject_REPR(c->u->u_varnames), - PyObject_REPR(c->u->u_names) + PyUnicode_AsUTF8(name), + PyUnicode_AsUTF8(c->u->u_name), + PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)), + PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)), + PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)), + PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names)) ); Py_FatalError(buf); } @@ -1476,11 +1476,11 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t args, PyO fprintf(stderr, "lookup %s in %s %d %d\n" "freevars of %s: %s\n", - PyObject_REPR(name), - PyBytes_AS_STRING(c->u->u_name), + PyUnicode_AsUTF8(PyObject_Repr(name)), + PyUnicode_AsUTF8(c->u->u_name), reftype, arg, - _PyUnicode_AsString(co->co_name), - PyObject_REPR(co->co_freevars)); + PyUnicode_AsUTF8(co->co_name), + PyUnicode_AsUTF8(PyObject_Repr(co->co_freevars))); Py_FatalError("compiler_make_closure()"); } ADDOP_I(c, LOAD_CLOSURE, arg); -- cgit v1.2.1 From 86a58dabec40bfb4c112b918cabd7eb21e52183c Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Thu, 20 Nov 2014 21:39:37 +1000 Subject: Issue #22869: Split pythonrun into two modules - interpreter startup and shutdown code moved to a new pylifecycle.c module - Py_OptimizeFlag moved into the new module with the other global flags --- Python/compile.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index ac9decc143..8abe50f4ca 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 -- cgit v1.2.1 From be670f799c5cc553ecaadf12d309cf60c9469230 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 27 Apr 2015 21:44:22 -0400 Subject: remove the concept of an unoptimized function scope from the compiler, since it can't happen anymore --- Python/compile.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index d5009e18fa..855ec464af 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2753,8 +2753,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: @@ -4185,9 +4184,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) -- cgit v1.2.1 From 2571248c875b79a134b3a6fd4010c2a2e6e2c7aa Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 5 May 2015 20:16:41 -0400 Subject: PEP 448: additional unpacking generalizations (closes #2292) Patch by Neil Girdhar. --- Python/compile.c | 319 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 230 insertions(+), 89 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 855ec464af..bf4cf40289 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -195,9 +195,7 @@ static int expr_constant(struct compiler *, expr_ty); static int compiler_with(struct compiler *, stmt_ty, int); 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 *); @@ -672,7 +670,8 @@ compiler_set_qualname(struct compiler *c) PyObject *mangled, *capsule; capsule = PyList_GET_ITEM(c->c_stack, stack_size - 1); - parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); + parent = (struct compiler_unit *)PyCapsule_GetPointer( + capsule, COMPILER_CAPSULE_NAME_COMPILER_UNIT); assert(parent); if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) { @@ -973,6 +972,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: @@ -1821,9 +1827,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 */ @@ -2871,67 +2875,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 (!seen_star) { - ADDOP_I(c, UNPACK_SEQUENCE, n); + if (is_unpacking) { + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); + containers++; } + else { + 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)); + elements++; + } + } + if (elements || containers == 0) { + ADDOP_I(c, BUILD_MAP, elements); + containers++; } - VISIT_SEQ(c, expr, e->v.Tuple.elts); - if (e->v.Tuple.ctx == Load) { - ADDOP_I(c, BUILD_TUPLE, n); + /* 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; } @@ -2987,9 +3069,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 */ @@ -2997,26 +3077,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 (nseen) { + /* Pack up any trailing positional arguments. */ + ADDOP_I(c, BUILD_TUPLE, nseen); + nsubargs++; } - if (starargs) { - VISIT(c, expr, starargs); + 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. */ + VISIT(c, expr, kw->value); + ADDOP_O(c, LOAD_CONST, kw->arg, consts); + nseen++; + } + else { + /* keyword argument */ + VISIT(c, keyword, kw) + nkw++; + } } - if (kwargs) { - VISIT(c, expr, kwargs); + if (nseen) { + /* Pack up any trailing keyword arguments. */ + ADDOP_I(c, BUILD_MAP, nseen); + nsubkwargs++; + } + 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); @@ -3141,8 +3297,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; @@ -3399,8 +3556,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. */ @@ -3427,23 +3582,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: @@ -3554,7 +3695,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: -- cgit v1.2.1 From ea639832c36905ecb07caba111f614c4bbf9bdd6 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Mon, 11 May 2015 22:57:16 -0400 Subject: PEP 0492 -- Coroutines with async and await syntax. Issue #24017. --- Python/compile.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 273 insertions(+), 15 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index efd4807613..7820f39f87 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -92,6 +92,7 @@ enum { COMPILER_SCOPE_MODULE, COMPILER_SCOPE_CLASS, COMPILER_SCOPE_FUNCTION, + COMPILER_SCOPE_ASYNC_FUNCTION, COMPILER_SCOPE_LAMBDA, COMPILER_SCOPE_COMPREHENSION, }; @@ -193,6 +194,8 @@ 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); @@ -673,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) @@ -687,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) @@ -927,7 +933,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; @@ -1048,6 +1056,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; } @@ -1642,19 +1660,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; + + + 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; - assert(s->kind == FunctionDef_kind); + scope_type = COMPILER_SCOPE_FUNCTION; + } if (!compiler_decorators(c, decos)) return 0; @@ -1672,12 +1714,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; @@ -1688,10 +1730,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); @@ -1711,12 +1753,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 @@ -1989,6 +2038,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) { @@ -2515,7 +2650,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: @@ -2594,7 +2729,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; } @@ -3471,6 +3613,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. @@ -3544,7 +3782,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); @@ -3595,6 +3834,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); } @@ -3606,11 +3847,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: -- cgit v1.2.1 From ffe5c8f2c45e238c70ac87fecf23aeef676a65f6 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 28 May 2015 14:30:26 -0500 Subject: in dict displays, evaluate the key before the value (closes #11205) Patch partially by Steve Dougherty. --- Python/compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 7820f39f87..5905910574 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3138,8 +3138,8 @@ compiler_dict(struct compiler *c, expr_ty e) containers++; } else { - 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)); + VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i)); elements++; } } @@ -3287,8 +3287,8 @@ compiler_call_helper(struct compiler *c, } else if (nsubkwargs) { /* A keyword argument and we already have a dict. */ - VISIT(c, expr, kw->value); ADDOP_O(c, LOAD_CONST, kw->arg, consts); + VISIT(c, expr, kw->value); nseen++; } else { -- cgit v1.2.1 From 2a8855656d526cce898303bb03c66274f06e7b51 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 28 May 2015 14:40:08 -0500 Subject: remove STORE_MAP, since it's unused --- Python/compile.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 5905910574..29b88ff0e3 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -903,8 +903,6 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return -1; case STORE_SUBSCR: return -3; - case STORE_MAP: - return -2; case DELETE_SUBSCR: return -2; -- cgit v1.2.1 From 15be527fca539925b6ba49e0d0089f13f1e210ee Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Mon, 22 Jun 2015 12:19:30 -0400 Subject: Issue #24400: Introduce a distinct type for 'async def' coroutines. Summary of changes: 1. Coroutines now have a distinct, separate from generators type at the C level: PyGen_Type, and a new typedef PyCoroObject. PyCoroObject shares the initial segment of struct layout with PyGenObject, making it possible to reuse existing generators machinery. The new type is exposed as 'types.CoroutineType'. As a consequence of having a new type, CO_GENERATOR flag is no longer applied to coroutines. 2. Having a separate type for coroutines made it possible to add an __await__ method to the type. Although it is not used by the interpreter (see details on that below), it makes coroutines naturally (without using __instancecheck__) conform to collections.abc.Coroutine and collections.abc.Awaitable ABCs. [The __instancecheck__ is still used for generator-based coroutines, as we don't want to add __await__ for generators.] 3. Add new opcode: GET_YIELD_FROM_ITER. The opcode is needed to allow passing native coroutines to the YIELD_FROM opcode. Before this change, 'yield from o' expression was compiled to: (o) GET_ITER LOAD_CONST YIELD_FROM Now, we use GET_YIELD_FROM_ITER instead of GET_ITER. The reason for adding a new opcode is that GET_ITER is used in some contexts (such as 'for .. in' loops) where passing a coroutine object is invalid. 4. Add two new introspection functions to the inspec module: getcoroutinestate(c) and getcoroutinelocals(c). 5. inspect.iscoroutine(o) is updated to test if 'o' is a native coroutine object. Before this commit it used abc.Coroutine, and it was requested to update inspect.isgenerator(o) to use abc.Generator; it was decided, however, that inspect functions should really be tailored for checking for native types. 6. sys.set_coroutine_wrapper(w) API is updated to work with only native coroutines. Since types.coroutine decorator supports any type of callables now, it would be confusing that it does not work for all types of coroutines. 7. Exceptions logic in generators C implementation was updated to raise clearer messages for coroutines: Before: TypeError("generator raised StopIteration") After: TypeError("coroutine raised StopIteration") --- Python/compile.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index cbc23aa209..1977c3a1bf 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1064,6 +1064,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return 0; case GET_ANEXT: return 1; + case GET_YIELD_FROM_ITER: + return 0; default: return PY_INVALID_STACK_EFFECT; } @@ -1751,12 +1753,8 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) Py_DECREF(qualname); Py_DECREF(co); - if (is_async) { + 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++) { @@ -3850,7 +3848,7 @@ compiler_visit_expr(struct compiler *c, expr_ty e) return compiler_error(c, "'yield from' inside async function"); VISIT(c, expr, e->v.YieldFrom.value); - ADDOP(c, GET_ITER); + ADDOP(c, GET_YIELD_FROM_ITER); ADDOP_O(c, LOAD_CONST, Py_None, consts); ADDOP(c, YIELD_FROM); break; -- cgit v1.2.1 From 5738abf09d4e561e1e19e132190a437342e1044a Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Tue, 30 Jun 2015 12:49:04 -0400 Subject: Issue #24528: Improve error message for awaits in comprehensions --- Python/compile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 1977c3a1bf..2202e8f3a1 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3856,7 +3856,10 @@ compiler_visit_expr(struct compiler *c, expr_ty e) 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_COMPREHENSION) + return compiler_error( + c, "'await' expressions in comprehensions are not supported"); + if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION) return compiler_error(c, "'await' outside async function"); -- cgit v1.2.1 From 0d0c1f7adb3accb5352012a42ecc68587a10e683 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Wed, 22 Jul 2015 14:48:57 +0300 Subject: Issue #24619: More tests; fix nits in compiler.c --- Python/compile.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 2202e8f3a1..33cc8c22cb 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1749,13 +1749,12 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) arglength = asdl_seq_LEN(args->defaults); arglength |= kw_default_count << 8; arglength |= num_annotations << 16; + if (is_async) + co->co_flags |= CO_COROUTINE; compiler_make_closure(c, co, arglength, qualname); Py_DECREF(qualname); Py_DECREF(co); - if (is_async) - co->co_flags |= CO_COROUTINE; - /* decorators */ for (i = 0; i < asdl_seq_LEN(decos); i++) { ADDOP_I(c, CALL_FUNCTION, 1); -- cgit v1.2.1 From debd2831daa2f74af4270cbdf79a642942bce4f5 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Thu, 23 Jul 2015 09:10:44 +0300 Subject: Issue #24687: Plug refleak on SyntaxError in function parameters annotations. --- Python/compile.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 33cc8c22cb..027e3abe68 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1559,32 +1559,31 @@ compiler_visit_argannotation(struct compiler *c, identifier id, VISIT(c, expr, annotation); mangled = _Py_Mangle(c->u->u_private, id); if (!mangled) - return -1; + return 0; if (PyList_Append(names, mangled) < 0) { Py_DECREF(mangled); - return -1; + return 0; } Py_DECREF(mangled); } - return 0; + return 1; } static int compiler_visit_argannotations(struct compiler *c, asdl_seq* args, PyObject *names) { - int i, error; + int i; for (i = 0; i < asdl_seq_LEN(args); i++) { arg_ty arg = (arg_ty)asdl_seq_GET(args, i); - error = compiler_visit_argannotation( + if (!compiler_visit_argannotation( c, arg->arg, arg->annotation, - names); - if (error) - return error; + names)) + return 0; } - return 0; + return 1; } static int @@ -1604,16 +1603,16 @@ compiler_visit_annotations(struct compiler *c, arguments_ty args, if (!names) return -1; - if (compiler_visit_argannotations(c, args->args, names)) + if (!compiler_visit_argannotations(c, args->args, names)) goto error; if (args->vararg && args->vararg->annotation && - compiler_visit_argannotation(c, args->vararg->arg, + !compiler_visit_argannotation(c, args->vararg->arg, args->vararg->annotation, names)) goto error; - if (compiler_visit_argannotations(c, args->kwonlyargs, names)) + if (!compiler_visit_argannotations(c, args->kwonlyargs, names)) goto error; if (args->kwarg && args->kwarg->annotation && - compiler_visit_argannotation(c, args->kwarg->arg, + !compiler_visit_argannotation(c, args->kwarg->arg, args->kwarg->annotation, names)) goto error; @@ -1622,7 +1621,7 @@ compiler_visit_annotations(struct compiler *c, arguments_ty args, if (!return_str) goto error; } - if (compiler_visit_argannotation(c, return_str, returns, names)) { + if (!compiler_visit_argannotation(c, return_str, returns, names)) { goto error; } -- cgit v1.2.1 From c2c079435efc01bdac0900d0100cf1403f5e5a1a Mon Sep 17 00:00:00 2001 From: Stefan Krah Date: Mon, 27 Jul 2015 12:56:49 +0200 Subject: Fix refleak. --- Python/compile.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 027e3abe68..cfeab0fdfe 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1146,8 +1146,10 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) v = PyDict_GetItem(dict, t); if (!v) { - if (PyErr_Occurred()) + if (PyErr_Occurred()) { + Py_DECREF(t); return -1; + } arg = PyDict_Size(dict); v = PyLong_FromSsize_t(arg); if (!v) { -- cgit v1.2.1 From c5806bf732577121ab46511ae48f41ba3f38287e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 10 Sep 2015 21:02:39 -0700 Subject: compute stack effect of BUILD_MAP correctly (closes #25060) --- Python/compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index cfeab0fdfe..97bb12ee67 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -985,7 +985,7 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) case BUILD_MAP_UNPACK_WITH_CALL: return 1 - (oparg & 0xFF); case BUILD_MAP: - return 1; + return 1 - 2*oparg; case LOAD_ATTR: return 0; case COMPARE_OP: -- cgit v1.2.1