From 8fbf4fa9edcb9efd1ca5d650ed235eb4770dea3a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 6 Dec 2012 17:41:04 -0500 Subject: create NameConstant AST class for None, True, and False literals (closes #16619) --- Python/compile.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 3cf71ef09e..3e960ccbfe 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3194,12 +3194,18 @@ expr_constant(struct compiler *c, expr_ty e) case Name_kind: /* optimize away names that can't be reassigned */ id = PyUnicode_AsUTF8(e->v.Name.id); - if (strcmp(id, "True") == 0) return 1; - if (strcmp(id, "False") == 0) return 0; - if (strcmp(id, "None") == 0) return 0; - if (strcmp(id, "__debug__") == 0) - return ! c->c_optimize; - /* fall through */ + if (id && strcmp(id, "__debug__") == 0) + return !c->c_optimize; + return -1; + case NameConstant_kind: { + PyObject *o = e->v.NameConstant.value; + if (o == Py_None) + return 0; + else if (o == Py_True) + return 1; + else if (o == Py_False) + return 0; + } default: return -1; } @@ -3375,6 +3381,9 @@ compiler_visit_expr(struct compiler *c, expr_ty e) case Ellipsis_kind: ADDOP_O(c, LOAD_CONST, Py_Ellipsis, consts); break; + case NameConstant_kind: + ADDOP_O(c, LOAD_CONST, e->v.NameConstant.value, consts); + break; /* The following exprs can be assignment targets. */ case Attribute_kind: if (e->v.Attribute.ctx != AugStore) -- cgit v1.2.1 From 114832065bf0892650154c391093095d8d950c25 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 6 Dec 2012 17:49:58 -0500 Subject: assert than we never try to deal with True, False, or None as a name --- Python/compile.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 3e960ccbfe..8f876a6d0d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2635,6 +2635,10 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) if (!mangled) return 0; + assert(PyUnicode_CompareWithASCIIString(name, "None") && + PyUnicode_CompareWithASCIIString(name, "True") && + PyUnicode_CompareWithASCIIString(name, "False")); + op = 0; optype = OP_NAME; scope = PyST_GetScope(c->u->u_ste, mangled); -- cgit v1.2.1 From 3519d4fdaa0875b231d459d2bbe948aeb6761af3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 10 Feb 2013 09:29:59 -0500 Subject: evaluate positional defaults before keyword-only defaults (closes #16967) --- 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 8f876a6d0d..a0df40c323 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1565,6 +1565,8 @@ compiler_function(struct compiler *c, stmt_ty s) if (!compiler_decorators(c, decos)) return 0; + if (args->defaults) + VISIT_SEQ(c, expr, args->defaults); if (args->kwonlyargs) { int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, args->kw_defaults); @@ -1572,8 +1574,6 @@ compiler_function(struct compiler *c, stmt_ty s) return 0; kw_default_count = res; } - if (args->defaults) - VISIT_SEQ(c, expr, args->defaults); num_annotations = compiler_visit_annotations(c, args, returns); if (num_annotations < 0) return 0; -- cgit v1.2.1 From 7ca707eaa6c4fb73690a0ef904261a63fd0c6385 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 10 Feb 2013 09:48:22 -0500 Subject: evaluate lambda keyword-only defaults after positional defaults (#16967 again) --- 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 a0df40c323..61f35f82cd 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1794,14 +1794,14 @@ compiler_lambda(struct compiler *c, expr_ty e) return 0; } + if (args->defaults) + VISIT_SEQ(c, expr, args->defaults); if (args->kwonlyargs) { int res = compiler_visit_kwonlydefaults(c, args->kwonlyargs, args->kw_defaults); if (res < 0) return 0; kw_default_count = res; } - if (args->defaults) - VISIT_SEQ(c, expr, args->defaults); if (!compiler_enter_scope(c, name, COMPILER_SCOPE_FUNCTION, (void *)e, e->lineno)) return 0; -- cgit v1.2.1 From 7eadff200c3acb1286b95d417edfcc56cee617ee Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 18 Mar 2013 10:48:58 -0700 Subject: unify some ast.argument's attrs; change Attribute column offset (closes #16795) Patch from Sven Brauch. --- Python/compile.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 61f35f82cd..0aca8bd2e9 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1498,15 +1498,15 @@ compiler_visit_annotations(struct compiler *c, arguments_ty args, if (compiler_visit_argannotations(c, args->args, names)) goto error; - if (args->varargannotation && - compiler_visit_argannotation(c, args->vararg, - args->varargannotation, names)) + if (args->vararg && args->vararg->annotation && + compiler_visit_argannotation(c, args->vararg->arg, + args->vararg->annotation, names)) goto error; if (compiler_visit_argannotations(c, args->kwonlyargs, names)) goto error; - if (args->kwargannotation && - compiler_visit_argannotation(c, args->kwarg, - args->kwargannotation, names)) + if (args->kwarg && args->kwarg->annotation && + compiler_visit_argannotation(c, args->kwarg->arg, + args->kwarg->annotation, names)) goto error; if (!return_str) { -- cgit v1.2.1 From a2fc2ebe3d645e60d26996b51d8b33a1fe177d5c Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 30 Apr 2013 09:41:40 -0400 Subject: check local class namespace before reaching for cells (closes #17853) --- 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 52e8188d41..1ecbae8181 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -970,6 +970,7 @@ opcode_stack_effect(int opcode, int oparg) case LOAD_CLOSURE: return 1; case LOAD_DEREF: + case LOAD_CLASSDEREF: return 1; case STORE_DEREF: return -1; @@ -2677,7 +2678,9 @@ compiler_nameop(struct compiler *c, identifier name, expr_context_ty ctx) switch (optype) { case OP_DEREF: switch (ctx) { - case Load: op = LOAD_DEREF; break; + case Load: + op = (c->u->u_ste->ste_type == ClassBlock) ? LOAD_CLASSDEREF : LOAD_DEREF; + break; case Store: op = STORE_DEREF; break; case AugLoad: case AugStore: -- cgit v1.2.1 From f773ed5048253f3e3d86b28e47f8245c2542027c Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 15 May 2013 15:26:42 -0500 Subject: hide the __class__ closure from the class body (#12370) --- Python/compile.c | 64 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 15 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 1ecbae8181..24ff61f8a9 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -535,6 +535,37 @@ compiler_enter_scope(struct compiler *c, identifier name, compiler_unit_free(u); return 0; } + if (u->u_ste->ste_needs_class_closure) { + /* Cook up a implicit __class__ cell. */ + _Py_IDENTIFIER(__class__); + PyObject *tuple, *name, *zero; + int res; + assert(u->u_scope_type == COMPILER_SCOPE_CLASS); + assert(PyDict_Size(u->u_cellvars) == 0); + name = _PyUnicode_FromId(&PyId___class__); + if (!name) { + compiler_unit_free(u); + return 0; + } + tuple = PyTuple_Pack(2, name, Py_TYPE(name)); + if (!tuple) { + compiler_unit_free(u); + return 0; + } + zero = PyLong_FromLong(0); + if (!zero) { + Py_DECREF(tuple); + compiler_unit_free(u); + return 0; + } + res = PyDict_SetItem(u->u_cellvars, tuple, zero); + Py_DECREF(tuple); + Py_DECREF(zero); + if (res < 0) { + compiler_unit_free(u); + return 0; + } + } u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, PyDict_Size(u->u_cellvars)); @@ -1331,6 +1362,9 @@ compiler_mod(struct compiler *c, mod_ty mod) static int get_ref_type(struct compiler *c, PyObject *name) { + if (c->u->u_scope_type == COMPILER_SCOPE_CLASS && + !PyUnicode_CompareWithASCIIString(name, "__class__")) + return CELL; int scope = PyST_GetScope(c->u->u_ste, name); if (scope == 0) { char buf[350]; @@ -1704,24 +1738,24 @@ compiler_class(struct compiler *c, stmt_ty s) compiler_exit_scope(c); return 0; } - /* return the (empty) __class__ cell */ - str = PyUnicode_InternFromString("__class__"); - if (str == NULL) { - compiler_exit_scope(c); - return 0; - } - i = compiler_lookup_arg(c->u->u_cellvars, str); - Py_DECREF(str); - if (i == -1) { - /* This happens when nobody references the cell */ - PyErr_Clear(); - /* Return None */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); - } - else { + if (c->u->u_ste->ste_needs_class_closure) { + /* return the (empty) __class__ cell */ + str = PyUnicode_InternFromString("__class__"); + if (str == NULL) { + compiler_exit_scope(c); + return 0; + } + i = compiler_lookup_arg(c->u->u_cellvars, str); + Py_DECREF(str); + assert(i == 0); /* Return the cell where to store __class__ */ ADDOP_I(c, LOAD_CLOSURE, i); } + else { + assert(PyDict_Size(c->u->u_cellvars) == 0); + /* This happens when nobody references the cell. Return None. */ + ADDOP_O(c, LOAD_CONST, Py_None, consts); + } ADDOP_IN_SCOPE(c, RETURN_VALUE); /* create the code object */ co = assemble(c, 1); -- cgit v1.2.1 From df197a8dcb7f4aba4ba0e6b28f910cb28088549e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 16 May 2013 14:37:25 -0500 Subject: rather than passing locals to the class body, just execute the class body in the proper environment --- Python/compile.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 24ff61f8a9..65043e4396 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -893,8 +893,6 @@ opcode_stack_effect(int opcode, int oparg) return 7; case WITH_CLEANUP: return -1; /* XXX Sometimes more */ - case STORE_LOCALS: - return -1; case RETURN_VALUE: return -1; case IMPORT_STAR: @@ -1696,12 +1694,6 @@ compiler_class(struct compiler *c, stmt_ty s) Py_INCREF(s->v.ClassDef.name); Py_XDECREF(c->u->u_private); c->u->u_private = s->v.ClassDef.name; - /* force it to have one mandatory argument */ - c->u->u_argcount = 1; - /* load the first argument (__locals__) ... */ - ADDOP_I(c, LOAD_FAST, 0); - /* ... and store it into f_locals */ - ADDOP_IN_SCOPE(c, STORE_LOCALS); /* load (global) __name__ ... */ str = PyUnicode_InternFromString("__name__"); if (!str || !compiler_nameop(c, str, Load)) { @@ -4110,9 +4102,8 @@ compute_code_flags(struct compiler *c) { PySTEntryObject *ste = c->u->u_ste; int flags = 0, n; - if (ste->ste_type != ModuleBlock) - flags |= CO_NEWLOCALS; if (ste->ste_type == FunctionBlock) { + flags |= CO_NEWLOCALS; if (!ste->ste_unoptimized) flags |= CO_OPTIMIZED; if (ste->ste_nested) -- cgit v1.2.1 From 3be142c560917a899230a0695dccb1052bda0f3a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 16 May 2013 22:17:17 +0200 Subject: fix compilation on Windows --- Python/compile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index 65043e4396..4fc7575926 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1360,10 +1360,11 @@ compiler_mod(struct compiler *c, mod_ty mod) static int get_ref_type(struct compiler *c, PyObject *name) { + int scope; if (c->u->u_scope_type == COMPILER_SCOPE_CLASS && !PyUnicode_CompareWithASCIIString(name, "__class__")) return CELL; - int scope = PyST_GetScope(c->u->u_ste, name); + scope = PyST_GetScope(c->u->u_ste, name); if (scope == 0) { char buf[350]; PyOS_snprintf(buf, sizeof(buf), -- cgit v1.2.1 From 3d0056f5b1d38eeecacd4e905a25d9ff0130e322 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 11 Jul 2013 22:50:45 +0200 Subject: Issue #18408: Fix compiler_import() to handle PyUnicode_Substring() failure properly --- 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 4fc7575926..d11e3abeaa 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -2316,8 +2316,11 @@ compiler_import(struct compiler *c, stmt_ty s) identifier tmp = alias->name; Py_ssize_t dot = PyUnicode_FindChar( alias->name, '.', 0, PyUnicode_GET_LENGTH(alias->name), 1); - if (dot != -1) + if (dot != -1) { tmp = PyUnicode_Substring(alias->name, 0, dot); + if (tmp == NULL) + return 0; + } r = compiler_nameop(c, tmp, Store); if (dot != -1) { Py_DECREF(tmp); -- cgit v1.2.1 From c36bfc1c99c6dffff8cb89c723001902d721ff97 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 26 Aug 2013 22:28:21 +0200 Subject: Close #11619: The parser and the import machinery do not encode Unicode filenames anymore on Windows. --- Python/compile.c | 57 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 20 deletions(-) (limited to 'Python/compile.c') diff --git a/Python/compile.c b/Python/compile.c index d11e3abeaa..71a0930a8e 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -149,8 +149,7 @@ handled by the symbol analysis pass. */ struct compiler { - const char *c_filename; - PyObject *c_filename_obj; + PyObject *c_filename; struct symtable *c_st; PyFutureFeatures *c_future; /* pointer to module's __future__ */ PyCompilerFlags *c_flags; @@ -288,8 +287,8 @@ compiler_init(struct compiler *c) } PyCodeObject * -PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags, - int optimize, PyArena *arena) +PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, + int optimize, PyArena *arena) { struct compiler c; PyCodeObject *co = NULL; @@ -304,12 +303,10 @@ PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags, if (!compiler_init(&c)) return NULL; + Py_INCREF(filename); c.c_filename = filename; - c.c_filename_obj = PyUnicode_DecodeFSDefault(filename); - if (!c.c_filename_obj) - goto finally; c.c_arena = arena; - c.c_future = PyFuture_FromAST(mod, filename); + c.c_future = PyFuture_FromASTObject(mod, filename); if (c.c_future == NULL) goto finally; if (!flags) { @@ -323,7 +320,7 @@ PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags, c.c_optimize = (optimize == -1) ? Py_OptimizeFlag : optimize; c.c_nestlevel = 0; - c.c_st = PySymtable_Build(mod, filename, c.c_future); + c.c_st = PySymtable_BuildObject(mod, filename, c.c_future); if (c.c_st == NULL) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_SystemError, "no symtable"); @@ -338,6 +335,21 @@ PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags, return co; } +PyCodeObject * +PyAST_CompileEx(mod_ty mod, const char *filename_str, PyCompilerFlags *flags, + int optimize, PyArena *arena) +{ + PyObject *filename; + PyCodeObject *co; + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + return NULL; + co = PyAST_CompileObject(mod, filename, flags, optimize, arena); + Py_DECREF(filename); + return co; + +} + PyCodeObject * PyNode_Compile(struct _node *n, const char *filename) { @@ -360,8 +372,7 @@ compiler_free(struct compiler *c) PySymtable_Free(c->c_st); if (c->c_future) PyObject_Free(c->c_future); - if (c->c_filename_obj) - Py_DECREF(c->c_filename_obj); + Py_XDECREF(c->c_filename); Py_DECREF(c->c_stack); } @@ -1368,12 +1379,11 @@ get_ref_type(struct compiler *c, PyObject *name) if (scope == 0) { char buf[350]; PyOS_snprintf(buf, sizeof(buf), - "unknown scope for %.100s in %.100s(%s) in %s\n" + "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), - c->c_filename, PyObject_REPR(c->u->u_ste->ste_symbols), PyObject_REPR(c->u->u_varnames), PyObject_REPR(c->u->u_names) @@ -2411,6 +2421,7 @@ compiler_assert(struct compiler *c, stmt_ty s) { static PyObject *assertion_error = NULL; basicblock *end; + PyObject* msg; if (c->c_optimize) return 1; @@ -2421,11 +2432,17 @@ compiler_assert(struct compiler *c, stmt_ty s) } if (s->v.Assert.test->kind == Tuple_kind && asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) { - const char* msg = - "assertion is always true, perhaps remove parentheses?"; - if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, c->c_filename, - c->u->u_lineno, NULL, NULL) == -1) + msg = PyUnicode_FromString("assertion is always true, " + "perhaps remove parentheses?"); + 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); } VISIT(c, expr, s->v.Assert.test); end = compiler_new_block(c); @@ -3593,12 +3610,12 @@ compiler_error(struct compiler *c, const char *errstr) PyObject *loc; PyObject *u = NULL, *v = NULL; - loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); + loc = PyErr_ProgramTextObject(c->c_filename, c->u->u_lineno); if (!loc) { Py_INCREF(Py_None); loc = Py_None; } - u = Py_BuildValue("(OiiO)", c->c_filename_obj, c->u->u_lineno, + u = Py_BuildValue("(OiiO)", c->c_filename, c->u->u_lineno, c->u->u_col_offset, loc); if (!u) goto exit; @@ -4188,7 +4205,7 @@ makecode(struct compiler *c, struct assembler *a) nlocals, stackdepth(c), flags, bytecode, consts, names, varnames, freevars, cellvars, - c->c_filename_obj, c->u->u_name, + c->c_filename, c->u->u_name, c->u->u_firstlineno, a->a_lnotab); error: -- cgit v1.2.1